From 273f30784be87e94724474a485a9f102164c43b4 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Wed, 17 Nov 2010 01:05:36 +0100 Subject: [PATCH 1/7] Werkende RTMP connector! WHEEEE! Also, RTMPf weggegooit. Er is geen ruimte voor faal in dit bedrijf! --- Buffer/main.cpp | 8 +- Buffer/playh264.sh | 2 +- Connector_RTMP/Makefile | 2 +- Connector_RTMP/amf.cpp | 2 +- Connector_RTMP/chunkstream.cpp | 2 +- Connector_RTMP/crypto.cpp | 2 +- Connector_RTMP/handshake.cpp | 4 +- Connector_RTMP/main.cpp | 129 ++++---- Connector_RTMP/parsechunks.cpp | 53 ++-- Connector_RTMPf/Makefile | 23 -- Connector_RTMPf/amf.cpp | 285 ------------------ Connector_RTMPf/chunkstream.cpp | 501 ------------------------------- Connector_RTMPf/crypto.cpp | 506 -------------------------------- Connector_RTMPf/crypto.h | 45 --- Connector_RTMPf/flv_sock.cpp | 30 -- Connector_RTMPf/handshake.cpp | 137 --------- Connector_RTMPf/main.cpp | 119 -------- Connector_RTMPf/parsechunks.cpp | 246 ---------------- Makefile | 3 - PLS | 15 - util/ddv_socket.cpp | 16 +- util/flv_sock.cpp | 8 +- 22 files changed, 123 insertions(+), 2015 deletions(-) delete mode 100644 Connector_RTMPf/Makefile delete mode 100644 Connector_RTMPf/amf.cpp delete mode 100644 Connector_RTMPf/chunkstream.cpp delete mode 100644 Connector_RTMPf/crypto.cpp delete mode 100644 Connector_RTMPf/crypto.h delete mode 100644 Connector_RTMPf/flv_sock.cpp delete mode 100644 Connector_RTMPf/handshake.cpp delete mode 100644 Connector_RTMPf/main.cpp delete mode 100644 Connector_RTMPf/parsechunks.cpp diff --git a/Buffer/main.cpp b/Buffer/main.cpp index 8330108f..638524cb 100644 --- a/Buffer/main.cpp +++ b/Buffer/main.cpp @@ -70,7 +70,7 @@ int main( int argc, char * argv[] ) { //invalidate the current buffer ringbuf[current_buffer]->number = -1; if ((epoll_wait(poller, events, 1, 100) > 0) && FLV_GetPacket(ringbuf[current_buffer]->FLV)){ - loopcount ++; + loopcount++; packtype = ringbuf[current_buffer]->FLV->data[0]; //store metadata, if available if (packtype == 0x12){ @@ -113,12 +113,14 @@ int main( int argc, char * argv[] ) { } //on keyframe set start point if (packtype == 0x09){ - if (((ringbuf[current_buffer]->FLV->data[11] & 0xf0) >> 4) == 1){lastproper = current_buffer;} + if (((ringbuf[current_buffer]->FLV->data[11] & 0xf0) >> 4) == 1){ + lastproper = current_buffer; + } } //keep track of buffers + ringbuf[current_buffer]->number = loopcount; current_buffer++; current_buffer %= buffers; - ringbuf[current_buffer]->number = loopcount; } //check for new connections, accept them if there are any diff --git a/Buffer/playh264.sh b/Buffer/playh264.sh index cde1f2fd..c50fc61e 100755 --- a/Buffer/playh264.sh +++ b/Buffer/playh264.sh @@ -5,5 +5,5 @@ #ffmpeg -y -i "$1" -ar 44100 -vcodec libx264 -b 1000k -g 150 -r 20 -f flv - | ./Buffer 500 -ffmpeg -i "$1" -re -acodec aac -ar 11025 -vcodec libx264 -b 700k -vpre ultrafast -refs 1 -bf 0 -g 150 -f flv - 2> /dev/null | ./Buffer 500 +ffmpeg -i "$1" -re -acodec aac -ar 11025 -vcodec libx264 -b 700k -vpre ultrafast -refs 1 -bf 0 -g 150 -f flv - 2> /dev/null | ./Buffer 500 $2 diff --git a/Connector_RTMP/Makefile b/Connector_RTMP/Makefile index 1edeaee9..8a32051b 100644 --- a/Connector_RTMP/Makefile +++ b/Connector_RTMP/Makefile @@ -11,7 +11,7 @@ LIBS = -lssl -lcrypto .PHONY: clean default default: $(OUT) .cpp.o: - $(CC) $(INCLUDES) $(CCFLAGS) $(LIBS) -c $< -o $@ + $(CC) $(INCLUDES) $(CCFLAGS) -c $< -o $@ $(OUT): $(OBJ) chunkstream.cpp parsechunks.cpp handshake.cpp crypto.cpp amf.cpp $(CC) $(LIBS) -o $(OUT) $(OBJ) clean: diff --git a/Connector_RTMP/amf.cpp b/Connector_RTMP/amf.cpp index 70aab059..794ae577 100644 --- a/Connector_RTMP/amf.cpp +++ b/Connector_RTMP/amf.cpp @@ -270,7 +270,7 @@ AMFType parseOneAMF(const unsigned char *& data, unsigned int &len, unsigned int return ret; } break; } - #ifdef DEBUG + #if DEBUG >= 2 fprintf(stderr, "Error: Unimplemented AMF type %hhx - returning.\n", data[i]); #endif return AMFType("error", (unsigned char)0xFF); diff --git a/Connector_RTMP/chunkstream.cpp b/Connector_RTMP/chunkstream.cpp index 8edf2016..d27cbd45 100644 --- a/Connector_RTMP/chunkstream.cpp +++ b/Connector_RTMP/chunkstream.cpp @@ -457,7 +457,7 @@ chunkpack * AddChunkPart(chunkpack newchunk){ p = it->second; tmpdata = (unsigned char*)realloc(p->data, p->real_len + newchunk.real_len); if (tmpdata == 0){ - #ifdef DEBUG + #if DEBUG >= 1 fprintf(stderr, "Error allocating memory!\n"); #endif return 0; diff --git a/Connector_RTMP/crypto.cpp b/Connector_RTMP/crypto.cpp index 9f62e5ce..bc1e616c 100644 --- a/Connector_RTMP/crypto.cpp +++ b/Connector_RTMP/crypto.cpp @@ -497,7 +497,7 @@ bool ValidateClientScheme(uint8_t * pBuffer, uint8_t scheme) { uint8_t *pTempHash = new uint8_t[512]; HMACsha256(pTempBuffer, 1536 - 32, genuineFPKey, 30, pTempHash); bool result = (memcmp(pBuffer+clientDigestOffset, pTempHash, 32) == 0); - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Client scheme validation %hhi %s\n", scheme, result?"success":"failed"); #endif delete[] pTempBuffer; diff --git a/Connector_RTMP/handshake.cpp b/Connector_RTMP/handshake.cpp index a8461a83..3b674b35 100644 --- a/Connector_RTMP/handshake.cpp +++ b/Connector_RTMP/handshake.cpp @@ -69,14 +69,14 @@ bool doHandshake(){ for (int i = 8; i < 3072; ++i){Server[i] = versionstring[i%13];}//"random" data bool encrypted = (Version == 6); - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Handshake version is %hhi\n", Version); #endif uint8_t _validationScheme = 5; if (ValidateClientScheme(Client, 0)) _validationScheme = 0; if (ValidateClientScheme(Client, 1)) _validationScheme = 1; - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Handshake type is %hhi, encryption is %s\n", _validationScheme, encrypted?"on":"off"); #endif diff --git a/Connector_RTMP/main.cpp b/Connector_RTMP/main.cpp index fd0d2ae0..70326938 100644 --- a/Connector_RTMP/main.cpp +++ b/Connector_RTMP/main.cpp @@ -1,4 +1,10 @@ -#undef DEBUG +//debugging level 0 = nothing +//debugging level 1 = critical errors +//debugging level 2 = errors +//debugging level 3 = status information +//debugging level 4 = extremely verbose status information +#define DEBUG 3 + #include #include #include @@ -27,6 +33,12 @@ int server_socket = 0; void termination_handler (int signum){ if (server_socket == 0) return; + switch (signum){ + case SIGINT: break; + case SIGHUP: break; + case SIGTERM: break; + default: return; break; + } close(server_socket); server_socket = 0; } @@ -41,9 +53,16 @@ int main(int argc, char ** argv){ sigaction (SIGHUP, &new_action, NULL); sigaction (SIGTERM, &new_action, NULL); - server_socket = DDV_Listen(1936); - if ((argc < 2) || (argv[1] == "nd")){ - if (server_socket > 0){daemon(1, 0);}else{return 1;} + server_socket = DDV_Listen(1935); + fprintf(stderr, "Made a listening socket on port 1936..."); + if ((argc < 2) || (strcmp(argv[1], "nd") != 0)){ + if (server_socket > 0){ + daemon(1, 0); + fprintf(stderr, "Going into background mode..."); + }else{ + fprintf(stderr, "Error: could not make listening socket"); + return 1; + } } int status; while (server_socket > 0){ @@ -54,7 +73,7 @@ int main(int argc, char ** argv){ if (myid == 0){ break; }else{ - printf("Spawned new process %i for handling socket %i\n", (int)myid, CONN_fd); + fprintf(stderr, "Spawned new process %i for handling socket %i\n", (int)myid, CONN_fd); } } } @@ -71,23 +90,16 @@ int main(int argc, char ** argv){ //first timestamp set firsttime = getNowMS(); - #ifdef DEBUG - fprintf(stderr, "Doing handshake...\n"); - #endif if (doHandshake()){ - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Handshake succcess!\n"); #endif }else{ - #ifdef DEBUG + #if DEBUG >= 1 fprintf(stderr, "Handshake fail!\n"); #endif return 0; } - #ifdef DEBUG - fprintf(stderr, "Starting processing...\n"); - #endif - int retval; int poller = epoll_create(1); @@ -104,10 +116,17 @@ int main(int argc, char ** argv){ while (!socketError && !All_Hell_Broke_Loose){ //only parse input if available or not yet init'ed //rightnow = getNowMS(); - retval = epoll_wait(poller, events, 1, 0); - if ((retval > 0) || !ready4data || (snd_cnt - snd_window_at >= snd_window_size)){ - if (DDV_ready(CONN_fd)){ - parseChunk(); + retval = epoll_wait(poller, events, 1, 1); + if ((retval > 0) || !ready4data){// || (snd_cnt - snd_window_at >= snd_window_size) + switch (DDV_ready(CONN_fd)){ + case 0: + socketError = true; + #if DEBUG >= 1 + fprintf(stderr, "User socket is disconnected.\n"); + #endif + break; + case -1: break;//not ready yet + default: parseChunk(); break; } } if (ready4data){ @@ -115,47 +134,57 @@ int main(int argc, char ** argv){ //we are ready, connect the socket! ss = DDV_OpenUnix(streamname); if (ss <= 0){ - #ifdef DEBUG + #if DEBUG >= 1 fprintf(stderr, "Could not connect to server!\n"); #endif - return 0; + socketError = 1; + break; } ev.events = EPOLLIN; ev.data.fd = ss; epoll_ctl(sspoller, EPOLL_CTL_ADD, ss, &ev); - #ifdef DEBUG + #if DEBUG >= 3 fprintf(stderr, "Everything connected, starting to send video data...\n"); #endif inited = true; } - retval = epoll_wait(poller, events, 1, 50); - if (DDV_ready(ss)){ - if (FLV_GetPacket(tag, ss)){//able to read a full packet? - ts = tag->data[7] * 256*256*256; - ts += tag->data[4] * 256*256; - ts += tag->data[5] * 256; - ts += tag->data[6]; - if (ts != 0){ - if (fts == 0){fts = ts;ftst = getNowMS();} - ts -= fts; - tag->data[7] = ts / (256*256*256); - tag->data[4] = ts / (256*256); - tag->data[5] = ts / 256; - tag->data[6] = ts % 256; - ts += ftst; - }else{ - ftst = getNowMS(); - tag->data[7] = ftst / (256*256*256); - tag->data[4] = ftst / (256*256); - tag->data[5] = ftst / 256; - tag->data[6] = ftst % 256; - } - SendMedia((unsigned char)tag->data[0], (unsigned char *)tag->data+11, tag->len-15, ts); - #ifdef DEBUG - fprintf(stderr, "Sent a tag to %i\n", CONN_fd); + retval = epoll_wait(poller, events, 1, 1); + switch (DDV_ready(ss)){ + case 0: + socketError = true; + #if DEBUG >= 1 + fprintf(stderr, "Source socket is disconnected.\n"); #endif - } + break; + case -1: break;//not ready yet + default: + if (FLV_GetPacket(tag, ss)){//able to read a full packet? + ts = tag->data[7] * 256*256*256; + ts += tag->data[4] * 256*256; + ts += tag->data[5] * 256; + ts += tag->data[6]; + if (ts != 0){ + if (fts == 0){fts = ts;ftst = getNowMS();} + ts -= fts; + tag->data[7] = ts / (256*256*256); + tag->data[4] = ts / (256*256); + tag->data[5] = ts / 256; + tag->data[6] = ts % 256; + ts += ftst; + }else{ + ftst = getNowMS(); + tag->data[7] = ftst / (256*256*256); + tag->data[4] = ftst / (256*256); + tag->data[5] = ftst / 256; + tag->data[6] = ftst % 256; + } + SendMedia((unsigned char)tag->data[0], (unsigned char *)tag->data+11, tag->len-15, ts); + #if DEBUG >= 4 + fprintf(stderr, "Sent a tag to %i\n", CONN_fd); + #endif + } + break; } } //send ACK if we received a whole window @@ -164,10 +193,10 @@ int main(int argc, char ** argv){ SendCTL(3, rec_cnt);//send ack (msg 3) } } - //#ifdef DEBUG - if (socketError){fprintf(stderr, "socketError\n");} + close(CONN_fd); + #if DEBUG >= 1 if (All_Hell_Broke_Loose){fprintf(stderr, "All Hell Broke Loose\n");} fprintf(stderr, "User %i disconnected.\n", CONN_fd); - //#endif + #endif return 0; }//main diff --git a/Connector_RTMP/parsechunks.cpp b/Connector_RTMP/parsechunks.cpp index 5860b65f..d509173b 100644 --- a/Connector_RTMP/parsechunks.cpp +++ b/Connector_RTMP/parsechunks.cpp @@ -13,25 +13,25 @@ void parseChunk(){ break;//happens when connection breaks unexpectedly case 1://set chunk size chunk_rec_max = ntohl(*(int*)next.data); - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "CTRL: Set chunk size: %i\n", chunk_rec_max); #endif break; case 2://abort message - we ignore this one - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "CTRL: Abort message\n"); #endif //4 bytes of stream id to drop break; case 3://ack - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "CTRL: Acknowledgement\n"); #endif snd_window_at = ntohl(*(int*)next.data); snd_window_at = snd_cnt; break; case 4:{ - #ifdef DEBUG + #if DEBUG >= 4 short int ucmtype = ntohs(*(short int*)next.data); fprintf(stderr, "CTRL: User control message %hi\n", ucmtype); #endif @@ -47,7 +47,7 @@ void parseChunk(){ //we don't need to process this } break; case 5://window size of other end - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "CTRL: Window size\n"); #endif rec_window_size = ntohl(*(int*)next.data); @@ -55,7 +55,7 @@ void parseChunk(){ SendCTL(3, rec_cnt);//send ack (msg 3) break; case 6: - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "CTRL: Set peer bandwidth\n"); #endif //4 bytes window size, 1 byte limit type (ignored) @@ -63,49 +63,45 @@ void parseChunk(){ SendCTL(5, snd_window_size);//send window acknowledgement size (msg 5) break; case 8: - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Received audio data\n"); #endif break; case 9: - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Received video data\n"); #endif break; case 15: - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Received AFM3 data message\n"); #endif break; case 16: - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Received AFM3 shared object\n"); #endif break; case 17: - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Received AFM3 command message\n"); #endif break; case 18: - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Received AFM0 data message\n"); #endif break; case 19: - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Received AFM0 shared object\n"); #endif break; case 20:{//AMF0 command message bool parsed = false; amfdata = parseAMF(next.data, next.real_len); - #ifdef DEBUG - fprintf(stderr, "Received AFM0 command message:\n"); - amfdata.Print(); - #endif if (amfdata.getContentP(0)->StrValue() == "connect"){ - #ifdef DEBUG + #if DEBUG >= 4 int tmpint; tmpint = amfdata.getContentP(2)->getContentP("videoCodecs")->NumValue(); if (tmpint & 0x04){fprintf(stderr, "Sorensen video support detected\n");} @@ -149,9 +145,6 @@ void parseChunk(){ amfreply.addContent(AMFType("", (double)1));//stream ID - we use 1 SendChunk(3, 20, next.msg_stream_id, amfreply.Pack()); SendUSR(0, 0);//send UCM StreamBegin (0), stream 0 - #ifdef DEBUG - fprintf(stderr, "AMF0 command: createStream result\n"); - #endif parsed = true; }//createStream if ((amfdata.getContentP(0)->StrValue() == "getStreamLength") || (amfdata.getContentP(0)->StrValue() == "getMovLen")){ @@ -162,9 +155,6 @@ void parseChunk(){ amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info amfreply.addContent(AMFType("", (double)0));//zero length SendChunk(3, 20, next.msg_stream_id, amfreply.Pack()); - #ifdef DEBUG - fprintf(stderr, "AMF0 command: getStreamLength result\n"); - #endif parsed = true; }//getStreamLength if (amfdata.getContentP(0)->StrValue() == "checkBandwidth"){ @@ -175,9 +165,6 @@ void parseChunk(){ amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info SendChunk(3, 20, 1, amfreply.Pack()); - #ifdef DEBUG - fprintf(stderr, "AMF0 command: checkBandwidth result\n"); - #endif parsed = true; }//checkBandwidth if ((amfdata.getContentP(0)->StrValue() == "play") || (amfdata.getContentP(0)->StrValue() == "play2")){ @@ -220,24 +207,24 @@ void parseChunk(){ chunk_snd_max = 1024*1024; SendCTL(1, chunk_snd_max);//send chunk size max (msg 1) ready4data = true;//start sending video data! - #ifdef DEBUG - fprintf(stderr, "AMF0 command: play result (%s)\n", streamname.c_str()); - #endif parsed = true; }//createStream + #if DEBUG >= 3 + fprintf(stderr, "AMF0 command: %s\n", amfdata.getContentP(0)->StrValue().c_str()); + #endif if (!parsed){ - #ifdef DEBUG + #if DEBUG >= 2 fprintf(stderr, "AMF0 command not processed! :(\n"); #endif } } break; case 22: - #ifdef DEBUG + #if DEBUG >= 4 fprintf(stderr, "Received aggregate message\n"); #endif break; default: - #ifdef DEBUG + #if DEBUG >= 1 fprintf(stderr, "Unknown chunk received! Probably protocol corruption, stopping parsing of incoming data.\n"); #endif stopparsing = true; diff --git a/Connector_RTMPf/Makefile b/Connector_RTMPf/Makefile deleted file mode 100644 index 113d8023..00000000 --- a/Connector_RTMPf/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -SRC = main.cpp ../sockets/sw_base.cpp ../sockets/sw_inet.cpp ../sockets/sw_unix.cpp -OBJ = $(SRC:.cpp=.o) -OUT = Connector_RTMPf -INCLUDES = -CCFLAGS = -Wall -Wextra -funsigned-char -g -CC = $(CROSS)g++ -LD = $(CROSS)ld -AR = $(CROSS)ar -LIBS = -lssl -lcrypto -.SUFFIXES: .cpp -.PHONY: clean default -default: $(OUT) -.cpp.o: - $(CC) $(INCLUDES) $(CCFLAGS) $(LIBS) -c $< -o $@ -$(OUT): $(OBJ) chunkstream.cpp parsechunks.cpp handshake.cpp crypto.cpp amf.cpp - $(CC) $(LIBS) -o $(OUT) $(OBJ) -clean: - rm -rf $(OBJ) $(OUT) Makefile.bak *~ -run-test: $(OUT) - rm -rf ./meh - mkfifo ./meh - cat ./meh & - nc -l -p 1935 -e './Connector_RTMPf 2>./meh' diff --git a/Connector_RTMPf/amf.cpp b/Connector_RTMPf/amf.cpp deleted file mode 100644 index 70aab059..00000000 --- a/Connector_RTMPf/amf.cpp +++ /dev/null @@ -1,285 +0,0 @@ -#include -#include -#include - -class AMFType { - public: - std::string Indice(){return myIndice;}; - unsigned char GetType(){return myType;}; - double NumValue(){return numval;}; - std::string StrValue(){return strval;}; - const char * Str(){return strval.c_str();}; - int hasContent(){ - if (!contents){return 0;} - return contents->size(); - }; - void addContent(AMFType c){if (contents != 0){contents->push_back(c);}}; - AMFType* getContentP(int i){if (contents != 0){return &contents->at(i);}else{return 0;}}; - AMFType getContent(int i){if (contents != 0){return contents->at(i);}else{return AMFType("error");}}; - AMFType* getContentP(std::string s){ - if (contents != 0){ - for (std::vector::iterator it = contents->begin(); it != contents->end(); it++){ - if (it->Indice() == s){ - return &(*it); - } - } - } - return this; - }; - AMFType getContent(std::string s){ - if (contents != 0){ - for (std::vector::iterator it = contents->begin(); it != contents->end(); it++){ - if (it->Indice() == s){ - return *it; - } - } - } - return AMFType("error"); - }; - AMFType(std::string indice, double val, unsigned char setType = 0x00){//num type initializer - myIndice = indice; - myType = setType; - strval = ""; - numval = val; - contents = 0; - }; - AMFType(std::string indice, std::string val, unsigned char setType = 0x02){//str type initializer - myIndice = indice; - myType = setType; - strval = val; - numval = 0; - contents = 0; - }; - AMFType(std::string indice, unsigned char setType = 0x03){//object type initializer - myIndice = indice; - myType = setType; - strval = ""; - numval = 0; - contents = new std::vector; - }; - ~AMFType(){if (contents != 0){delete contents;contents=0;}}; - AMFType& operator=(const AMFType &a) { - myIndice = a.myIndice; - myType = a.myType; - strval = a.strval; - numval = a.numval; - if (contents){ - if (a.contents != contents){ - delete contents; - if (a.contents){ - contents = new std::vector; - for (std::vector::iterator it = a.contents->begin(); it < a.contents->end(); it++){ - contents->push_back(*it); - } - }else{ - contents = 0; - } - } - }else{ - if (a.contents){ - contents = new std::vector; - for (std::vector::iterator it = a.contents->begin(); it < a.contents->end(); it++){ - contents->push_back(*it); - } - } - } - return *this; - };//= operator - AMFType(const AMFType &a){ - myIndice = a.myIndice; - myType = a.myType; - strval = a.strval; - numval = a.numval; - if (a.contents){ - contents = new std::vector; - for (std::vector::iterator it = a.contents->begin(); it < a.contents->end(); it++){ - contents->push_back(*it); - } - }else{contents = 0;} - };//copy constructor - void Print(std::string indent = ""){ - std::cerr << indent; - switch (myType){ - case 0x00: std::cerr << "Number"; break; - case 0x01: std::cerr << "Bool"; break; - case 0x02://short string - case 0x0C: std::cerr << "String"; break; - case 0x03: std::cerr << "Object"; break; - case 0x08: std::cerr << "ECMA Array"; break; - case 0x05: std::cerr << "Null"; break; - case 0x06: std::cerr << "Undefined"; break; - case 0x0D: std::cerr << "Unsupported"; break; - case 0xFF: std::cerr << "Container"; break; - } - std::cerr << " " << myIndice << " "; - switch (myType){ - case 0x00: case 0x01: std::cerr << numval; break; - case 0x02: case 0x0C: std::cerr << strval; break; - } - std::cerr << std::endl; - if (contents){ - for (std::vector::iterator it = contents->begin(); it != contents->end(); it++){it->Print(indent+" ");} - } - };//print - std::string Pack(){ - std::string r = ""; - if ((myType == 0x02) && (strval.size() > 0xFFFF)){myType = 0x0C;} - if (myType != 0xFF){r += myType;} - switch (myType){ - case 0x00://number - r += *(((char*)&numval)+7); r += *(((char*)&numval)+6); - r += *(((char*)&numval)+5); r += *(((char*)&numval)+4); - r += *(((char*)&numval)+3); r += *(((char*)&numval)+2); - r += *(((char*)&numval)+1); r += *(((char*)&numval)); - break; - case 0x01://bool - r += (char)numval; - break; - case 0x02://short string - r += strval.size() / 256; - r += strval.size() % 256; - r += strval; - break; - case 0x0C://long string - r += strval.size() / (256*256*256); - r += strval.size() / (256*256); - r += strval.size() / 256; - r += strval.size() % 256; - r += strval; - break; - case 0x03://object - if (contents){ - for (std::vector::iterator it = contents->begin(); it != contents->end(); it++){ - r += it->Indice().size() / 256; - r += it->Indice().size() % 256; - r += it->Indice(); - r += it->Pack(); - } - } - r += (char)0; r += (char)0; r += (char)9; - break; - case 0x08:{//array - int arrlen = 0; - if (contents){ - arrlen = getContentP("length")->NumValue(); - r += arrlen / (256*256*256); r += arrlen / (256*256); r += arrlen / 256; r += arrlen % 256; - for (std::vector::iterator it = contents->begin(); it != contents->end(); it++){ - r += it->Indice().size() / 256; - r += it->Indice().size() % 256; - r += it->Indice(); - r += it->Pack(); - } - }else{ - r += (char)0; r += (char)0; r += (char)0; r += (char)0; - } - r += (char)0; r += (char)0; r += (char)9; - } break; - case 0xFF://container - our own type - do not send, only send contents - if (contents){ - for (std::vector::iterator it = contents->begin(); it != contents->end(); it++){ - r += it->Pack(); - } - } - break; - } - return r; - };//pack - protected: - std::string myIndice; - unsigned char myType; - std::string strval; - double numval; - std::vector * contents; -};//AMFType - -AMFType parseOneAMF(const unsigned char *& data, unsigned int &len, unsigned int &i, std::string name){ - char * helperchar = 0; - std::string tmpstr; - unsigned int tmpi = 0; - unsigned char tmpdbl[8]; - switch (data[i]){ - case 0x00://number - tmpdbl[7] = data[i+1]; - tmpdbl[6] = data[i+2]; - tmpdbl[5] = data[i+3]; - tmpdbl[4] = data[i+4]; - tmpdbl[3] = data[i+5]; - tmpdbl[2] = data[i+6]; - tmpdbl[1] = data[i+7]; - tmpdbl[0] = data[i+8]; - i+=9; - return AMFType(name, *(double*)tmpdbl, 0x00); - break; - case 0x01://bool - i+=2; - if (data[i-1] == 0){ - return AMFType(name, (double)0, 0x01); - }else{ - return AMFType(name, (double)1, 0x01); - } - break; - case 0x0C://long string - tmpi = data[i+1]*256*256*256+data[i+2]*256*256+data[i+3]*256+data[i+4]; - helperchar = (char*)malloc(tmpi+1); - memcpy(helperchar, data+i+5, tmpi); - helperchar[tmpi] = 0; - tmpstr = helperchar; - free(helperchar); - i += tmpi + 5; - return AMFType(name, tmpstr, 0x0C); - break; - case 0x02://string - tmpi = data[i+1]*256+data[i+2]; - helperchar = (char*)malloc(tmpi+1); - memcpy(helperchar, data+i+3, tmpi); - helperchar[tmpi] = 0; - tmpstr = helperchar; - free(helperchar); - i += tmpi + 3; - return AMFType(name, tmpstr, 0x02); - break; - case 0x05://null - case 0x06://undefined - case 0x0D://unsupported - ++i; - return AMFType(name, (double)0, data[i-1]); - break; - case 0x03:{//object - ++i; - AMFType ret = AMFType(name, data[i-1]); - while (data[i] + data[i+1] != 0){ - tmpi = data[i]*256+data[i+1]; - tmpstr = (char*)(data+i+2); - i += tmpi + 2; - ret.addContent(parseOneAMF(data, len, i, tmpstr)); - } - i += 3; - return ret; - } break; - case 0x08:{//ECMA array - ++i; - AMFType ret = AMFType(name, data[i-1]); - i += 4; - while (data[i] + data[i+1] != 0){ - tmpi = data[i]*256+data[i+1]; - tmpstr = (char*)(data+i+2); - i += tmpi + 2; - ret.addContent(parseOneAMF(data, len, i, tmpstr)); - } - i += 3; - return ret; - } break; - } - #ifdef DEBUG - fprintf(stderr, "Error: Unimplemented AMF type %hhx - returning.\n", data[i]); - #endif - return AMFType("error", (unsigned char)0xFF); -}//parseOneAMF - -AMFType parseAMF(const unsigned char * data, unsigned int len){ - AMFType ret("returned", (unsigned char)0xFF);//container type - unsigned int i = 0; - while (i < len){ret.addContent(parseOneAMF(data, len, i, ""));} - return ret; -}//parseAMF -AMFType parseAMF(std::string data){return parseAMF((const unsigned char*)data.c_str(), data.size());} diff --git a/Connector_RTMPf/chunkstream.cpp b/Connector_RTMPf/chunkstream.cpp deleted file mode 100644 index 9d9247aa..00000000 --- a/Connector_RTMPf/chunkstream.cpp +++ /dev/null @@ -1,501 +0,0 @@ -#include -#include -#include -#include -#include - -unsigned int getNowMS(){ - timeval t; - gettimeofday(&t, 0); - return t.tv_sec + t.tv_usec/1000; -} - - -unsigned int chunk_rec_max = 128; -unsigned int chunk_snd_max = 128; -unsigned int rec_window_size = 0xFA00; -unsigned int snd_window_size = 1024*500; -unsigned int rec_window_at = 0; -unsigned int snd_window_at = 0; -unsigned int rec_cnt = 0; -unsigned int snd_cnt = 0; - -unsigned int firsttime; - -struct chunkinfo { - 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; -};//chunkinfo - -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 - -//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 - - -//ugly global, but who cares... -std::map prevmap; -//return previous packet of this cs_id -chunkinfo GetPrev(unsigned int cs_id){ - return prevmap[cs_id]; -}//GetPrev -//store packet information of last packet of this cs_id -void PutPrev(chunkpack prev){ - prevmap[prev.cs_id].timestamp = prev.timestamp; - prevmap[prev.cs_id].len = prev.len; - prevmap[prev.cs_id].real_len = prev.real_len; - prevmap[prev.cs_id].len_left = prev.len_left; - prevmap[prev.cs_id].msg_type_id = prev.msg_type_id; - prevmap[prev.cs_id].msg_stream_id = prev.msg_stream_id; -}//PutPrev - -//ugly global, but who cares... -std::map sndprevmap; -//return previous packet of this cs_id -chunkinfo GetSndPrev(unsigned int cs_id){ - return sndprevmap[cs_id]; -}//GetPrev -//store packet information of last packet of this cs_id -void PutSndPrev(chunkpack prev){ - sndprevmap[prev.cs_id].cs_id = prev.cs_id; - sndprevmap[prev.cs_id].timestamp = prev.timestamp; - sndprevmap[prev.cs_id].len = prev.len; - sndprevmap[prev.cs_id].real_len = prev.real_len; - sndprevmap[prev.cs_id].len_left = prev.len_left; - sndprevmap[prev.cs_id].msg_type_id = prev.msg_type_id; - sndprevmap[prev.cs_id].msg_stream_id = prev.msg_stream_id; -}//PutPrev - - - -//sends the chunk over the network -void SendChunk(chunkpack ch){ - unsigned char tmp; - unsigned int tmpi; - unsigned char chtype = 0x00; - chunkinfo prev = GetSndPrev(ch.cs_id); - ch.timestamp -= firsttime; - if (prev.cs_id == ch.cs_id){ - if (ch.msg_stream_id == prev.msg_stream_id){ - chtype = 0x40;//do not send msg_stream_id - if (ch.len == prev.len){ - if (ch.msg_type_id == prev.msg_type_id){ - chtype = 0x80;//do not send len and msg_type_id - if (ch.timestamp == prev.timestamp){ - chtype = 0xC0;//do not send timestamp - } - } - } - } - } - if (ch.cs_id <= 63){ - tmp = chtype | ch.cs_id; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=1; - }else{ - if (ch.cs_id <= 255+64){ - tmp = chtype | 0; fwrite(&tmp, 1, 1, stdout); - tmp = ch.cs_id - 64; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=2; - }else{ - tmp = chtype | 1; fwrite(&tmp, 1, 1, stdout); - tmpi = ch.cs_id - 64; - tmp = tmpi % 256; fwrite(&tmp, 1, 1, stdout); - tmp = tmpi / 256; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=3; - } - } - unsigned int ntime = 0; - if (chtype != 0xC0){ - //timestamp or timestamp diff - if (chtype == 0x00){ - tmpi = ch.timestamp; - if (tmpi >= 0x00ffffff){ntime = tmpi; tmpi = 0x00ffffff;} - tmp = tmpi / (256*256); fwrite(&tmp, 1, 1, stdout); - tmp = tmpi / 256; fwrite(&tmp, 1, 1, stdout); - tmp = tmpi % 256; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=3; - }else{ - tmpi = ch.timestamp - prev.timestamp; - if (tmpi >= 0x00ffffff){ntime = tmpi; tmpi = 0x00ffffff;} - tmp = tmpi / (256*256); fwrite(&tmp, 1, 1, stdout); - tmp = tmpi / 256; fwrite(&tmp, 1, 1, stdout); - tmp = tmpi % 256; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=3; - } - if (chtype != 0x80){ - //len - tmpi = ch.len; - tmp = tmpi / (256*256); fwrite(&tmp, 1, 1, stdout); - tmp = tmpi / 256; fwrite(&tmp, 1, 1, stdout); - tmp = tmpi % 256; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=3; - //msg type id - tmp = ch.msg_type_id; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=1; - if (chtype != 0x40){ - //msg stream id - tmp = ch.msg_stream_id % 256; fwrite(&tmp, 1, 1, stdout); - tmp = ch.msg_stream_id / 256; fwrite(&tmp, 1, 1, stdout); - tmp = ch.msg_stream_id / (256*256); fwrite(&tmp, 1, 1, stdout); - tmp = ch.msg_stream_id / (256*256*256); fwrite(&tmp, 1, 1, stdout); - snd_cnt+=4; - } - } - } - //support for 0x00ffffff timestamps - if (ntime){ - tmp = ntime / (256*256*256); fwrite(&tmp, 1, 1, stdout); - tmp = ntime / (256*256); fwrite(&tmp, 1, 1, stdout); - tmp = ntime / 256; fwrite(&tmp, 1, 1, stdout); - tmp = ntime % 256; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=4; - } - ch.len_left = 0; - while (ch.len_left < ch.len){ - tmpi = ch.len - ch.len_left; - if (tmpi > chunk_snd_max){tmpi = chunk_snd_max;} - fwrite((ch.data + ch.len_left), 1, tmpi, stdout); - snd_cnt+=tmpi; - ch.len_left += tmpi; - if (ch.len_left < ch.len){ - if (ch.cs_id <= 63){ - tmp = 0xC0 + ch.cs_id; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=1; - }else{ - if (ch.cs_id <= 255+64){ - tmp = 0xC0; fwrite(&tmp, 1, 1, stdout); - tmp = ch.cs_id - 64; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=2; - }else{ - tmp = 0xC1; fwrite(&tmp, 1, 1, stdout); - tmpi = ch.cs_id - 64; - tmp = tmpi % 256; fwrite(&tmp, 1, 1, stdout); - tmp = tmpi / 256; fwrite(&tmp, 1, 1, stdout); - snd_cnt+=4; - } - } - } - } - PutSndPrev(ch); -}//SendChunk - -//sends a chunk -void SendChunk(unsigned int cs_id, unsigned char msg_type_id, unsigned int msg_stream_id, std::string data){ - chunkpack ch; - ch.cs_id = cs_id; - ch.timestamp = getNowMS(); - ch.len = data.size(); - ch.real_len = data.size(); - ch.len_left = 0; - ch.msg_type_id = msg_type_id; - ch.msg_stream_id = msg_stream_id; - ch.data = (unsigned char*)malloc(data.size()); - memcpy(ch.data, data.c_str(), data.size()); - SendChunk(ch); - free(ch.data); -}//SendChunk - -//sends a media chunk -void SendMedia(unsigned char msg_type_id, unsigned char * data, int len, unsigned int ts){ - chunkpack ch; - ch.cs_id = msg_type_id; - ch.timestamp = ts; - ch.len = len; - ch.real_len = len; - ch.len_left = 0; - ch.msg_type_id = msg_type_id; - ch.msg_stream_id = 1; - ch.data = (unsigned char*)malloc(len); - memcpy(ch.data, data, len); - SendChunk(ch); - free(ch.data); -}//SendMedia - -//sends a control message -void SendCTL(unsigned char type, unsigned int data){ - chunkpack ch; - ch.cs_id = 2; - ch.timestamp = getNowMS(); - ch.len = 4; - ch.real_len = 4; - ch.len_left = 0; - ch.msg_type_id = type; - ch.msg_stream_id = 0; - ch.data = (unsigned char*)malloc(4); - data = htonl(data); - memcpy(ch.data, &data, 4); - SendChunk(ch); - free(ch.data); -}//SendCTL - -//sends a control message -void SendCTL(unsigned char type, unsigned int data, unsigned char data2){ - chunkpack ch; - ch.cs_id = 2; - ch.timestamp = getNowMS(); - ch.len = 5; - ch.real_len = 5; - ch.len_left = 0; - ch.msg_type_id = type; - ch.msg_stream_id = 0; - ch.data = (unsigned char*)malloc(5); - data = htonl(data); - memcpy(ch.data, &data, 4); - ch.data[4] = data2; - SendChunk(ch); - free(ch.data); -}//SendCTL - -//sends a usr control message -void SendUSR(unsigned char type, unsigned int data){ - chunkpack ch; - ch.cs_id = 2; - ch.timestamp = getNowMS(); - ch.len = 6; - ch.real_len = 6; - ch.len_left = 0; - ch.msg_type_id = 4; - ch.msg_stream_id = 0; - ch.data = (unsigned char*)malloc(6); - data = htonl(data); - memcpy(ch.data+2, &data, 4); - ch.data[0] = 0; - ch.data[1] = type; - SendChunk(ch); - free(ch.data); -}//SendUSR - -//sends a usr control message -void SendUSR(unsigned char type, unsigned int data, unsigned int data2){ - chunkpack ch; - ch.cs_id = 2; - ch.timestamp = getNowMS(); - ch.len = 10; - ch.real_len = 10; - ch.len_left = 0; - ch.msg_type_id = 4; - ch.msg_stream_id = 0; - ch.data = (unsigned char*)malloc(10); - data = htonl(data); - data2 = htonl(data2); - memcpy(ch.data+2, &data, 4); - memcpy(ch.data+6, &data2, 4); - ch.data[0] = 0; - ch.data[1] = type; - SendChunk(ch); - free(ch.data); -}//SendUSR - -//get a chunk from standard input -struct chunkpack getChunk(){ - gettimeofday(&lastrec, 0); - struct chunkpack ret; - unsigned char temp; - fread(&(ret.chunktype), 1, 1, stdin); - rec_cnt++; - //read the chunkstream ID properly - switch (ret.chunktype & 0x3F){ - case 0: - fread(&temp, 1, 1, stdin); - rec_cnt++; - 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; - rec_cnt+=2; - break; - default: - ret.cs_id = ret.chunktype & 0x3F; - break; - } - chunkinfo prev = GetPrev(ret.cs_id); - //process the rest of the header, for each chunk type - switch (ret.chunktype & 0xC0){ - case 0x00: - 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; - fread(&temp, 1, 1, stdin); - ret.msg_stream_id += temp*256; - fread(&temp, 1, 1, stdin); - ret.msg_stream_id += temp*256*256; - fread(&temp, 1, 1, stdin); - ret.msg_stream_id += temp*256*256*256; - rec_cnt+=11; - break; - case 0x40: - 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; - rec_cnt+=7; - break; - case 0x80: - 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; - rec_cnt+=3; - break; - case 0xC0: - 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; - } - //calculate chunk length, real length, and length left till complete - 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; - ret.real_len = chunk_rec_max; - } - //read extended timestamp, if neccesary - 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; - rec_cnt+=4; - } - //read data if length > 0, and allocate it - if (ret.real_len > 0){ - ret.data = (unsigned char*)malloc(ret.real_len); - fread(ret.data, 1, ret.real_len, stdin); - rec_cnt+=ret.real_len; - }else{ - ret.data = 0; - } - PutPrev(ret); - return ret; -}//getChunk - -//adds newchunk to global list of unfinished chunks, re-assembling them complete -//returns pointer to chunk when a chunk is finished, 0 otherwise -//removes pointed to chunk from internal list if returned, without cleanup -// (cleanup performed in getWholeChunk function) -chunkpack * AddChunkPart(chunkpack newchunk){ - chunkpack * p; - unsigned char * tmpdata = 0; - static std::map ch_lst; - std::map::iterator it; - it = ch_lst.find(newchunk.cs_id); - if (it == ch_lst.end()){ - p = (chunkpack*)malloc(sizeof(chunkpack)); - *p = newchunk; - p->data = (unsigned char*)malloc(p->real_len); - memcpy(p->data, newchunk.data, p->real_len); - if (p->len_left == 0){return p;} - ch_lst[newchunk.cs_id] = p; - }else{ - p = it->second; - tmpdata = (unsigned char*)realloc(p->data, p->real_len + newchunk.real_len); - if (tmpdata == 0){ - #ifdef DEBUG - fprintf(stderr, "Error allocating memory!\n"); - #endif - return 0; - } - p->data = tmpdata; - memcpy(p->data+p->real_len, newchunk.data, newchunk.real_len); - p->real_len += newchunk.real_len; - p->len_left -= newchunk.real_len; - if (p->len_left <= 0){ - ch_lst.erase(it); - return p; - }else{ - ch_lst[newchunk.cs_id] = p;//pointer may have changed - } - } - return 0; -}//AddChunkPart - -//grabs chunks until a whole one comes in, then returns that -chunkpack getWholeChunk(){ - static chunkpack gwc_next, gwc_complete; - static bool clean = false; - int counter = 0; - if (!clean){gwc_complete.data = 0; clean = true;}//prevent brain damage - chunkpack * ret = 0; - scrubChunk(gwc_complete); - while (counter < 10000){ - gwc_next = getChunk(); - ret = AddChunkPart(gwc_next); - scrubChunk(gwc_next); - if (ret){ - gwc_complete = *ret; - free(ret);//cleanup returned chunk - return gwc_complete; - } - if (feof(stdin) != 0){break;} - counter++; - } - gwc_complete.msg_type_id = 0; - return gwc_complete; -}//getWholeChunk diff --git a/Connector_RTMPf/crypto.cpp b/Connector_RTMPf/crypto.cpp deleted file mode 100644 index 9f62e5ce..00000000 --- a/Connector_RTMPf/crypto.cpp +++ /dev/null @@ -1,506 +0,0 @@ -#define STR(x) (((std::string)(x)).c_str()) - -#include "crypto.h" - -#define P768 \ -"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ -"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ -"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ -"E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF" - -#define P1024 \ -"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ -"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ -"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ -"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ -"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \ -"FFFFFFFFFFFFFFFF" - -#define Q1024 \ -"7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68" \ -"948127044533E63A0105DF531D89CD9128A5043CC71A026E" \ -"F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122" \ -"F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6" \ -"F71C35FDAD44CFD2D74F9208BE258FF324943328F67329C0" \ -"FFFFFFFFFFFFFFFF" - -#define P1536 \ -"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ -"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ -"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ -"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ -"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ -"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ -"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ -"670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" - -#define P2048 \ -"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ -"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ -"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ -"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ -"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ -"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ -"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ -"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ -"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ -"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ -"15728E5A8AACAA68FFFFFFFFFFFFFFFF" - -#define P3072 \ -"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ -"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ -"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ -"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ -"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ -"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ -"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ -"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ -"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ -"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ -"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ -"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ -"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ -"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ -"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ -"43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" - -#define P4096 \ -"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ -"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ -"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ -"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ -"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ -"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ -"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ -"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ -"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ -"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ -"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ -"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ -"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ -"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ -"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ -"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ -"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ -"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ -"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ -"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ -"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ -"FFFFFFFFFFFFFFFF" - -#define P6144 \ -"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ -"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ -"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ -"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ -"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ -"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ -"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ -"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ -"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ -"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ -"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ -"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ -"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ -"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ -"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ -"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ -"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ -"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ -"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ -"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ -"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" \ -"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" \ -"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" \ -"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" \ -"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" \ -"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" \ -"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" \ -"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" \ -"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" \ -"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" \ -"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" \ -"12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF" - -#define P8192 \ -"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ -"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ -"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ -"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ -"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ -"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ -"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ -"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ -"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ -"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ -"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ -"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ -"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ -"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ -"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ -"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ -"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ -"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ -"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ -"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ -"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" \ -"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" \ -"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" \ -"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" \ -"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" \ -"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" \ -"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" \ -"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" \ -"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" \ -"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" \ -"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" \ -"12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" \ -"38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" \ -"741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" \ -"3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" \ -"22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" \ -"4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" \ -"062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" \ -"4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" \ -"B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" \ -"4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" \ -"9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" \ -"60C980DD98EDD3DFFFFFFFFFFFFFFFFF" - - -uint8_t genuineFMSKey[] = { - 0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20, - 0x41, 0x64, 0x6f, 0x62, 0x65, 0x20, 0x46, 0x6c, - 0x61, 0x73, 0x68, 0x20, 0x4d, 0x65, 0x64, 0x69, - 0x61, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Media Server 001 - 0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0xe8, - 0x2e, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57, - 0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab, - 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae -}; // 68 - -uint8_t genuineFPKey[] = { - 0x47, 0x65, 0x6E, 0x75, 0x69, 0x6E, 0x65, 0x20, - 0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x46, 0x6C, - 0x61, 0x73, 0x68, 0x20, 0x50, 0x6C, 0x61, 0x79, - 0x65, 0x72, 0x20, 0x30, 0x30, 0x31, // Genuine Adobe Flash Player 001 - 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, - 0x2E, 0x00, 0xD0, 0xD1, 0x02, 0x9E, 0x7E, 0x57, - 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, - 0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE -}; // 62 - - -void replace(std::string &target, std::string search, std::string replacement) { - if (search == replacement) - return; - if (search == "") - return; - std::string::size_type i = std::string::npos; - while ((i = target.find(search)) != std::string::npos) { - target.replace(i, search.length(), replacement); - } -} - - -DHWrapper::DHWrapper(int32_t bitsCount) { - _bitsCount = bitsCount; - _pDH = NULL; - _pSharedKey = NULL; - _sharedKeyLength = 0; - _peerPublickey = NULL; -} - -DHWrapper::~DHWrapper() { - Cleanup(); -} - -bool DHWrapper::Initialize() { - Cleanup(); - - //1. Create the DH - _pDH = DH_new(); - if (_pDH == NULL) { - Cleanup(); - return false; - } - - //2. Create his internal p and g - _pDH->p = BN_new(); - if (_pDH->p == NULL) { - Cleanup(); - return false; - } - _pDH->g = BN_new(); - if (_pDH->g == NULL) { - Cleanup(); - return false; - } - - //3. initialize p, g and key length - if (BN_hex2bn(&_pDH->p, P1024) == 0) { - Cleanup(); - return false; - } - if (BN_set_word(_pDH->g, 2) != 1) { - Cleanup(); - return false; - } - - //4. Set the key length - _pDH->length = _bitsCount; - - //5. Generate private and public key - if (DH_generate_key(_pDH) != 1) { - Cleanup(); - return false; - } - - return true; -} - -bool DHWrapper::CopyPublicKey(uint8_t *pDst, int32_t dstLength) { - if (_pDH == NULL) { - return false; - } - - return CopyKey(_pDH->pub_key, pDst, dstLength); -} - -bool DHWrapper::CopyPrivateKey(uint8_t *pDst, int32_t dstLength) { - if (_pDH == NULL) { - return false; - } - - return CopyKey(_pDH->priv_key, pDst, dstLength); -} - -bool DHWrapper::CreateSharedKey(uint8_t *pPeerPublicKey, int32_t length) { - if (_pDH == NULL) { - return false; - } - - if (_sharedKeyLength != 0 || _pSharedKey != NULL) { - return false; - } - - _sharedKeyLength = DH_size(_pDH); - if (_sharedKeyLength <= 0 || _sharedKeyLength > 1024) { - return false; - } - _pSharedKey = new uint8_t[_sharedKeyLength]; - - _peerPublickey = BN_bin2bn(pPeerPublicKey, length, 0); - if (_peerPublickey == NULL) { - return false; - } - - if (DH_compute_key(_pSharedKey, _peerPublickey, _pDH) != _sharedKeyLength) { - return false; - } - - return true; -} - -bool DHWrapper::CopySharedKey(uint8_t *pDst, int32_t dstLength) { - if (_pDH == NULL) { - return false; - } - - if (dstLength != _sharedKeyLength) { - return false; - } - - memcpy(pDst, _pSharedKey, _sharedKeyLength); - - return true; -} - -void DHWrapper::Cleanup() { - if (_pDH != NULL) { - if (_pDH->p != NULL) { - BN_free(_pDH->p); - _pDH->p = NULL; - } - if (_pDH->g != NULL) { - BN_free(_pDH->g); - _pDH->g = NULL; - } - DH_free(_pDH); - _pDH = NULL; - } - - if (_pSharedKey != NULL) { - delete[] _pSharedKey; - _pSharedKey = NULL; - } - _sharedKeyLength = 0; - - if (_peerPublickey != NULL) { - BN_free(_peerPublickey); - _peerPublickey = NULL; - } -} - -bool DHWrapper::CopyKey(BIGNUM *pNum, uint8_t *pDst, int32_t dstLength) { - int32_t keySize = BN_num_bytes(pNum); - if ((keySize <= 0) || (dstLength <= 0) || (keySize > dstLength)) { - return false; - } - - if (BN_bn2bin(pNum, pDst) != keySize) { - return false; - } - - return true; -} - -void InitRC4Encryption(uint8_t *secretKey, uint8_t *pubKeyIn, uint8_t *pubKeyOut, RC4_KEY *rc4keyIn, RC4_KEY *rc4keyOut) { - uint8_t digest[SHA256_DIGEST_LENGTH]; - unsigned int digestLen = 0; - - HMAC_CTX ctx; - HMAC_CTX_init(&ctx); - HMAC_Init_ex(&ctx, secretKey, 128, EVP_sha256(), 0); - HMAC_Update(&ctx, pubKeyIn, 128); - HMAC_Final(&ctx, digest, &digestLen); - HMAC_CTX_cleanup(&ctx); - - RC4_set_key(rc4keyOut, 16, digest); - - HMAC_CTX_init(&ctx); - HMAC_Init_ex(&ctx, secretKey, 128, EVP_sha256(), 0); - HMAC_Update(&ctx, pubKeyOut, 128); - HMAC_Final(&ctx, digest, &digestLen); - HMAC_CTX_cleanup(&ctx); - - RC4_set_key(rc4keyIn, 16, digest); -} - -std::string md5(std::string source, bool textResult) { - EVP_MD_CTX mdctx; - unsigned char md_value[EVP_MAX_MD_SIZE]; - unsigned int md_len; - - EVP_DigestInit(&mdctx, EVP_md5()); - EVP_DigestUpdate(&mdctx, STR(source), source.length()); - EVP_DigestFinal_ex(&mdctx, md_value, &md_len); - EVP_MD_CTX_cleanup(&mdctx); - - if (textResult) { - std::string result = ""; - char tmp[3]; - for (uint32_t i = 0; i < md_len; i++) { - sprintf(tmp, "%02x", md_value[i]); - result += tmp; - } - return result; - } else { - return std::string((char *) md_value, md_len); - } -} - -std::string b64(std::string source) { - return b64((uint8_t *) STR(source), source.size()); -} - -std::string b64(uint8_t *pBuffer, uint32_t length) { - BIO *bmem; - BIO *b64; - BUF_MEM *bptr; - - b64 = BIO_new(BIO_f_base64()); - bmem = BIO_new(BIO_s_mem()); - - b64 = BIO_push(b64, bmem); - BIO_write(b64, pBuffer, length); - std::string result = ""; - if (BIO_flush(b64) == 1) { - BIO_get_mem_ptr(b64, &bptr); - result = std::string(bptr->data, bptr->length); - } - - BIO_free_all(b64); - - - replace(result, "\n", ""); - replace(result, "\r", ""); - - return result; -} - -std::string unb64(std::string source) { - return unb64((uint8_t *)STR(source),source.length()); -} - -std::string unb64(uint8_t *pBuffer, uint32_t length){ - // create a memory buffer containing base64 encoded data - //BIO* bmem = BIO_new_mem_buf((void*) STR(source), source.length()); - BIO* bmem = BIO_new_mem_buf((void *)pBuffer, length); - - // push a Base64 filter so that reading from buffer decodes it - BIO *bioCmd = BIO_new(BIO_f_base64()); - // we don't want newlines - BIO_set_flags(bioCmd, BIO_FLAGS_BASE64_NO_NL); - bmem = BIO_push(bioCmd, bmem); - - char *pOut = new char[length]; - - int finalLen = BIO_read(bmem, (void*) pOut, length); - BIO_free_all(bmem); - std::string result(pOut, finalLen); - delete[] pOut; - return result; -} - -void HMACsha256(const void *pData, uint32_t dataLength, const void *pKey, uint32_t keyLength, void *pResult) { - unsigned int digestLen; - HMAC_CTX ctx; - HMAC_CTX_init(&ctx); - HMAC_Init_ex(&ctx, (unsigned char*) pKey, keyLength, EVP_sha256(), NULL); - HMAC_Update(&ctx, (unsigned char *) pData, dataLength); - HMAC_Final(&ctx, (unsigned char *) pResult, &digestLen); - HMAC_CTX_cleanup(&ctx); -} - -uint32_t GetDigestOffset0(uint8_t *pBuffer) { - uint32_t offset = pBuffer[8] + pBuffer[9] + pBuffer[10] + pBuffer[11]; - return (offset % 728) + 12; -} -uint32_t GetDigestOffset1(uint8_t *pBuffer) { - uint32_t offset = pBuffer[772] + pBuffer[773] + pBuffer[774] + pBuffer[775]; - return (offset % 728) + 776; -} -uint32_t GetDigestOffset(uint8_t *pBuffer, uint8_t scheme){ - if (scheme == 0){return GetDigestOffset0(pBuffer);}else{return GetDigestOffset1(pBuffer);} -} -uint32_t GetDHOffset0(uint8_t *pBuffer) { - uint32_t offset = pBuffer[1532] + pBuffer[1533] + pBuffer[1534] + pBuffer[1535]; - return (offset % 632) + 772; -} -uint32_t GetDHOffset1(uint8_t *pBuffer) { - uint32_t offset = pBuffer[768] + pBuffer[769] + pBuffer[770] + pBuffer[771]; - return (offset % 632) + 8; -} -uint32_t GetDHOffset(uint8_t *pBuffer, uint8_t scheme){ - if (scheme == 0){return GetDHOffset0(pBuffer);}else{return GetDHOffset1(pBuffer);} -} - - -bool ValidateClientScheme(uint8_t * pBuffer, uint8_t scheme) { - uint32_t clientDigestOffset = GetDigestOffset(pBuffer, scheme); - uint8_t *pTempBuffer = new uint8_t[1536 - 32]; - memcpy(pTempBuffer, pBuffer, clientDigestOffset); - memcpy(pTempBuffer + clientDigestOffset, pBuffer + clientDigestOffset + 32, 1536 - clientDigestOffset - 32); - uint8_t *pTempHash = new uint8_t[512]; - HMACsha256(pTempBuffer, 1536 - 32, genuineFPKey, 30, pTempHash); - bool result = (memcmp(pBuffer+clientDigestOffset, pTempHash, 32) == 0); - #ifdef DEBUG - fprintf(stderr, "Client scheme validation %hhi %s\n", scheme, result?"success":"failed"); - #endif - delete[] pTempBuffer; - delete[] pTempHash; - return result; -} diff --git a/Connector_RTMPf/crypto.h b/Connector_RTMPf/crypto.h deleted file mode 100644 index 8d36188b..00000000 --- a/Connector_RTMPf/crypto.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _CRYPTO_H -#define _CRYPTO_H -#define DLLEXP - -#include -#include -#include -#include -#include -#include -#include -#include - -class DLLEXP DHWrapper { -private: - int32_t _bitsCount; - DH *_pDH; - uint8_t *_pSharedKey; - int32_t _sharedKeyLength; - BIGNUM *_peerPublickey; -public: - DHWrapper(int32_t bitsCount); - virtual ~DHWrapper(); - - bool Initialize(); - bool CopyPublicKey(uint8_t *pDst, int32_t dstLength); - bool CopyPrivateKey(uint8_t *pDst, int32_t dstLength); - bool CreateSharedKey(uint8_t *pPeerPublicKey, int32_t length); - bool CopySharedKey(uint8_t *pDst, int32_t dstLength); -private: - void Cleanup(); - bool CopyKey(BIGNUM *pNum, uint8_t *pDst, int32_t dstLength); -}; - - -DLLEXP void InitRC4Encryption(uint8_t *secretKey, uint8_t *pubKeyIn, uint8_t *pubKeyOut, - RC4_KEY *rc4keyIn, RC4_KEY *rc4keyOut); -DLLEXP std::string md5(std::string source, bool textResult); -DLLEXP std::string b64(std::string source); -DLLEXP std::string b64(uint8_t *pBuffer, uint32_t length); -DLLEXP std::string unb64(std::string source); -DLLEXP std::string unb64(uint8_t *pBuffer, uint32_t length); - -#endif /* _CRYPTO_H */ - diff --git a/Connector_RTMPf/flv_sock.cpp b/Connector_RTMPf/flv_sock.cpp deleted file mode 100644 index 8d6c55a4..00000000 --- a/Connector_RTMPf/flv_sock.cpp +++ /dev/null @@ -1,30 +0,0 @@ -SWBaseSocket::SWBaseError SWBerr; -char * FLVbuffer; -int FLV_len; -int FLVbs = 0; - -void FLV_Readheader(SWUnixSocket & ss){ - static char header[13]; - while (ss.frecv(header, 13, &SWBerr) != 13){ - //wait - } -}//FLV_Readheader - -void FLV_Dump(){FLV_len = 0;} - -bool FLV_GetPacket(SWUnixSocket & ss){ - if (FLVbs < 15){FLVbuffer = (char*)realloc(FLVbuffer, 15); FLVbs = 15;} - //if received a whole header, receive a whole packet - //if not, retry header next pass - if (FLV_len == 0){ - if (ss.frecv(FLVbuffer, 11, &SWBerr) == 11){ - FLV_len = FLVbuffer[3] + 15; - FLV_len += (FLVbuffer[2] << 8); - FLV_len += (FLVbuffer[1] << 16); - if (FLVbs < FLV_len){FLVbuffer = (char*)realloc(FLVbuffer, FLV_len);FLVbs = FLV_len;} - } - }else{ - if (ss.frecv(FLVbuffer+11, FLV_len-11, &SWBerr) == FLV_len-11){return true;} - } - return false; -}//FLV_GetPacket diff --git a/Connector_RTMPf/handshake.cpp b/Connector_RTMPf/handshake.cpp deleted file mode 100644 index 43143dc8..00000000 --- a/Connector_RTMPf/handshake.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#undef OLDHANDSHAKE //change to #define for old handshake method - -char versionstring[] = "PLSRTMPServer"; - -#ifdef OLDHANDSHAKE -struct Handshake { - char Time[4]; - char Zero[4]; - char Random[1528]; -};//Handshake - -bool doHandshake(){ - 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); - rec_cnt+=1537; - /** 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] = versionstring[i%13]; - } - /** 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); - snd_cnt+=1537; - /** Send S2 **/ - fwrite(Client.Time, 1, 4, stdout); - fwrite(Client.Time, 1, 4, stdout); - fwrite(Client.Random, 1, 1528, stdout); - snd_cnt+=1536; - /** 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); - rec_cnt+=1536; - return true; -}//doHandshake - -#else - -#include "crypto.cpp" //cryptography for handshaking - -bool doHandshake(){ - char Version; - /** Read C0 **/ - fread(&Version, 1, 1, stdin); - uint8_t Client[1536]; - uint8_t Server[3072]; - fread(&Client, 1, 1536, stdin); - rec_cnt+=1537; - - /** Build S1 Packet **/ - *((uint32_t*)Server) = 0;//time zero - *(((uint32_t*)(Server+4))) = htonl(0x01020304);//version 1 2 3 4 - for (int i = 8; i < 3072; ++i){Server[i] = versionstring[i%13];}//"random" data - - bool encrypted = (Version == 6); - #ifdef DEBUG - fprintf(stderr, "Handshake version is %hhi\n", Version); - #endif - uint8_t _validationScheme = 5; - if (ValidateClientScheme(Client, 0)) _validationScheme = 0; - if (ValidateClientScheme(Client, 1)) _validationScheme = 1; - - #ifdef DEBUG - fprintf(stderr, "Handshake type is %hhi, encryption is %s\n", _validationScheme, encrypted?"on":"off"); - #endif - - //**** FIRST 1536 bytes from server response ****// - //compute DH key position - uint32_t serverDHOffset = GetDHOffset(Server, _validationScheme); - uint32_t clientDHOffset = GetDHOffset(Client, _validationScheme); - - //generate DH key - DHWrapper dhWrapper(1024); - if (!dhWrapper.Initialize()) return false; - if (!dhWrapper.CreateSharedKey(Client + clientDHOffset, 128)) return false; - if (!dhWrapper.CopyPublicKey(Server + serverDHOffset, 128)) return false; - - if (encrypted) { - uint8_t secretKey[128]; - if (!dhWrapper.CopySharedKey(secretKey, sizeof (secretKey))) return false; - RC4_KEY _pKeyIn; - RC4_KEY _pKeyOut; - InitRC4Encryption(secretKey, (uint8_t*) & Client[clientDHOffset], (uint8_t*) & Server[serverDHOffset], &_pKeyIn, &_pKeyOut); - uint8_t data[1536]; - RC4(&_pKeyIn, 1536, data, data); - RC4(&_pKeyOut, 1536, data, data); - } - //generate the digest - uint32_t serverDigestOffset = GetDigestOffset(Server, _validationScheme); - uint8_t *pTempBuffer = new uint8_t[1536 - 32]; - memcpy(pTempBuffer, Server, serverDigestOffset); - memcpy(pTempBuffer + serverDigestOffset, Server + serverDigestOffset + 32, 1536 - serverDigestOffset - 32); - uint8_t *pTempHash = new uint8_t[512]; - HMACsha256(pTempBuffer, 1536 - 32, genuineFMSKey, 36, pTempHash); - memcpy(Server + serverDigestOffset, pTempHash, 32); - delete[] pTempBuffer; - delete[] pTempHash; - - //**** SECOND 1536 bytes from server response ****// - uint32_t keyChallengeIndex = GetDigestOffset(Client, _validationScheme); - pTempHash = new uint8_t[512]; - HMACsha256(Client + keyChallengeIndex, 32, genuineFMSKey, 68, pTempHash); - uint8_t *pLastHash = new uint8_t[512]; - HMACsha256(Server + 1536, 1536 - 32, pTempHash, 32, pLastHash); - memcpy(Server + 1536 * 2 - 32, pLastHash, 32); - delete[] pTempHash; - delete[] pLastHash; - //***** DONE BUILDING THE RESPONSE ***// - /** Send response **/ - fwrite(&Version, 1, 1, stdout); - fwrite(&Server, 1, 3072, stdout); - snd_cnt+=3073; - /** Flush, necessary in order to work **/ - fflush(stdout); - /** Read and discard C2 **/ - fread(Client, 1, 1536, stdin); - rec_cnt+=1536; - return true; -} - -#endif diff --git a/Connector_RTMPf/main.cpp b/Connector_RTMPf/main.cpp deleted file mode 100644 index 5b724215..00000000 --- a/Connector_RTMPf/main.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#undef DEBUG -#include -#include -#include -#include - -//needed for select -#include -#include -#include -#include -#include - -//for connection to server -#include "../sockets/SocketW.h" -bool ready4data = false;//set to true when streaming starts -bool inited = false; -bool stopparsing = false; -timeval lastrec; - -#include "parsechunks.cpp" //chunkstream parsing -#include "handshake.cpp" //handshaking -#include "flv_sock.cpp" //FLV parsing with SocketW - -int main(){ - unsigned int ts; - unsigned int fts = 0; - unsigned int ftst; - SWUnixSocket ss; - fd_set pollset; - struct timeval timeout; - //0 timeout - return immediately after select call - timeout.tv_sec = 1; timeout.tv_usec = 0; - FD_ZERO(&pollset);//clear the polling set - FD_SET(0, &pollset);//add stdin to polling set - - //first timestamp set - firsttime = getNowMS(); - - #ifdef DEBUG - fprintf(stderr, "Doing handshake...\n"); - #endif - if (doHandshake()){ - #ifdef DEBUG - fprintf(stderr, "Handshake succcess!\n"); - #endif - }else{ - #ifdef DEBUG - fprintf(stderr, "Handshake fail!\n"); - #endif - return 0; - } - #ifdef DEBUG - fprintf(stderr, "Starting processing...\n"); - #endif - while (std::cin.good() && std::cout.good()){ - //select(1, &pollset, 0, 0, &timeout); - //only parse input from stdin if available or not yet init'ed - //FD_ISSET(0, &pollset) || //NOTE: Polling does not work? WHY?!? WHY DAMN IT?!? - if ((!ready4data || (snd_cnt - snd_window_at >= snd_window_size)) && !stopparsing){parseChunk();fflush(stdout);} - if (ready4data){ - if (!inited){ - //we are ready, connect the socket! - if (!ss.connect(streamname.c_str())){ - #ifdef DEBUG - fprintf(stderr, "Could not connect to server!\n"); - #endif - return 0; - } - FLV_Readheader(ss);//read the header, we don't want it - #ifdef DEBUG - fprintf(stderr, "Header read, starting to send video data...\n"); - #endif - inited = true; - } - //only send data if previous data has been ACK'ed... - if (snd_cnt - snd_window_at < snd_window_size){ - if (FLV_GetPacket(ss)){//able to read a full packet? - ts = FLVbuffer[7] * 256*256*256; - ts += FLVbuffer[4] * 256*256; - ts += FLVbuffer[5] * 256; - ts += FLVbuffer[6]; - if (ts != 0){ - if (fts == 0){fts = ts;ftst = getNowMS();} - ts -= fts; - FLVbuffer[7] = ts / (256*256*256); - FLVbuffer[4] = ts / (256*256); - FLVbuffer[5] = ts / 256; - FLVbuffer[6] = ts % 256; - ts += ftst; - }else{ - ftst = getNowMS(); - FLVbuffer[7] = ftst / (256*256*256); - FLVbuffer[4] = ftst / (256*256); - FLVbuffer[5] = ftst / 256; - FLVbuffer[6] = ftst % 256; - } - SendMedia((unsigned char)FLVbuffer[0], (unsigned char *)FLVbuffer+11, FLV_len-15, ts); - FLV_Dump();//dump packet and get ready for next - } - if ((SWBerr != SWBaseSocket::ok) && (SWBerr != SWBaseSocket::notReady)){ - #ifdef DEBUG - fprintf(stderr, "No more data! :-( (%s)\n", SWBerr.get_error().c_str()); - #endif - return 0;//no more input possible! Fail immediately. - } - } - } - //send ACK if we received a whole window - if (rec_cnt - rec_window_at > rec_window_size){ - rec_window_at = rec_cnt; - SendCTL(3, rec_cnt);//send ack (msg 3) - } - } - #ifdef DEBUG - fprintf(stderr, "User disconnected.\n"); - #endif - return 0; -}//main diff --git a/Connector_RTMPf/parsechunks.cpp b/Connector_RTMPf/parsechunks.cpp deleted file mode 100644 index 5860b65f..00000000 --- a/Connector_RTMPf/parsechunks.cpp +++ /dev/null @@ -1,246 +0,0 @@ -#include "chunkstream.cpp" //chunkstream decoding -#include "amf.cpp" //simple AMF0 parsing -std::string streamname = "/tmp/shared_socket"; - -//gets and parses one chunk -void parseChunk(){ - static chunkpack next; - static AMFType amfdata("empty", (unsigned char)0xFF); - static AMFType amfelem("empty", (unsigned char)0xFF); - next = getWholeChunk(); - switch (next.msg_type_id){ - case 0://does not exist - break;//happens when connection breaks unexpectedly - case 1://set chunk size - chunk_rec_max = ntohl(*(int*)next.data); - #ifdef DEBUG - fprintf(stderr, "CTRL: Set chunk size: %i\n", chunk_rec_max); - #endif - break; - case 2://abort message - we ignore this one - #ifdef DEBUG - fprintf(stderr, "CTRL: Abort message\n"); - #endif - //4 bytes of stream id to drop - break; - case 3://ack - #ifdef DEBUG - fprintf(stderr, "CTRL: Acknowledgement\n"); - #endif - snd_window_at = ntohl(*(int*)next.data); - snd_window_at = snd_cnt; - break; - case 4:{ - #ifdef DEBUG - short int ucmtype = ntohs(*(short int*)next.data); - fprintf(stderr, "CTRL: User control message %hi\n", ucmtype); - #endif - //2 bytes event type, rest = event data - //types: - //0 = stream begin, 4 bytes ID - //1 = stream EOF, 4 bytes ID - //2 = stream dry, 4 bytes ID - //3 = setbufferlen, 4 bytes ID, 4 bytes length - //4 = streamisrecorded, 4 bytes ID - //6 = pingrequest, 4 bytes data - //7 = pingresponse, 4 bytes data - //we don't need to process this - } break; - case 5://window size of other end - #ifdef DEBUG - fprintf(stderr, "CTRL: Window size\n"); - #endif - rec_window_size = ntohl(*(int*)next.data); - rec_window_at = rec_cnt; - SendCTL(3, rec_cnt);//send ack (msg 3) - break; - case 6: - #ifdef DEBUG - fprintf(stderr, "CTRL: Set peer bandwidth\n"); - #endif - //4 bytes window size, 1 byte limit type (ignored) - snd_window_size = ntohl(*(int*)next.data); - SendCTL(5, snd_window_size);//send window acknowledgement size (msg 5) - break; - case 8: - #ifdef DEBUG - fprintf(stderr, "Received audio data\n"); - #endif - break; - case 9: - #ifdef DEBUG - fprintf(stderr, "Received video data\n"); - #endif - break; - case 15: - #ifdef DEBUG - fprintf(stderr, "Received AFM3 data message\n"); - #endif - break; - case 16: - #ifdef DEBUG - fprintf(stderr, "Received AFM3 shared object\n"); - #endif - break; - case 17: - #ifdef DEBUG - fprintf(stderr, "Received AFM3 command message\n"); - #endif - break; - case 18: - #ifdef DEBUG - fprintf(stderr, "Received AFM0 data message\n"); - #endif - break; - case 19: - #ifdef DEBUG - fprintf(stderr, "Received AFM0 shared object\n"); - #endif - break; - case 20:{//AMF0 command message - bool parsed = false; - amfdata = parseAMF(next.data, next.real_len); - #ifdef DEBUG - fprintf(stderr, "Received AFM0 command message:\n"); - amfdata.Print(); - #endif - if (amfdata.getContentP(0)->StrValue() == "connect"){ - #ifdef DEBUG - int tmpint; - tmpint = amfdata.getContentP(2)->getContentP("videoCodecs")->NumValue(); - if (tmpint & 0x04){fprintf(stderr, "Sorensen video support detected\n");} - if (tmpint & 0x80){fprintf(stderr, "H264 video support detected\n");} - tmpint = amfdata.getContentP(2)->getContentP("audioCodecs")->NumValue(); - if (tmpint & 0x04){fprintf(stderr, "MP3 audio support detected\n");} - if (tmpint & 0x400){fprintf(stderr, "AAC video support detected\n");} - #endif - SendCTL(6, rec_window_size, 0);//send peer bandwidth (msg 6) - SendCTL(5, snd_window_size);//send window acknowledgement size (msg 5) - SendUSR(0, 0);//send UCM StreamBegin (0), stream 0 - //send a _result reply - AMFType amfreply("container", (unsigned char)0xFF); - amfreply.addContent(AMFType("", "_result"));//result success - amfreply.addContent(amfdata.getContent(1));//same transaction ID -// amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info - amfreply.addContent(AMFType(""));//server properties - amfreply.getContentP(2)->addContent(AMFType("fmsVer", "FMS/3,0,1,123"));//stolen from examples - amfreply.getContentP(2)->addContent(AMFType("capabilities", (double)31));//stolen from examples - amfreply.addContent(AMFType(""));//info - amfreply.getContentP(3)->addContent(AMFType("level", "status")); - amfreply.getContentP(3)->addContent(AMFType("code", "NetConnection.Connect.Success")); - amfreply.getContentP(3)->addContent(AMFType("description", "Connection succeeded.")); - amfreply.getContentP(3)->addContent(AMFType("capabilities", (double)33));//from red5 server - amfreply.getContentP(3)->addContent(AMFType("fmsVer", "PLS/1,0,0,0"));//from red5 server - SendChunk(3, 20, next.msg_stream_id, amfreply.Pack()); - //send onBWDone packet - //amfreply = AMFType("container", (unsigned char)0xFF); - //amfreply.addContent(AMFType("", "onBWDone"));//result success - //amfreply.addContent(AMFType("", (double)0));//zero - //amfreply.addContent(AMFType("", (double)0, 0x05));//null - //SendChunk(3, 20, next.msg_stream_id, amfreply.Pack()); - parsed = true; - }//connect - if (amfdata.getContentP(0)->StrValue() == "createStream"){ - //send a _result reply - AMFType amfreply("container", (unsigned char)0xFF); - amfreply.addContent(AMFType("", "_result"));//result success - amfreply.addContent(amfdata.getContent(1));//same transaction ID - amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info - amfreply.addContent(AMFType("", (double)1));//stream ID - we use 1 - SendChunk(3, 20, next.msg_stream_id, amfreply.Pack()); - SendUSR(0, 0);//send UCM StreamBegin (0), stream 0 - #ifdef DEBUG - fprintf(stderr, "AMF0 command: createStream result\n"); - #endif - parsed = true; - }//createStream - if ((amfdata.getContentP(0)->StrValue() == "getStreamLength") || (amfdata.getContentP(0)->StrValue() == "getMovLen")){ - //send a _result reply - AMFType amfreply("container", (unsigned char)0xFF); - amfreply.addContent(AMFType("", "_result"));//result success - amfreply.addContent(amfdata.getContent(1));//same transaction ID - amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info - amfreply.addContent(AMFType("", (double)0));//zero length - SendChunk(3, 20, next.msg_stream_id, amfreply.Pack()); - #ifdef DEBUG - fprintf(stderr, "AMF0 command: getStreamLength result\n"); - #endif - parsed = true; - }//getStreamLength - if (amfdata.getContentP(0)->StrValue() == "checkBandwidth"){ - //send a _result reply - AMFType amfreply("container", (unsigned char)0xFF); - amfreply.addContent(AMFType("", "_result"));//result success - amfreply.addContent(amfdata.getContent(1));//same transaction ID - amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info - amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info - SendChunk(3, 20, 1, amfreply.Pack()); - #ifdef DEBUG - fprintf(stderr, "AMF0 command: checkBandwidth result\n"); - #endif - parsed = true; - }//checkBandwidth - if ((amfdata.getContentP(0)->StrValue() == "play") || (amfdata.getContentP(0)->StrValue() == "play2")){ - //send streambegin - streamname = amfdata.getContentP(3)->StrValue(); - for (std::string::iterator i=streamname.end()-1; i>=streamname.begin(); --i){ - if (!isalpha(*i) && !isdigit(*i)){streamname.erase(i);}else{*i=tolower(*i);} - } - streamname = "/tmp/shared_socket_" + streamname; - SendUSR(0, 1);//send UCM StreamBegin (0), stream 1 - //send a status reply - AMFType amfreply("container", (unsigned char)0xFF); - amfreply.addContent(AMFType("", "onStatus"));//status reply - amfreply.addContent(amfdata.getContent(1));//same transaction ID - amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info - amfreply.addContent(AMFType(""));//info - amfreply.getContentP(3)->addContent(AMFType("level", "status")); - amfreply.getContentP(3)->addContent(AMFType("code", "NetStream.Play.Reset")); - amfreply.getContentP(3)->addContent(AMFType("description", "Playing and resetting...")); - amfreply.getContentP(3)->addContent(AMFType("details", "PLS")); - amfreply.getContentP(3)->addContent(AMFType("clientid", (double)1)); - SendChunk(4, 20, next.msg_stream_id, amfreply.Pack()); - amfreply = AMFType("container", (unsigned char)0xFF); - amfreply.addContent(AMFType("", "onStatus"));//status reply - amfreply.addContent(amfdata.getContent(1));//same transaction ID - amfreply.addContent(AMFType("", (double)0, 0x05));//null - command info - amfreply.addContent(AMFType(""));//info - amfreply.getContentP(3)->addContent(AMFType("level", "status")); - amfreply.getContentP(3)->addContent(AMFType("code", "NetStream.Play.Start")); - amfreply.getContentP(3)->addContent(AMFType("description", "Playing!")); - amfreply.getContentP(3)->addContent(AMFType("details", "PLS")); - amfreply.getContentP(3)->addContent(AMFType("clientid", (double)1)); - SendChunk(4, 20, 1, amfreply.Pack()); -//No clue what this does. Most real servers send it, though... -// amfreply = AMFType("container", (unsigned char)0xFF); -// amfreply.addContent(AMFType("", "|RtmpSampleAccess"));//status reply -// amfreply.addContent(AMFType("", (double)1, 0x01));//bool true - audioaccess -// amfreply.addContent(AMFType("", (double)1, 0x01));//bool true - videoaccess -// SendChunk(4, 20, next.msg_stream_id, amfreply.Pack()); - chunk_snd_max = 1024*1024; - SendCTL(1, chunk_snd_max);//send chunk size max (msg 1) - ready4data = true;//start sending video data! - #ifdef DEBUG - fprintf(stderr, "AMF0 command: play result (%s)\n", streamname.c_str()); - #endif - parsed = true; - }//createStream - if (!parsed){ - #ifdef DEBUG - fprintf(stderr, "AMF0 command not processed! :(\n"); - #endif - } - } break; - case 22: - #ifdef DEBUG - fprintf(stderr, "Received aggregate message\n"); - #endif - break; - default: - #ifdef DEBUG - fprintf(stderr, "Unknown chunk received! Probably protocol corruption, stopping parsing of incoming data.\n"); - #endif - stopparsing = true; - break; - } -}//parseChunk diff --git a/Makefile b/Makefile index 9170c77c..42ead03d 100644 --- a/Makefile +++ b/Makefile @@ -3,14 +3,12 @@ default: client-install client: cd Connector_HTTP; $(MAKE) cd Connector_RTMP; $(MAKE) - cd Connector_RTMPf; $(MAKE) cd Connector_RAW; $(MAKE) #cd Connector_RTSP; $(MAKE) cd Buffer; $(MAKE) client-clean: cd Connector_HTTP; $(MAKE) clean cd Connector_RTMP; $(MAKE) clean - cd Connector_RTMPf; $(MAKE) clean cd Connector_RAW; $(MAKE) clean #cd Connector_RTSP; $(MAKE) clean cd Buffer; $(MAKE) clean @@ -20,7 +18,6 @@ client-install: client-clean client cp -f ./Connector_HTTP/Connector_HTTP /usr/bin/ cd Connector_RTMP; $(MAKE) install cp -f ./Connector_RAW/Connector_RAW /usr/bin/ - cp -f ./Connector_RTMPf/Connector_RTMPf /usr/bin/ #cp -f ./Connector_RTSP/Connector_RTSP /usr/bin/ cp -f ./Buffer/Buffer /usr/bin/ cp -f ./PLS /etc/xinetd.d/ diff --git a/PLS b/PLS index e1656837..94001b0c 100644 --- a/PLS +++ b/PLS @@ -25,18 +25,3 @@ service ddvtechraw per_source = 10 cps = 100 5 } - -service ddvtechrtmp -{ - disable = no - type = UNLISTED - protocol = tcp - socket_type = stream - user = root - server = /usr/bin/Connector_RTMPf - port = 1935 - wait = no - per_source = 10 - cps = 100 5 -} - diff --git a/util/ddv_socket.cpp b/util/ddv_socket.cpp index d8babf7a..dc4002c3 100644 --- a/util/ddv_socket.cpp +++ b/util/ddv_socket.cpp @@ -46,12 +46,12 @@ int DDV_Listen(int port){ if (ret == 0){ return s; }else{ - printf("Listen failed! Error: %s\n", strerror(errno)); + fprintf(stderr, "Listen failed! Error: %s\n", strerror(errno)); close(s); return 0; } }else{ - printf("Binding failed! Error: %s\n", strerror(errno)); + fprintf(stderr, "Binding failed! Error: %s\n", strerror(errno)); close(s); return 0; } @@ -77,7 +77,7 @@ bool DDV_write(void * buffer, int todo, int sock){ case EWOULDBLOCK: socketBlocking = true; break; default: socketError = true; - printf("Could not write! %s\n", strerror(errno)); + fprintf(stderr, "Could not write! %s\n", strerror(errno)); return false; break; } @@ -87,14 +87,14 @@ bool DDV_write(void * buffer, int todo, int sock){ return true; } -bool DDV_ready(int sock){ +signed int DDV_ready(int sock){ char tmp; int preflags = fcntl(sock, F_GETFL, 0); int postflags = preflags | O_NONBLOCK; fcntl(sock, F_SETFL, postflags); int r = recv(sock, &tmp, 1, MSG_PEEK); fcntl(sock, F_SETFL, preflags); - return (r == 1); + return r; } bool DDV_read(void * buffer, int todo, int sock){ @@ -107,7 +107,7 @@ bool DDV_read(void * buffer, int todo, int sock){ case EWOULDBLOCK: socketBlocking = true; break; default: socketError = true; - printf("Could not read! %s\n", strerror(errno)); + fprintf(stderr, "Could not read! %s\n", strerror(errno)); return false; break; } @@ -129,7 +129,7 @@ int DDV_iwrite(void * buffer, int todo, int sock){ case EWOULDBLOCK: break; default: socketError = true; - printf("Could not write! %s\n", strerror(errno)); + fprintf(stderr, "Could not write! %s\n", strerror(errno)); return false; break; } @@ -144,7 +144,7 @@ int DDV_iread(void * buffer, int todo, int sock){ case EWOULDBLOCK: break; default: socketError = true; - printf("Could not read! %s\n", strerror(errno)); + fprintf(stderr, "Could not read! %s\n", strerror(errno)); return false; break; } diff --git a/util/flv_sock.cpp b/util/flv_sock.cpp index 426aa7bd..be752d73 100644 --- a/util/flv_sock.cpp +++ b/util/flv_sock.cpp @@ -69,6 +69,7 @@ bool FLV_GetPacket(FLV_Pack *& p, int sock){ if (FLV_Checkheader(p->data)){ sofar = 0; memcpy(FLVHeader, p->data, 13); + //fwrite(p->data, 13, 1, stdout);//output raw stream }else{ All_Hell_Broke_Loose = true; fprintf(stderr, "Invalid FLV header. All Hell Broke Loose!\n"); @@ -94,12 +95,11 @@ bool FLV_GetPacket(FLV_Pack *& p, int sock){ testlen += (p->data[p->len-2] << 8); testlen += (p->data[p->len-3] << 16); testlen += (p->data[p->len-4] << 24); - if (p->len == testlen){ - fprintf(stderr, "Correct length tag...\n"); - }else{ + //fwrite(p->data, p->len, 1, stdout);//output raw stream + if (p->len != testlen){ fprintf(stderr, "Len: %i, testlen: %i\n", p->len, testlen); All_Hell_Broke_Loose = true; - fprintf(stderr, "ReadUntil fail: > 500kb tag? All Hell Broke Loose!\n", strerror(errno)); + fprintf(stderr, "ReadUntil fail: Wrong size tag? All Hell Broke Loose!\n"); return false; } done = true; From 47370e9621a301fd727d29194b608caa451dd430 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Sat, 20 Nov 2010 19:54:44 +0100 Subject: [PATCH 2/7] Rewrite Buffer programma --- Buffer/Makefile | 2 +- Buffer/buffer.h | 7 -- Buffer/main.cpp | 187 +++++++++++++++++++++++++++++----------- Buffer/user.cpp | 84 ------------------ Connector_RTMP/Makefile | 2 +- Makefile | 3 + util/ddv_socket.cpp | 37 ++++++-- 7 files changed, 175 insertions(+), 147 deletions(-) delete mode 100644 Buffer/buffer.h delete mode 100644 Buffer/user.cpp diff --git a/Buffer/Makefile b/Buffer/Makefile index a1e7bd97..aa683d41 100644 --- a/Buffer/Makefile +++ b/Buffer/Makefile @@ -1,4 +1,4 @@ -SRC = main.cpp ../sockets/sw_base.cpp ../sockets/sw_inet.cpp ../sockets/sw_unix.cpp +SRC = main.cpp OBJ = $(SRC:.cpp=.o) OUT = Buffer INCLUDES = diff --git a/Buffer/buffer.h b/Buffer/buffer.h deleted file mode 100644 index 5a18603f..00000000 --- a/Buffer/buffer.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -struct buffer{ - int number; - bool iskeyframe; - FLV_Pack * FLV; -};//buffer diff --git a/Buffer/main.cpp b/Buffer/main.cpp index 638524cb..77376630 100644 --- a/Buffer/main.cpp +++ b/Buffer/main.cpp @@ -1,62 +1,143 @@ -#include #include #include -#include "../sockets/SocketW.h" #include #include #include #include #include #include +#include #include "../util/flv.cpp" //FLV format parser -#include "user.cpp" +#include "../util/ddv_socket.cpp" //DDV Socket lib #include -int get_empty( user ** list, int amount ) { - for (int i = 0; i < amount; i++ ){ - if (!list[i]->is_connected){return i;} - } - return -1; +void termination_handler (int signum){ + return; } + +struct buffer{ + int number; + bool iskeyframe; + FLV_Pack * FLV; + buffer(){ + number = -1; + iskeyframe = false; + FLV = 0; + }//constructor +};//buffer + +class user{ + public: + int MyBuffer; + int MyBuffer_num; + int MyBuffer_len; + int MyNum; + int currsend; + void * lastpointer; + static int UserCount; + int s; + user(int fd){ + s = fd; + MyNum = UserCount++; + std::cout << "User " << MyNum << " connected" << std::endl; + }//constructor + void Disconnect(std::string reason) { + if (s != -1) { + close(s); + s = -1; + std::cout << "Disconnected user " << MyNum << ": " << reason << std::endl; + } + }//Disconnect + bool doSend(char * buffer, int todo){ + int r = send(s, buffer+currsend, todo-currsend, 0); + if (r <= 0){ + if ((r < 0) && (errno == EWOULDBLOCK)){return false;} + Disconnect("Connection closed"); + return false; + } + currsend += r; + return (currsend == todo); + } + void Send(buffer ** ringbuf, int buffers){ + //not connected? cancel + if (s < 0){return;} + //still waiting for next buffer? check it + if (MyBuffer_num < 0){ + MyBuffer_num = ringbuf[MyBuffer]->number; + //still waiting? don't crash - wait longer. + if (MyBuffer_num < 0){ + return; + }else{ + MyBuffer_len = ringbuf[MyBuffer]->FLV->len; + lastpointer = ringbuf[MyBuffer]->FLV->data; + } + } + if (lastpointer != ringbuf[MyBuffer]->FLV->data){ + Disconnect("Buffer resize at wrong time... had to disconnect"); + return; + } + if (doSend(ringbuf[MyBuffer]->FLV->data, MyBuffer_len)){ + //completed a send - switch to next buffer + if ((ringbuf[MyBuffer]->number != MyBuffer_num)){ + std::cout << "Warning: User " << MyNum << " was send corrupt video data and send to the next keyframe!" << std::endl; + int nocrashcount = 0; + do{ + MyBuffer++; + nocrashcount++; + MyBuffer %= buffers; + }while(!ringbuf[MyBuffer]->FLV->isKeyframe && (nocrashcount < buffers)); + if (nocrashcount >= buffers){ + std::cout << "Warning: No keyframe found in buffers! Skipping search for now..." << std::endl; + return; + } + }else{ + MyBuffer++; + MyBuffer %= buffers; + } + MyBuffer_num = -1; + lastpointer = 0; + currsend = 0; + }//completed a send + }//send +}; +int user::UserCount = 0; + int main( int argc, char * argv[] ) { + struct sigaction new_action; + new_action.sa_handler = termination_handler; + sigemptyset (&new_action.sa_mask); + new_action.sa_flags = 0; + sigaction (SIGPIPE, &new_action, NULL); + if (argc < 2) { std::cout << "usage: " << argv[0] << " buffers_count [streamname]" << std::endl; return 1; } - int metabuflen = 0; - char * metabuffer = 0; - int buffers = atoi(argv[1]); - buffer ** ringbuf = (buffer**) calloc (buffers,sizeof(buffer*)); - std::vector connectionList; - std::vector::iterator connIt; - for (int i = 0; i < buffers; ++i) ringbuf[i] = new buffer; - int current_buffer = 0; - int lastproper = 0;//last properly finished buffer number - unsigned int loopcount = 0; - SWUnixSocket listener(SWBaseSocket::nonblocking); - SWBaseSocket * incoming = 0; - SWBaseSocket::SWBaseError BError; - std::string shared_socket = "/tmp/shared_socket"; if (argc > 2){ shared_socket = argv[2]; shared_socket = "/tmp/shared_socket_" + shared_socket; } - unlink(shared_socket.c_str()); - listener.bind(shared_socket.c_str()); - listener.listen(50); - listener.set_timeout(0,50000); + + int metabuflen = 0; + char * metabuffer = 0; + int buffers = atoi(argv[1]); + buffer ** ringbuf = (buffer**) calloc (buffers,sizeof(buffer*)); + std::vector users; + std::vector::iterator usersIt; + for (int i = 0; i < buffers; ++i) ringbuf[i] = new buffer; + int current_buffer = 0; + int lastproper = 0;//last properly finished buffer number + unsigned int loopcount = 0; + int listener = DDV_UnixListen(shared_socket, true); + int incoming = 0; + unsigned char packtype; bool gotVideoInfo = false; bool gotAudioInfo = false; - //set stdin to be nonblocking - //int flags = fcntl(0, F_GETFL, 0); - //flags |= O_NONBLOCK; - //fcntl(0, F_SETFL, flags); - int infile = fileno(stdin); int poller = epoll_create(1); struct epoll_event ev; @@ -69,7 +150,7 @@ int main( int argc, char * argv[] ) { while(!feof(stdin) && !All_Hell_Broke_Loose){ //invalidate the current buffer ringbuf[current_buffer]->number = -1; - if ((epoll_wait(poller, events, 1, 100) > 0) && FLV_GetPacket(ringbuf[current_buffer]->FLV)){ + if ((epoll_wait(poller, events, 1, 10) > 0) && FLV_GetPacket(ringbuf[current_buffer]->FLV)){ loopcount++; packtype = ringbuf[current_buffer]->FLV->data[0]; //store metadata, if available @@ -124,35 +205,43 @@ int main( int argc, char * argv[] ) { } //check for new connections, accept them if there are any - incoming = listener.accept(&BError); - if (incoming){ - connectionList.push_back(user(incoming)); + incoming = DDV_Accept(listener, true); + if (incoming >= 0){ + users.push_back(incoming); //send the FLV header - connectionList.back().MyBuffer = lastproper; - connectionList.back().MyBuffer_num = -1; + users.back().currsend = 0; + users.back().MyBuffer = lastproper; + users.back().MyBuffer_num = -1; //TODO: Do this more nicely? - if (connectionList.back().Conn->send(FLVHeader,13,&BError) != 13){ - connectionList.back().disconnect("failed to receive the header!"); + if (!DDV_write(FLVHeader, 13, incoming)){ + users.back().Disconnect("failed to receive the header!"); }else{ - if (connectionList.back().Conn->send(metabuffer,metabuflen,&BError) != metabuflen){ - connectionList.back().disconnect("failed to receive metadata!"); + if (!DDV_write(metabuffer, metabuflen, incoming)){ + users.back().Disconnect("failed to receive metadata!"); } } - if (BError != SWBaseSocket::ok){ - connectionList.back().disconnect("Socket error: " + BError.get_error()); - } } + //send all connections what they need, if and when they need it - if (connectionList.size() > 0){ - for (connIt = connectionList.begin(); connIt != connectionList.end(); connIt++){ - if (!(*connIt).is_connected){connectionList.erase(connIt);break;} - (*connIt).Send(ringbuf, buffers); + if (users.size() > 0){ + for (usersIt = users.begin(); usersIt != users.end(); usersIt++){ + if ((*usersIt).s == -1){ + users.erase(usersIt); break; + }else{ + (*usersIt).Send(ringbuf, buffers); + } } } }//main loop // disconnect listener std::cout << "Reached EOF of input" << std::endl; - listener.disconnect(&BError); + close(listener); + while (users.size() > 0){ + for (usersIt = users.begin(); usersIt != users.end(); usersIt++){ + (*usersIt).Disconnect("Shutting down..."); + if ((*usersIt).s == -1){users.erase(usersIt);break;} + } + } return 0; } diff --git a/Buffer/user.cpp b/Buffer/user.cpp deleted file mode 100644 index 19c2878e..00000000 --- a/Buffer/user.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "buffer.h" -#include "../sockets/SocketW.h" -#include - -class user{ - public: - user(SWBaseSocket * newConn); - void disconnect(std::string reason); - void Send(buffer ** ringbuf, int buffers); - bool is_connected; - SWUnixSocket * Conn; - int MyBuffer; - int MyBuffer_num; - int MyBuffer_len; - int MyNum; - void * lastpointer; - static int UserCount; - static SWBaseSocket::SWBaseError err; -};//user - -int user::UserCount = 0; -SWBaseSocket::SWBaseError user::err; - -user::user(SWBaseSocket * newConn) { - Conn = (SWUnixSocket*)newConn; - is_connected = (Conn != 0); - MyNum = UserCount++; - std::cout << "User " << MyNum << " connected" << std::endl; -} - -void user::disconnect(std::string reason) { - if (Conn) { - Conn->disconnect(&err); - Conn = NULL; - std::cout << "Disconnected user " << MyNum << ": " << reason << std::endl; - } - is_connected = false; -} - -void user::Send(buffer ** ringbuf, int buffers){ - //not connected? cancel - if (!is_connected){return;} - //still waiting for next buffer? check it - if (MyBuffer_num < 0){ - MyBuffer_num = ringbuf[MyBuffer]->number; - //still waiting? don't crash - wait longer. - if (MyBuffer_num < 0){ - return; - }else{ - MyBuffer_len = ringbuf[MyBuffer]->FLV->len; - lastpointer = ringbuf[MyBuffer]->FLV->data; - } - } - if (lastpointer != ringbuf[MyBuffer]->FLV->data){ - disconnect("Buffer resize at wrong time... had to disconnect"); - return; - } - int ret = Conn->fsend(ringbuf[MyBuffer]->FLV->data, MyBuffer_len, &err); - if ((err != SWBaseSocket::ok) && (err != SWBaseSocket::notReady)){ - disconnect("Socket error: " + err.get_error()); - return; - } - if (ret == MyBuffer_len){ - //completed a send - switch to next buffer - if ((ringbuf[MyBuffer]->number != MyBuffer_num)){ - std::cout << "Warning: User " << MyNum << " was send corrupt video data and send to the next keyframe!" << std::endl; - int nocrashcount = 0; - do{ - MyBuffer++; - nocrashcount++; - MyBuffer %= buffers; - }while(!ringbuf[MyBuffer]->FLV->isKeyframe && (nocrashcount < buffers)); - if (nocrashcount >= buffers){ - std::cout << "Warning: No keyframe found in buffers! Skipping search for now..." << std::endl; - return; - } - }else{ - MyBuffer++; - MyBuffer %= buffers; - } - MyBuffer_num = -1; - lastpointer = 0; - } -} diff --git a/Connector_RTMP/Makefile b/Connector_RTMP/Makefile index 8a32051b..65d7cf48 100644 --- a/Connector_RTMP/Makefile +++ b/Connector_RTMP/Makefile @@ -1,4 +1,4 @@ -SRC = main.cpp ../sockets/sw_base.cpp ../sockets/sw_inet.cpp ../sockets/sw_unix.cpp +SRC = main.cpp OBJ = $(SRC:.cpp=.o) OUT = Connector_RTMP INCLUDES = diff --git a/Makefile b/Makefile index 42ead03d..a963ea54 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,9 @@ client-clean: cd Buffer; $(MAKE) clean clean: client-clean client-install: client-clean client + mkdir /tmp/cores + chmod 777 /tmp/cores + echo "/tmp/cores/%e.%s.%p" > /proc/sys/kernel/core_pattern service xinetd stop cp -f ./Connector_HTTP/Connector_HTTP /usr/bin/ cd Connector_RTMP; $(MAKE) install diff --git a/util/ddv_socket.cpp b/util/ddv_socket.cpp index dc4002c3..e7b6c099 100644 --- a/util/ddv_socket.cpp +++ b/util/ddv_socket.cpp @@ -33,7 +33,6 @@ int DDV_OpenUnix(std::string adres, bool nonblock = false){ int DDV_Listen(int port){ int s = socket(AF_INET, SOCK_STREAM, 0); - int on = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); struct sockaddr_in addr; @@ -57,9 +56,37 @@ int DDV_Listen(int port){ } } +int DDV_UnixListen(std::string adres, bool nonblock = false){ + unlink(adres.c_str()); + int s = socket(AF_UNIX, SOCK_STREAM, 0); + if (nonblock){ + int flags = fcntl(s, F_GETFL, 0); + flags |= O_NONBLOCK; + fcntl(s, F_SETFL, flags); + } + sockaddr_un addr; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, adres.c_str(), adres.size()+1); + int ret = bind(s, (sockaddr*)&addr, sizeof(addr)); + if (ret == 0){ + ret = listen(s, 100);//start listening, backlog of 100 allowed + if (ret == 0){ + return s; + }else{ + fprintf(stderr, "Listen failed! Error: %s\n", strerror(errno)); + close(s); + return 0; + } + }else{ + fprintf(stderr, "Binding failed! Error: %s\n", strerror(errno)); + close(s); + return 0; + } +} + int DDV_Accept(int sock, bool nonblock = false){ int r = accept(sock, 0, 0); - if ((r > 0) && nonblock){ + if ((r >= 0) && nonblock){ int flags = fcntl(r, F_GETFL, 0); flags |= O_NONBLOCK; fcntl(r, F_SETFL, flags); @@ -126,11 +153,11 @@ int DDV_iwrite(void * buffer, int todo, int sock){ int r = send(sock, buffer, todo, 0); if (r < 0){ switch (errno){ - case EWOULDBLOCK: break; + case EWOULDBLOCK: return 0; break; default: socketError = true; fprintf(stderr, "Could not write! %s\n", strerror(errno)); - return false; + return 0; break; } } @@ -145,7 +172,7 @@ int DDV_iread(void * buffer, int todo, int sock){ default: socketError = true; fprintf(stderr, "Could not read! %s\n", strerror(errno)); - return false; + return 0; break; } } From d43d041d5ea27b383e7b683d64ac79fc46115edb Mon Sep 17 00:00:00 2001 From: Thulinma Date: Sun, 21 Nov 2010 23:06:54 +0100 Subject: [PATCH 3/7] RTMP commandline, sigpipe signal catching, and init script changes --- Connector_RTMP/Conn_RTMP | 34 ++++++---------------------- Connector_RTMP/main.cpp | 49 ++++++++++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/Connector_RTMP/Conn_RTMP b/Connector_RTMP/Conn_RTMP index c1686a2f..1f38e92b 100755 --- a/Connector_RTMP/Conn_RTMP +++ b/Connector_RTMP/Conn_RTMP @@ -1,32 +1,22 @@ #!/bin/sh # -# chkconfig: 345 92 8 # description: DDVTech RTMP Connector -# # processname: Connector_RTMP -. /etc/rc.d/init.d/functions - prog="Connector_RTMP" fullprog="/usr/bin/Connector_RTMP" RETVAL=0 start() { - gprintf "Starting %s: " $prog - daemon --user=root $fullprog - RETVAL=$? - echo - [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog - return $RETVAL + echo "Starting $prog" + $fullprog + return $? } stop() { - gprintf "Stopping %s: " $prog - killproc $fullprog - RETVAL=$? - echo - [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog - return $RETVAL + echo "Stopping $prog" + killall $prog + return $? } case "$1" in @@ -40,18 +30,8 @@ case "$1" in stop start ;; - condrestart) - if [ -f /var/lock/subsys/$prog ]; then - stop - start - fi - ;; - status) - status $fullprog - RETVAL=$? - ;; *) - gprintf "Usage: %s {start|stop|restart|status}" $0 + echo "Usage: $0 {start|stop|restart}" RETVAL=1 esac diff --git a/Connector_RTMP/main.cpp b/Connector_RTMP/main.cpp index 70326938..0e27d067 100644 --- a/Connector_RTMP/main.cpp +++ b/Connector_RTMP/main.cpp @@ -14,6 +14,7 @@ #include #include #include +#include //for connection to server bool ready4data = false;//set to true when streaming starts @@ -49,20 +50,48 @@ int main(int argc, char ** argv){ new_action.sa_handler = termination_handler; sigemptyset (&new_action.sa_mask); new_action.sa_flags = 0; - sigaction (SIGINT, &new_action, NULL); - sigaction (SIGHUP, &new_action, NULL); - sigaction (SIGTERM, &new_action, NULL); + sigaction(SIGINT, &new_action, NULL); + sigaction(SIGHUP, &new_action, NULL); + sigaction(SIGTERM, &new_action, NULL); + sigaction(SIGPIPE, &new_action, NULL); + + int listen_port = 1935; + bool daemon_mode = true; + + int opt = 0; + static const char *optString = "np:h?"; + static const struct option longOpts[] = { + {"help",0,0,'h'}, + {"port",1,0,'p'}, + {"no-daemon",0,0,'n'} + }; + while ((opt = getopt_long(argc, argv, optString, longOpts, 0)) != -1){ + switch (opt){ + case 'p': + listen_port = atoi(optarg); + break; + case 'n': + daemon_mode = false; + break; + case 'h': + case '?': + printf("Options: -h[elp], -?, -n[o-daemon], -p[ort] #\n"); + return 1; + break; + } + } - server_socket = DDV_Listen(1935); - fprintf(stderr, "Made a listening socket on port 1936..."); - if ((argc < 2) || (strcmp(argv[1], "nd") != 0)){ - if (server_socket > 0){ + + server_socket = DDV_Listen(listen_port); + fprintf(stderr, "Made a listening socket on port %i...\n", listen_port); + if (server_socket > 0){ + if (daemon_mode){ daemon(1, 0); fprintf(stderr, "Going into background mode..."); - }else{ - fprintf(stderr, "Error: could not make listening socket"); - return 1; } + }else{ + fprintf(stderr, "Error: could not make listening socket"); + return 1; } int status; while (server_socket > 0){ From 654acfb412015ddaa3a189b222141a83660fc4c9 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Sun, 21 Nov 2010 23:08:06 +0100 Subject: [PATCH 4/7] Makefile oepsies --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a963ea54..2dbb804f 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ client-clean: cd Buffer; $(MAKE) clean clean: client-clean client-install: client-clean client - mkdir /tmp/cores + mkdir -p /tmp/cores chmod 777 /tmp/cores echo "/tmp/cores/%e.%s.%p" > /proc/sys/kernel/core_pattern service xinetd stop From d6f6d21af14983ebc185548bbd766c4e760bac1f Mon Sep 17 00:00:00 2001 From: Thulinma Date: Sun, 21 Nov 2010 23:21:18 +0100 Subject: [PATCH 5/7] New handshake, data timeout after 2 seconds --- Connector_RTMP/handshake.cpp | 2 +- Connector_RTMP/main.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Connector_RTMP/handshake.cpp b/Connector_RTMP/handshake.cpp index 3b674b35..b7ba2896 100644 --- a/Connector_RTMP/handshake.cpp +++ b/Connector_RTMP/handshake.cpp @@ -1,6 +1,6 @@ #undef OLDHANDSHAKE //change to #define for old handshake method -char versionstring[] = "PLSRTMPServer"; +char versionstring[] = "WWW.DDVTECH.COM "; #ifdef OLDHANDSHAKE struct Handshake { diff --git a/Connector_RTMP/main.cpp b/Connector_RTMP/main.cpp index 0e27d067..ede667c4 100644 --- a/Connector_RTMP/main.cpp +++ b/Connector_RTMP/main.cpp @@ -117,6 +117,7 @@ int main(int argc, char ** argv){ FLV_Pack * tag = 0; //first timestamp set + int lastcheck = getNowMS(); firsttime = getNowMS(); if (doHandshake()){ @@ -155,7 +156,10 @@ int main(int argc, char ** argv){ #endif break; case -1: break;//not ready yet - default: parseChunk(); break; + default: + parseChunk(); + lastcheck = getNowMS(); + break; } } if (ready4data){ @@ -209,6 +213,7 @@ int main(int argc, char ** argv){ tag->data[6] = ftst % 256; } SendMedia((unsigned char)tag->data[0], (unsigned char *)tag->data+11, tag->len-15, ts); + lastcheck = getNowMS(); #if DEBUG >= 4 fprintf(stderr, "Sent a tag to %i\n", CONN_fd); #endif @@ -217,7 +222,7 @@ int main(int argc, char ** argv){ } } //send ACK if we received a whole window - if (rec_cnt - rec_window_at > rec_window_size){ + if ((rec_cnt - rec_window_at > rec_window_size) || (getNowMS() - lastcheck > 1)){ rec_window_at = rec_cnt; SendCTL(3, rec_cnt);//send ack (msg 3) } From eaa1c7c26f178ed322ace6ab0064fc941a68ceb8 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Mon, 22 Nov 2010 01:52:17 +0100 Subject: [PATCH 6/7] Debugging RTMP connector, compile warning in Buffer fixed --- Buffer/main.cpp | 5 ++++- Connector_RTMP/handshake.cpp | 2 +- Connector_RTMP/main.cpp | 11 +++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Buffer/main.cpp b/Buffer/main.cpp index 77376630..243205e2 100644 --- a/Buffer/main.cpp +++ b/Buffer/main.cpp @@ -13,7 +13,10 @@ #include void termination_handler (int signum){ - return; + switch (signum){ + case SIGPIPE: return; break; + default: return; break; + } } diff --git a/Connector_RTMP/handshake.cpp b/Connector_RTMP/handshake.cpp index b7ba2896..24095c3b 100644 --- a/Connector_RTMP/handshake.cpp +++ b/Connector_RTMP/handshake.cpp @@ -24,7 +24,7 @@ bool doHandshake(){ 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] = versionstring[i%13]; + Server.Random[i] = versionstring[i%sizeof(versionstring)]; } /** Send S0 **/ DDV_write(&(Version), 1, 1, CONN_fd); diff --git a/Connector_RTMP/main.cpp b/Connector_RTMP/main.cpp index ede667c4..0f9d5a90 100644 --- a/Connector_RTMP/main.cpp +++ b/Connector_RTMP/main.cpp @@ -225,12 +225,23 @@ int main(int argc, char ** argv){ if ((rec_cnt - rec_window_at > rec_window_size) || (getNowMS() - lastcheck > 1)){ rec_window_at = rec_cnt; SendCTL(3, rec_cnt);//send ack (msg 3) + lastcheck = getNowMS(); } } close(CONN_fd); + if (inited) close(ss); #if DEBUG >= 1 if (All_Hell_Broke_Loose){fprintf(stderr, "All Hell Broke Loose\n");} fprintf(stderr, "User %i disconnected.\n", CONN_fd); + if (inited){ + fprintf(stderr, "Status was: inited\n"); + }else{ + if (ready4data){ + fprintf(stderr, "Status was: ready4data\n"); + }else{ + fprintf(stderr, "Status was: connected\n"); + } + } #endif return 0; }//main From 8093e14ce7617f67e75989268b477cad936cca06 Mon Sep 17 00:00:00 2001 From: Erik Zandvliet Date: Tue, 14 Dec 2010 10:41:15 +0100 Subject: [PATCH 7/7] Start MP4 Box container implementation --- MP4/box.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ MP4/boxheader.h | 4 ++++ 2 files changed, 62 insertions(+) create mode 100644 MP4/box.h create mode 100644 MP4/boxheader.h diff --git a/MP4/box.h b/MP4/box.h new file mode 100644 index 00000000..bab440b6 --- /dev/null +++ b/MP4/box.h @@ -0,0 +1,58 @@ +#include "boxheader.h" + +class Box { + public: + Box(); + Box(uint32_t BoxType); + ~Box(); + + void SetBoxType(uint32_t BoxType); + uint32_t GetBoxType(); + + void SetPayload(uint32_t PayloadSize, uint8_t * Data); + uint8_t * GetPayload(); + uint8_t * GetPayload(uint32_t Index, uint32_t Size); + private: + BoxHeader header; + uint8_t * Payload; +};//Box Class + +Box::Box() { + Payload = NULL; +} + +Box::Box(uint32_t BoxType) { + header.BoxType = BoxType; + Payload = NULL; +} + +Box::~Box() { +} + +void Box::SetBoxType(uint32_t BoxType) { + header.BoxType = BoxType; +} + +uint32_t Box::GetBoxType() { + return header.BoxType; +} + +void Box::SetPayload(uint32_t PayloadSize, uint8_t * Data ) { + if ( Payload != NULL ) { delete Payload; } + Payload = new uint8_t[PayloadSize]; + memcpy( Payload, Data, PayloadSize ); + header.TotalSize = PayloadSize + 8; +} + +uint8_t * Box::GetPayload() { + uint8_t * temp = new uint8_t[header.TotalSize - 8]; + memcpy( temp, Payload, header.TotalSize - 8 ); + return temp; +} + +uint8_t * Box::GetPayload(uint32_t Index, uint32_t Size) { + if( + uint8_t * temp = new uint8_t[header.TotalSize - 8]; + memcpy( temp, Payload, header.TotalSize - 8 ); + return temp; +} diff --git a/MP4/boxheader.h b/MP4/boxheader.h new file mode 100644 index 00000000..b3dbc501 --- /dev/null +++ b/MP4/boxheader.h @@ -0,0 +1,4 @@ +struct BoxHeader { + uint32_t TotalSize; + uint32_t BoxType; +};//BoxHeader struct