mistserver/Connector_RTMP/parsechunks.cpp

115 lines
4.9 KiB
C++

#include "chunkstream.cpp" //chunkstream decoding
#include "amf.cpp" //simple AMF0 parsing
//gets and parses one chunk
void parseChunk(){
static chunkpack next;
static AMFType amfdata("empty", (unsigned char)0xFF);
static AMFType amfelem("empty", (unsigned char)0xFF);
static int tmpint;
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);
fprintf(stderr, "CTRL: Set chunk size: %i\n", chunk_rec_max);
break;
case 2://abort message - we ignore this one
fprintf(stderr, "CTRL: Abort message\n");
//4 bytes of stream id to drop
break;
case 3://ack
fprintf(stderr, "CTRL: Acknowledgement\n");
snd_window_at = ntohl(*(int*)next.data);
//maybe better? snd_window_at = snd_cnt;
break;
case 4:{
short int ucmtype = ntohs(*(short int*)next.data);
fprintf(stderr, "CTRL: User control message %hi\n", ucmtype);
//2 bytes event type, rest = event data
//we don't need to process this
} break;
case 5://window size of other end
fprintf(stderr, "CTRL: Window size\n");
rec_window_size = ntohl(*(int*)next.data);
break;
case 6:
fprintf(stderr, "CTRL: Set peer bandwidth\n");
//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:
fprintf(stderr, "Received audio data\n");
break;
case 9:
fprintf(stderr, "Received video data\n");
break;
case 15:
fprintf(stderr, "Received AFM3 data message\n");
break;
case 16:
fprintf(stderr, "Received AFM3 shared object\n");
break;
case 17:
fprintf(stderr, "Received AFM3 command message\n");
break;
case 18:
fprintf(stderr, "Received AFM0 data message\n");
break;
case 19:
fprintf(stderr, "Received AFM0 shared object\n");
break;
case 20:{//AMF0 command message
amfdata = parseAMF(next.data, next.real_len);
fprintf(stderr, "Received AFM0 command message:\n");
amfdata.Print();
if (amfdata.getContentP(0)->StrValue() == "connect"){
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");}
//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 - properties (none?)
amfreply.addContent(AMFType(""));//info
amfreply.getContentP(3)->addContent(AMFType("level", "status"));
amfreply.getContentP(3)->addContent(AMFType("code", "NetConnection.Connect.Sucess"));
amfreply.getContentP(3)->addContent(AMFType("description", "Connection succeeded."));
SendChunk(3, 20, next.msg_stream_id, amfreply.Pack());
SendCTL(5, snd_window_size);//send window acknowledgement size (msg 5)
SendCTL(5, rec_window_size, 1);//send peer bandwidth (msg 6)
SendUSR(0, 10);//send UCM StreamBegin (0), stream 10 (we use this number)
}//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)10));//stream ID - we use 10
SendChunk(3, 20, next.msg_stream_id, amfreply.Pack());
}//createStream
if ((amfdata.getContentP(0)->StrValue() == "play") || (amfdata.getContentP(0)->StrValue() == "play2")){
//send a status reply
AMFType amfreply("container", (unsigned char)0xFF);
amfreply.addContent(AMFType("", "onStatus"));//status reply
amfreply.addContent(AMFType("", "NetStream.Play.Start"));//result success
SendChunk(3, 20, next.msg_stream_id, amfreply.Pack());
ready4data = true;//start sending video data!
}//createStream
} break;
case 22:
fprintf(stderr, "Received aggregate message\n");
break;
default:
fprintf(stderr, "Unknown chunk received!\n");
break;
}
}//parseChunk