Meer cleanup, chunkstream implemented
This commit is contained in:
parent
a4fa349028
commit
6bff69af30
5 changed files with 277 additions and 107 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ignore object files and nonsense like that
|
||||
*.[oa]
|
||||
Client_PLS
|
||||
Server_PLS
|
||||
Connector_RTMP
|
||||
*~
|
||||
|
24
RTMP/Connector/Makefile
Normal file
24
RTMP/Connector/Makefile
Normal file
|
@ -0,0 +1,24 @@
|
|||
SRC = main.cpp
|
||||
OBJ = $(SRC:.cpp=.o)
|
||||
OUT = Connector_RTMP
|
||||
INCLUDES =
|
||||
CCFLAGS = -Wall -Wextra -funsigned-char -g
|
||||
CC = $(CROSS)g++
|
||||
LD = $(CROSS)ld
|
||||
AR = $(CROSS)ar
|
||||
LIBS =
|
||||
.SUFFIXES: .cpp
|
||||
.PHONY: clean default
|
||||
default: $(OUT)
|
||||
.cpp.o:
|
||||
$(CC) $(INCLUDES) $(CCFLAGS) $(LIBS) -c $< -o $@
|
||||
$(OUT): $(OBJ) handshake.cpp chunkstream.cpp
|
||||
$(CC) $(LIBS) -o $(OUT) $(OBJ)
|
||||
clean:
|
||||
rm -rf $(OBJ) $(OUT) Makefile.bak *~
|
||||
run-test: $(OUT)
|
||||
rm -rf ./meh
|
||||
mkfifo ./meh
|
||||
nc -o test -l -p 1935 -e './Connector_RTMP 2>./meh'
|
||||
run-cat:
|
||||
cat < ./meh
|
138
RTMP/Connector/chunkstream.cpp
Normal file
138
RTMP/Connector/chunkstream.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
struct chunkpack {
|
||||
unsigned char chunktype;
|
||||
unsigned int cs_id;
|
||||
unsigned int timestamp;
|
||||
unsigned int len;
|
||||
unsigned int real_len;
|
||||
unsigned int len_left;
|
||||
unsigned char msg_type_id;
|
||||
unsigned int msg_stream_id;
|
||||
unsigned char * data;
|
||||
};//chunkpack
|
||||
|
||||
unsigned int chunk_rec_max = 128;
|
||||
|
||||
//clean a chunk so that it may be re-used without memory leaks
|
||||
void scrubChunk(struct chunkpack c){
|
||||
if (c.data){free(c.data);}
|
||||
c.data = 0;
|
||||
c.real_len = 0;
|
||||
}//scrubChunk
|
||||
|
||||
//get a chunk from standard input
|
||||
struct chunkpack getChunk(struct chunkpack prev){
|
||||
struct chunkpack ret;
|
||||
unsigned char temp;
|
||||
fread(&(ret.chunktype), 1, 1, stdin);
|
||||
fprintf(stderr, "Got chunkstream ID %hhi\n", ret.chunktype & 0x3F);
|
||||
switch (ret.chunktype & 0x3F){
|
||||
case 0:
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.cs_id = temp + 64;
|
||||
break;
|
||||
case 1:
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.cs_id = temp + 64;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.cs_id += temp * 256;
|
||||
break;
|
||||
default:
|
||||
ret.cs_id = ret.chunktype & 0x3F;
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "Got a type %hhi chunk\n", ret.chunktype & 0xC0);
|
||||
switch (ret.chunktype & 0xC0){
|
||||
case 0:
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp = temp*256*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp += temp*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp += temp;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.len = temp*256*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.len += temp*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.len += temp;
|
||||
ret.len_left = 0;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.msg_type_id = temp;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.msg_stream_id = temp*256*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.msg_stream_id += temp*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.msg_stream_id += temp;
|
||||
break;
|
||||
case 1:
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp = temp*256*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp += temp*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp += temp;
|
||||
ret.timestamp += prev.timestamp;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.len = temp*256*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.len += temp*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.len += temp;
|
||||
ret.len_left = 0;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.msg_type_id = temp;
|
||||
ret.msg_stream_id = prev.msg_stream_id;
|
||||
break;
|
||||
case 2:
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp = temp*256*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp += temp*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp += temp;
|
||||
ret.timestamp += prev.timestamp;
|
||||
ret.len = prev.len;
|
||||
ret.len_left = prev.len_left;
|
||||
ret.msg_type_id = prev.msg_type_id;
|
||||
ret.msg_stream_id = prev.msg_stream_id;
|
||||
break;
|
||||
case 3:
|
||||
ret.timestamp = prev.timestamp;
|
||||
ret.len = prev.len;
|
||||
ret.len_left = prev.len_left;
|
||||
ret.msg_type_id = prev.msg_type_id;
|
||||
ret.msg_stream_id = prev.msg_stream_id;
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "Timestamp: %i\n", ret.timestamp);
|
||||
fprintf(stderr, "Length: %i\n", ret.len);
|
||||
fprintf(stderr, "Message type ID: %hhi\n", ret.msg_type_id);
|
||||
fprintf(stderr, "Message stream ID: %i\n", ret.msg_stream_id);
|
||||
if (ret.len_left > 0){
|
||||
ret.real_len = ret.len_left;
|
||||
ret.len_left -= ret.real_len;
|
||||
}else{
|
||||
ret.real_len = ret.len;
|
||||
}
|
||||
if (ret.real_len > chunk_rec_max){
|
||||
ret.len_left += ret.real_len - chunk_rec_max;
|
||||
}
|
||||
if (ret.timestamp == 0x00ffffff){
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp = temp*256*256*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp += temp*256*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp += temp*256;
|
||||
fread(&temp, 1, 1, stdin);
|
||||
ret.timestamp += temp;
|
||||
}
|
||||
if (ret.real_len > 0){
|
||||
ret.data = (unsigned char*)malloc(ret.real_len);
|
||||
fread(ret.data, 1, ret.real_len, stdin);
|
||||
}else{
|
||||
ret.data = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
40
RTMP/Connector/handshake.cpp
Normal file
40
RTMP/Connector/handshake.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
struct Handshake {
|
||||
char Time[4];
|
||||
char Zero[4];
|
||||
char Random[1528];
|
||||
};//Handshake
|
||||
|
||||
void doHandshake(){
|
||||
srand(time(NULL));
|
||||
char Version;
|
||||
Handshake Client;
|
||||
Handshake Server;
|
||||
/** Read C0 **/
|
||||
fread(&(Version), 1, 1, stdin);
|
||||
/** Read C1 **/
|
||||
fread(Client.Time, 1, 4, stdin);
|
||||
fread(Client.Zero, 1, 4, stdin);
|
||||
fread(Client.Random, 1, 1528, stdin);
|
||||
/** Build S1 Packet **/
|
||||
Server.Time[0] = 0; Server.Time[1] = 0; Server.Time[2] = 0; Server.Time[3] = 0;
|
||||
Server.Zero[0] = 0; Server.Zero[1] = 0; Server.Zero[2] = 0; Server.Zero[3] = 0;
|
||||
for (int i = 0; i < 1528; i++){Server.Random[i] = (rand() % 256);}
|
||||
/** Send S0 **/
|
||||
fwrite(&(Version), 1, 1, stdout);
|
||||
/** Send S1 **/
|
||||
fwrite(Server.Time, 1, 4, stdout);
|
||||
fwrite(Server.Zero, 1, 4, stdout);
|
||||
fwrite(Server.Random, 1, 1528, stdout);
|
||||
/** Flush output, just for certainty **/
|
||||
fflush(stdout);
|
||||
/** Send S2 **/
|
||||
fwrite(Client.Time, 1, 4, stdout);
|
||||
fwrite(Client.Time, 1, 4, stdout);
|
||||
fwrite(Client.Random, 1, 1528, stdout);
|
||||
/** Flush, necessary in order to work **/
|
||||
fflush(stdout);
|
||||
/** Read and discard C2 **/
|
||||
fread(Client.Time, 1, 4, stdin);
|
||||
fread(Client.Zero, 1, 4, stdin);
|
||||
fread(Client.Random, 1, 1528, stdin);
|
||||
}//doHandshake
|
|
@ -2,116 +2,77 @@
|
|||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include "handshake.cpp" //handshaking
|
||||
#include "chunkstream.cpp" //chunkstream decoding
|
||||
|
||||
struct Handshake_0 {
|
||||
char Version;
|
||||
};//Handshake_0
|
||||
int main(){
|
||||
chunkpack prev, next;
|
||||
doHandshake();
|
||||
std::cerr << "Handshake completed" << std::endl;
|
||||
|
||||
struct Handshake_1 {
|
||||
char Time[4];
|
||||
char Zero[4];
|
||||
char Random[1528];
|
||||
};//Handshake_1
|
||||
|
||||
struct Handshake_2 {
|
||||
char Time[4];
|
||||
char Time2[4];
|
||||
char Random_Echo[1528];
|
||||
};//Handshake_2
|
||||
|
||||
int main( ) {
|
||||
srand( time( NULL ) );
|
||||
char next;
|
||||
char chunk_header[14];//Space to any chunk header imaginable. Basic header max 3, Chunck msg header max 11
|
||||
char extended_timestamp[4];//Not always used, so not included in header space.
|
||||
int chunkIDlenght;
|
||||
int chunkstream_id;
|
||||
Handshake_0 Client_0;
|
||||
Handshake_1 Client_1;
|
||||
Handshake_2 Client_2;
|
||||
Handshake_1 Server_1;
|
||||
Handshake_2 Server_2;
|
||||
/** Start Handshake **/
|
||||
|
||||
/** Read C0 **/
|
||||
std::cin >> Client_0.Version;
|
||||
/** Read C1 **/
|
||||
fread( Client_1.Time, 1, 4, stdin);
|
||||
fread( Client_1.Zero, 1, 4, stdin);
|
||||
fread( Client_1.Random, 1, 1528, stdin);
|
||||
/** Build S1 Packet **/
|
||||
Server_1.Time[0] = 0; Server_1.Time[1] = 0; Server_1.Time[2] = 0; Server_1.Time[3] = 4;
|
||||
Server_1.Zero[0] = 0; Server_1.Zero[1] = 0; Server_1.Zero[2] = 0; Server_1.Zero[3] = 0;
|
||||
for (int i = 0; i < 1528; i++) { Server_1.Random[i] = (rand() % 256); }
|
||||
/** Send S0 **/
|
||||
std::cout << Client_0.Version;
|
||||
/** Send S1 **/
|
||||
std::cout << Server_1.Time[0];
|
||||
std::cout << Server_1.Time[1];
|
||||
std::cout << Server_1.Time[2];
|
||||
std::cout << Server_1.Time[3];
|
||||
std::cout << Server_1.Zero[0];
|
||||
std::cout << Server_1.Zero[1];
|
||||
std::cout << Server_1.Zero[2];
|
||||
std::cout << Server_1.Zero[3];
|
||||
for (int i = 0; i < 1528; i++) {
|
||||
std::cout << Server_1.Random[i];
|
||||
}
|
||||
/** Flush output, just for certainty **/
|
||||
std::cout << std::flush;
|
||||
/** Build S2 Packet **/
|
||||
for (int i = 0; i < 4; i++ ) {
|
||||
Server_2.Time[i] = Client_1.Time[i];
|
||||
Server_2.Time2[i] = Server_2.Time[i];
|
||||
}
|
||||
Server_2.Time2[3] = Server_2.Time2[3] + 1;
|
||||
/** Send S2 **/
|
||||
std::cout << Server_2.Time[0];
|
||||
std::cout << Server_2.Time[1];
|
||||
std::cout << Server_2.Time[2];
|
||||
std::cout << Server_2.Time[3];
|
||||
std::cout << Server_2.Time2[0];
|
||||
std::cout << Server_2.Time2[1];
|
||||
std::cout << Server_2.Time2[2];
|
||||
std::cout << Server_2.Time2[3];
|
||||
for (int i = 0; i < 1528; i++) {
|
||||
std::cout << Client_1.Random[i];
|
||||
}
|
||||
/** Flush, necessary in order to work **/
|
||||
std::cout << std::flush;
|
||||
/** Read C2 **/
|
||||
fread( Client_2.Time, 1, 4, stdin);
|
||||
fread( Client_2.Time2, 1, 4, stdin);
|
||||
fread( Client_2.Random_Echo, 1, 1528, stdin);
|
||||
|
||||
/** Handshake done, continue with connect command **/
|
||||
|
||||
int chunkIDlength = 0;
|
||||
next = std::cin.peek();
|
||||
if (next > 63 || next == 2) { exit(1); }//Connect command has a 11 byte header, ALWAYS, maximum value of first byte is then 63
|
||||
if (next <= 63 && next >= 3) {//1 byte chunkstream ID
|
||||
fread ( chunk_header, 1, 12, stdin );
|
||||
chunkIDlength = 1;
|
||||
} else if ((int) next == 0 ) {//2 bytes chunkstream ID
|
||||
fread ( chunk_header, 1, 13, stdin );
|
||||
chunkIDlength = 2;
|
||||
} else if ((int) next == 1 ) {//3 bytes chunkstream ID
|
||||
fread ( chunk_header, 1, 14, stdin );
|
||||
chunkIDlength = 3;
|
||||
}
|
||||
switch(chunkIDlength) {
|
||||
case 1: chunkstream_id = (int)chunk_header[0]; break;
|
||||
case 2: chunkstream_id = (int)chunk_header[1] + 64; break;
|
||||
case 3: chunkstream_id = ((int)chunk_header[2] * 256) + (int)chunk_header[1] + 64; break;
|
||||
default: exit(1); break;//Something went wrong
|
||||
}
|
||||
|
||||
if ( chunk_header[chunkIDlength] == 0xFF && chunk_header[chunkIDlength+1] == 0xFF && chunk_header[chunkIDlength+2] == 0xFF ) {
|
||||
fread ( extended_timestamp, 1, 4, stdin); //read extended timestamp if 3-byte timestamp equals 0xFFFFFF
|
||||
} else {//set extended timestamp to 0
|
||||
extended_timestamp[0] = 0; extended_timestamp[1] = 0; extended_timestamp[2] = 0; extended_timestamp[3] = 0;
|
||||
prev.len = 0;
|
||||
prev.data = 0;
|
||||
while (!feof(stdin)){
|
||||
next = getChunk(prev);
|
||||
if (next.cs_id == 2 && next.msg_stream_id == 0){
|
||||
fprintf(stderr, "Received protocol message. (cs_id 2, stream id 0)\nContents:\n");
|
||||
fwrite(next.data, 1, next.real_len, stderr);
|
||||
fflush(stderr);
|
||||
}
|
||||
switch (next.msg_type_id){
|
||||
case 1:
|
||||
fprintf(stderr, "CTRL: Set chunk size\n");
|
||||
break;
|
||||
case 2:
|
||||
fprintf(stderr, "CTRL: Abort message\n");
|
||||
break;
|
||||
case 3:
|
||||
fprintf(stderr, "CTRL: Acknowledgement\n");
|
||||
break;
|
||||
case 4:
|
||||
fprintf(stderr, "CTRL: User control message\n");
|
||||
break;
|
||||
case 5:
|
||||
fprintf(stderr, "CTRL: Window size\n");
|
||||
break;
|
||||
case 6:
|
||||
fprintf(stderr, "CTRL: Set peer bandwidth\n");
|
||||
break;
|
||||
case 8:
|
||||
fprintf(stderr, "Received audio data\n");
|
||||
break;
|
||||
case 9:
|
||||
fprintf(stderr, "Received video data\n");
|
||||
break;
|
||||
case 15:
|
||||
fprintf(stderr, "Received AFM3 data message\n");
|
||||
break;
|
||||
case 16:
|
||||
fprintf(stderr, "Received AFM3 shared object\n");
|
||||
break;
|
||||
case 17:
|
||||
fprintf(stderr, "Received AFM3 command message\n");
|
||||
break;
|
||||
case 18:
|
||||
fprintf(stderr, "Received AFM0 data message\n");
|
||||
break;
|
||||
case 19:
|
||||
fprintf(stderr, "Received AFM0 shared object\n");
|
||||
break;
|
||||
case 20:
|
||||
fprintf(stderr, "Received AFM0 command message\n");
|
||||
break;
|
||||
case 22:
|
||||
fprintf(stderr, "Received aggregate message\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown chunk received!\n");
|
||||
break;
|
||||
}
|
||||
scrubChunk(prev);
|
||||
prev = next;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}//main
|
||||
|
|
Loading…
Add table
Reference in a new issue