📄 rtsp_response.c
字号:
return 0;}GF_EXPORTGF_Err gf_rtsp_get_response(GF_RTSPSession *sess, GF_RTSPResponse *rsp){ GF_Err e; u32 BodyStart, size; if (!sess || !rsp) return GF_BAD_PARAM; gf_rtsp_response_reset(rsp); //LOCK gf_mx_p(sess->mx); e = gf_rtsp_check_connection(sess); if (e) goto exit; //push data in our queue e = gf_rtsp_fill_buffer(sess); if (e) goto exit; //this is interleaved data if (!IsRTSPMessage(sess->TCPBuffer+sess->CurrentPos) ) { gf_rtsp_session_read(sess); e = GF_IP_NETWORK_EMPTY; goto exit; } e = gf_rtsp_read_reply(sess); if (e) goto exit; //get the reply gf_rtsp_get_body_info(sess, &BodyStart, &size); e = RTSP_ParseResponseHeader(sess, rsp, BodyStart); //copy the body if any if (!e && rsp->Content_Length) { rsp->body = (char *)malloc(sizeof(char) * (rsp->Content_Length)); memcpy(rsp->body, sess->TCPBuffer+sess->CurrentPos + BodyStart, rsp->Content_Length); } GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTSP] Got Response:\n%s\n", sess->TCPBuffer+sess->CurrentPos)); //reset TCP buffer sess->CurrentPos += BodyStart + rsp->Content_Length; if (e) goto exit; //update RTSP aggreagation info if (sess->NbPending) sess->NbPending -= 1; if (sess->RTSP_State == GF_RTSP_STATE_WAITING) sess->RTSP_State = GF_RTSP_STATE_INIT; //control, and everything is recieved else if (sess->RTSP_State == GF_RTSP_STATE_WAIT_FOR_CONTROL) { if (!sess->NbPending) sess->RTSP_State = GF_RTSP_STATE_INIT; } //this is a late reply to an aggregated control - signal nothing if (!strcmp(sess->RTSPLastRequest, "RESET") && sess->CSeq > rsp->CSeq) { e = GF_IP_NETWORK_EMPTY; goto exit; } //reset last request if (sess->RTSP_State == GF_RTSP_STATE_INIT) strcpy(sess->RTSPLastRequest, ""); //check the CSeq is in the right range. The server should ALWAYS reply in sequence //to an aggreagated sequence of requests //if we have reseted the connection (due to an APP error) return empty if (sess->CSeq > rsp->CSeq + sess->NbPending) { gf_mx_v(sess->mx); return gf_rtsp_get_response(sess, rsp); } if (sess->CSeq != rsp->CSeq + sess->NbPending) { e = GF_REMOTE_SERVICE_ERROR; goto exit; } /*check session ID*/ if (rsp->Session && sess->last_session_id && strcmp(sess->last_session_id, rsp->Session)) { e = GF_REMOTE_SERVICE_ERROR; goto exit; } //destroy sessionID if needed - real doesn't close the connection when destroying //session if (!strcmp(sess->RTSPLastRequest, GF_RTSP_TEARDOWN)) { sess->last_session_id = NULL; } if (rsp->Connection && !stricmp(rsp->Connection, "Close")) { gf_rtsp_session_reset(sess, 0); //destroy the socket if (sess->connection) gf_sk_del(sess->connection); sess->connection = NULL; //destroy the http tunnel if any if (sess->HasTunnel && sess->http) { gf_sk_del(sess->http); sess->http = NULL; } } exit: gf_mx_v(sess->mx); return e;}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 *) 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, 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(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(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(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(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, 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 = strlen(buffer); return GF_OK;}GF_EXPORTGF_Err gf_rtsp_send_response(GF_RTSPSession *sess, GF_RTSPResponse *rsp){ u32 size; char *buffer; GF_Err e; if (!sess || !rsp || !rsp->CSeq) return GF_BAD_PARAM; //check we're not sending something greater than the current CSeq if (rsp->CSeq > sess->CSeq) return GF_BAD_PARAM; e = RTSP_WriteResponse(sess, rsp, (unsigned char **) &buffer, &size); if (e) goto exit; //send buffer e = gf_rtsp_send_data(sess, buffer, size); if (e) return e;// printf("RTSP Send Response\n\n%s\n\n", buffer);exit: if (buffer) free(buffer); return e;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -