GF_Err RTSP_WriteCommand(GF_RTSPSession *sess, GF_RTSPCommand *com, unsigned char *req_buffer, unsigned char **out_buffer, u32 *out_size) { u32 i, cur_pos, size, count; char *buffer, temp[50]; GF_RTSPTransport *trans; GF_X_Attribute *att; *out_buffer = NULL; size = RTSP_WRITE_STEPALLOC; buffer = (char *) gf_malloc(size); cur_pos = 0; //request RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, req_buffer); //then all headers RTSP_WRITE_HEADER(buffer, size, cur_pos, "Accept", com->Accept); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Accept-Encoding", com->Accept_Encoding); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Accept-Language", com->Accept_Language); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Authorization", com->Authorization); if (com->Bandwidth) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Bandwidth: "); RTSP_WRITE_INT(buffer, size, cur_pos, com->Bandwidth, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } if (com->Blocksize) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Blocksize: "); RTSP_WRITE_INT(buffer, size, cur_pos, com->Blocksize, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Cache-Control", com->Cache_Control); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Conference", com->Conference); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Connection", com->Connection); //if we have a body write the content length if (com->body) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Content-Length: "); RTSP_WRITE_INT(buffer, size, cur_pos, (u32) strlen(com->body), 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } //write the CSeq - use the SESSION CSeq RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "CSeq: "); RTSP_WRITE_INT(buffer, size, cur_pos, sess->CSeq, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); RTSP_WRITE_HEADER(buffer, size, cur_pos, "From", com->From); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Proxy-Authorization", com->Proxy_Authorization); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Proxy-Require", com->Proxy_Require); //Range, only NPT if (com->Range && !com->Range->UseSMPTE) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Range: npt="); RTSP_WRITE_FLOAT_WITHOUT_CHECK(buffer, size, cur_pos, com->Range->start); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); if (com->Range->end > com->Range->start) { RTSP_WRITE_FLOAT_WITHOUT_CHECK(buffer, size, cur_pos, com->Range->end); } RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Referer", com->Referer); if (com->Scale != 0.0) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Scale: "); RTSP_WRITE_FLOAT_WITHOUT_CHECK(buffer, size, cur_pos, com->Scale); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Session", com->Session); if (com->Speed != 0.0) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Speed: "); RTSP_WRITE_FLOAT_WITHOUT_CHECK(buffer, size, cur_pos, com->Speed); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } //transport info count = gf_list_count(com->Transports); if (count) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Transport: "); for (i=0; i<count; i++) { //line separator for headers if (i) RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n ,"); trans = (GF_RTSPTransport *) gf_list_get(com->Transports, i); //then write the structure RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->Profile); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, (trans->IsUnicast ? ";unicast" : ";multicast")); if (trans->destination) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";destination="); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->destination); } if (trans->source) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";source="); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->source); } if (trans->IsRecord) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";mode=RECORD"); if (trans->Append) RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";append"); } if (trans->IsInterleaved) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";interleaved="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->rtpID, 0); if (trans->rtcpID != trans->rtpID) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); RTSP_WRITE_INT(buffer, size, cur_pos, trans->rtcpID, 0); } } if (trans->port_first) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, (trans->IsUnicast ? ";server_port=" : ";port=")); RTSP_WRITE_INT(buffer, size, cur_pos, trans->port_first, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); RTSP_WRITE_INT(buffer, size, cur_pos, trans->port_last, 0); } if (/*trans->IsUnicast && */trans->client_port_first) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";client_port="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->client_port_first, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); RTSP_WRITE_INT(buffer, size, cur_pos, trans->client_port_last, 0); } //multicast specific if (!trans->IsUnicast) { if (trans->MulticastLayers) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";layers="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->MulticastLayers, 0); } if (trans->TTL) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";ttl="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->TTL, 0); } } if (trans->SSRC) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";ssrc="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->SSRC, 0); } } //done with transport RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "User-Agent", com->User_Agent); //eXtensions count = gf_list_count(com->Xtensions); for (i=0; i<count; i++) { att = (GF_X_Attribute *) gf_list_get(com->Xtensions, i); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "x-"); RTSP_WRITE_HEADER(buffer, size, cur_pos, att->Name, att->Value); } //the end of header RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); //then body RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, com->body); //the end of message ? to check, should not be needed... // RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); *out_buffer = (unsigned char *)buffer; *out_size = (u32) strlen(buffer); return GF_OK; }
GF_Err RTSP_WriteResponse(GF_RTSPSession *sess, GF_RTSPResponse *rsp, unsigned char **out_buffer, u32 *out_size) { u32 i, cur_pos, size, count; char *buffer, temp[50]; GF_RTSPTransport *trans; GF_X_Attribute *att; GF_RTPInfo *info; *out_buffer = NULL; size = RTSP_WRITE_STEPALLOC; buffer = (char *) gf_malloc(size); cur_pos = 0; //RTSP line RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, GF_RTSP_VERSION); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, " "); RTSP_WRITE_INT(buffer, size, cur_pos, rsp->ResponseCode, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, " "); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, gf_rtsp_nc_to_string(rsp->ResponseCode)); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); //all headers RTSP_WRITE_HEADER(buffer, size, cur_pos, "Accept", rsp->Accept); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Accept-Encoding", rsp->Accept_Encoding); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Accept-Language", rsp->Accept_Language); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Allow", rsp->Allow); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Authorization", rsp->Authorization); if (rsp->Bandwidth) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Bandwidth: "); RTSP_WRITE_INT(buffer, size, cur_pos, rsp->Bandwidth, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } if (rsp->Blocksize) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Blocksize: "); RTSP_WRITE_INT(buffer, size, cur_pos, rsp->Blocksize, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Cache-Control", rsp->Cache_Control); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Conference", rsp->Conference); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Connection", rsp->Connection); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Content-Base", rsp->Content_Base); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Content-Encoding", rsp->Content_Encoding); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Content-Language", rsp->Content_Language); //if we have a body write the content length if (rsp->body) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Content-Length: "); RTSP_WRITE_INT(buffer, size, cur_pos, (u32) strlen(rsp->body), 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Content-Location", rsp->Content_Location); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Content-Type", rsp->Content_Type); //write the CSeq - use the RESPONSE CSeq RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "CSeq: "); RTSP_WRITE_INT(buffer, size, cur_pos, rsp->CSeq, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Date", rsp->Date); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Expires", rsp->Expires); RTSP_WRITE_HEADER(buffer, size, cur_pos, "From", rsp->From); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Host", rsp->Host); RTSP_WRITE_HEADER(buffer, size, cur_pos, "If-Match", rsp->If_Match); RTSP_WRITE_HEADER(buffer, size, cur_pos, "If-Modified-Since", rsp->If_Modified_Since); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Last-Modified", rsp->Last_Modified); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Location", rsp->Location); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Proxy-Authenticate", rsp->Proxy_Authenticate); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Proxy-Require", rsp->Proxy_Require); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Public", rsp->Public); //Range, only NPT if (rsp->Range && !rsp->Range->UseSMPTE) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Range: npt:"); RTSP_WRITE_FLOAT_WITHOUT_CHECK(buffer, size, cur_pos, rsp->Range->start); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); if (rsp->Range->end > rsp->Range->start) { RTSP_WRITE_FLOAT_WITHOUT_CHECK(buffer, size, cur_pos, rsp->Range->end); } RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Referer", rsp->Referer); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Require", rsp->Require); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Retry-After", rsp->Retry_After); //RTP Infos count = gf_list_count(rsp->RTP_Infos); if (count) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "RTPInfo: "); for (i=0; i<count; i++) { //line separator for headers if (i) RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n ,"); info = (GF_RTPInfo*)gf_list_get(rsp->RTP_Infos, i); if (info->url) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "url="); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, info->url); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";"); } RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "seq="); RTSP_WRITE_INT(buffer, size, cur_pos, info->seq, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";rtptime="); RTSP_WRITE_INT(buffer, size, cur_pos, info->rtp_time, 0); } RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } if (rsp->Scale != 0.0) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Scale: "); RTSP_WRITE_FLOAT_WITHOUT_CHECK(buffer, size, cur_pos, rsp->Scale); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Server", rsp->Server); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Session", rsp->Session); if (rsp->Speed != 0.0) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Scale: "); RTSP_WRITE_FLOAT_WITHOUT_CHECK(buffer, size, cur_pos, rsp->Speed); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Timestamp", rsp->Timestamp); //transport info count = gf_list_count(rsp->Transports); if (count) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Transport: "); for (i=0; i<count; i++) { //line separator for headers if (i) RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n ,"); trans = (GF_RTSPTransport*)gf_list_get(rsp->Transports, i); //then write the structure RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->Profile); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, (trans->IsUnicast ? ";unicast" : ";multicast")); if (trans->destination) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";destination="); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->destination); } if (trans->source) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";source="); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->source); } if (trans->IsRecord) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";mode=RECORD"); if (trans->Append) RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";append"); } if (trans->IsInterleaved) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";interleaved="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->rtpID, 0); if (trans->rtcpID != trans->rtpID) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); RTSP_WRITE_INT(buffer, size, cur_pos, trans->rtcpID, 0); } } //multicast specific if (!trans->IsUnicast) { if (trans->MulticastLayers) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";layers="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->MulticastLayers, 0); } if (trans->TTL) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";ttl="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->TTL, 0); } } if (trans->port_first) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, (const char *) (trans->IsUnicast ? ";server_port=" : ";port=")); RTSP_WRITE_INT(buffer, size, cur_pos, trans->port_first, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); RTSP_WRITE_INT(buffer, size, cur_pos, trans->port_last, 0); } if (trans->IsUnicast && trans->client_port_first) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";client_port="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->client_port_first, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); RTSP_WRITE_INT(buffer, size, cur_pos, trans->client_port_last, 0); } if (trans->SSRC) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";ssrc="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->SSRC, 0); } } //done with transport RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Unsupported", rsp->Unsupported); RTSP_WRITE_HEADER(buffer, size, cur_pos, "User-Agent", rsp->User_Agent); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Vary", rsp->Vary); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Via", rsp->Via); RTSP_WRITE_HEADER(buffer, size, cur_pos, "WWW-Authenticate", rsp->WWW_Authenticate); //eXtensions count = gf_list_count(rsp->Xtensions); for (i=0; i<count; i++) { att = (GF_X_Attribute*)gf_list_get(rsp->Xtensions, i); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "x-"); RTSP_WRITE_HEADER(buffer, size, cur_pos, att->Name, att->Value); } //end of header RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); //then body RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, rsp->body); *out_buffer = (unsigned char *) buffer; *out_size = (u32) strlen(buffer); return GF_OK; }