⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsp_command.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
		&& strcmp(com->method, GF_RTSP_TEARDOWN)		&& strcmp(com->method, GF_RTSP_OPTIONS)		) return GF_BAD_PARAM;	//check the state machine	if (strcmp(com->method, GF_RTSP_PLAY) 		&& strcmp(com->method, GF_RTSP_PAUSE) 		&& strcmp(com->method, GF_RTSP_RECORD)		&& sess->RTSP_State != GF_RTSP_STATE_INIT) 		return GF_SERVICE_ERROR;	//aggregation is ONLY for the same request - unclear in RFC2326 ...	//it is often mentioned "queued requests" at the server, like 3 PLAYS	//and a PAUSE ....		/*	else if (sess->RTSP_State == GF_RTSP_STATE_WAIT_FOR_CONTROL 		&& strcmp(com->method, sess->RTSPLastRequest))		&& strcmp(com->method, GF_RTSP_OPTIONS))		return GF_BAD_PARAM;*/	//OPTIONS must have a parameter string 	if (!strcmp(com->method, GF_RTSP_OPTIONS) && !sCtrl) return GF_BAD_PARAM;	//update sequence number	sess->CSeq += 1;	sess->NbPending += 1;	if (!strcmp(com->method, GF_RTSP_OPTIONS)) {		sprintf(buffer, "OPTIONS %s %s\r\n", sCtrl, GF_RTSP_VERSION);	} else {		rad = (sess->ConnectionType == GF_SOCK_TYPE_TCP) ? "rtsp" : "rtspu";		if (sCtrl) {			//if both server and service names are included in the control, just			//use the control			if (strstr(sCtrl, sess->Server) && strstr(sCtrl, sess->Service)) {				sprintf(buffer, "%s %s %s\r\n", com->method, sCtrl, GF_RTSP_VERSION);			}			//if service is specified in ctrl, do not rewrite it			else if (strstr(sCtrl, sess->Service)) {				sprintf(buffer, "%s %s://%s:%d/%s %s\r\n", com->method, rad, sess->Server, sess->Port, sCtrl, GF_RTSP_VERSION);			}			else if (!strnicmp(sCtrl, "rtsp", 4)) {				sprintf(buffer, "%s %s %s\r\n", com->method, sCtrl, GF_RTSP_VERSION);			}			//otherwise rewrite full URL			else {				sprintf(buffer, "%s %s://%s/%s/%s %s\r\n", com->method, rad, sess->Server, sess->Service, sCtrl, GF_RTSP_VERSION);//				sprintf(buffer, "%s %s://%s:%d/%s/%s %s\r\n", com->method, rad, sess->Server, sess->Port, sess->Service, sCtrl, GF_RTSP_VERSION);			}		} else {			sprintf(buffer, "%s %s://%s:%d/%s %s\r\n", com->method, rad, sess->Server, sess->Port, sess->Service, GF_RTSP_VERSION);		}	}	//Body on ANNOUNCE, GET_PARAMETER, SET_PARAMETER ONLY	body = NULL;	if (strcmp(com->method, GF_RTSP_ANNOUNCE) 		&& strcmp(com->method, GF_RTSP_GET_PARAMETER) 		&& strcmp(com->method, GF_RTSP_SET_PARAMETER) 		) {		//this is an error, but don't say anything		if (com->body) {			body = com->body;			com->body = NULL;		}	}	result = NULL;	e = RTSP_WriteCommand(sess, com, (unsigned char *)buffer, (unsigned char **) &result, &size);	//restore body if needed	if (body) com->body = body;	if (e) goto exit;	GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTSP] Sending Command:\n%s\n", result));	//send buffer	e = gf_rtsp_send_data(sess, result, size);	if (e) goto exit;	//update our state	if (!strcmp(com->method, GF_RTSP_RECORD)) sess->RTSP_State = GF_RTSP_STATE_WAIT_FOR_CONTROL;	else if (!strcmp(com->method, GF_RTSP_PLAY)) sess->RTSP_State = GF_RTSP_STATE_WAIT_FOR_CONTROL;	else if (!strcmp(com->method, GF_RTSP_PAUSE)) sess->RTSP_State = GF_RTSP_STATE_WAIT_FOR_CONTROL;	else sess->RTSP_State = GF_RTSP_STATE_WAITING;	//teardown invalidates the session most of the time, so we force the user to wait for the reply	//as the reply may indicate a connection-closed	strcpy(sess->RTSPLastRequest, com->method);exit:	if (result) free(result);	return e;}void gf_rtsp_set_command_value(GF_RTSPCommand *com, char *Header, char *Value){	char LineBuffer[400];	s32 LinePos;	GF_RTSPTransport *trans;	GF_X_Attribute *x_Att;	if (!stricmp(Header, "Accept")) com->Accept = strdup(Value);	else if (!stricmp(Header, "Accept-Encoding")) com->Accept_Encoding = strdup(Value);	else if (!stricmp(Header, "Accept-Language")) com->Accept_Language = strdup(Value);	else if (!stricmp(Header, "Authorization")) com->Authorization = strdup(Value);	else if (!stricmp(Header, "Bandwidth")) sscanf(Value, "%d", &com->Bandwidth);	else if (!stricmp(Header, "Blocksize")) sscanf(Value, "%d", &com->Blocksize);	else if (!stricmp(Header, "Cache-Control")) com->Cache_Control = strdup(Value);	else if (!stricmp(Header, "Conference")) com->Conference = strdup(Value);	else if (!stricmp(Header, "Connection")) com->Connection = strdup(Value);	else if (!stricmp(Header, "Content-Length")) sscanf(Value, "%d", &com->Content_Length);	else if (!stricmp(Header, "CSeq")) sscanf(Value, "%d", &com->CSeq);	else if (!stricmp(Header, "From")) com->From = strdup(Value);	else if (!stricmp(Header, "Proxy_Authorization")) com->Proxy_Authorization = strdup(Value);	else if (!stricmp(Header, "Proxy_Require")) com->Proxy_Require = strdup(Value);	else if (!stricmp(Header, "Range")) com->Range = gf_rtsp_range_parse(Value);	else if (!stricmp(Header, "Referer")) com->Referer = strdup(Value);	else if (!stricmp(Header, "Scale")) sscanf(Value, "%lf", &com->Scale);	else if (!stricmp(Header, "Session")) com->Session = strdup(Value);	else if (!stricmp(Header, "Speed")) sscanf(Value, "%lf", &com->Speed);	else if (!stricmp(Header, "User_Agent")) com->User_Agent = strdup(Value);	//Transports	else if (!stricmp(Header, "Transport")) {		LinePos = 0;		while (1) {			LinePos = gf_token_get(Value, LinePos, "\r\n", LineBuffer, 400);			if (LinePos <= 0) return;			trans = gf_rtsp_transport_parse(Value);			if (trans) gf_list_add(com->Transports, trans);		}	}	//eXtensions attributes	else if (!strnicmp(Header, "x-", 2)) {		x_Att = (GF_X_Attribute*)malloc(sizeof(GF_X_Attribute));		x_Att->Name = strdup(Header+2);		x_Att->Value = NULL;		if (Value && strlen(Value)) x_Att->Value = strdup(Value);		gf_list_add(com->Xtensions, x_Att);	}	//the rest is ignored}GF_Err RTSP_ParseCommandHeader(GF_RTSPSession *sess, GF_RTSPCommand *com, u32 BodyStart){	char LineBuffer[1024];	char ValBuf[1024];	char *buffer;	s32 Pos, ret;	u32 Size;	Size = sess->CurrentSize - sess->CurrentPos;	buffer = sess->TCPBuffer + sess->CurrentPos;	//by default the command is wrong ;)	com->StatusCode = NC_RTSP_Bad_Request;	//parse first line	ret = gf_token_get_line(buffer, 0, Size, LineBuffer, 1024);	if (ret < 0) return GF_REMOTE_SERVICE_ERROR;	//method	Pos = gf_token_get(LineBuffer, 0, " \t\r\n", ValBuf, 1024);	if (Pos <= 0) return GF_OK;	com->method = strdup((const char *) ValBuf);	//URL	Pos = gf_token_get(LineBuffer, Pos, " \t\r\n", ValBuf, 1024);	if (Pos <= 0) return GF_OK;	com->service_name = strdup(ValBuf);		//RTSP version	Pos = gf_token_get(LineBuffer, Pos, "\t\r\n", ValBuf, 1024);	if (Pos <= 0) return GF_OK;	if (strcmp(ValBuf, GF_RTSP_VERSION)) {		com->StatusCode = NC_RTSP_RTSP_Version_Not_Supported;		return GF_OK;	}	com->StatusCode = NC_RTSP_OK;		return gf_rtsp_parse_header(buffer + ret, Size - ret, BodyStart, com, NULL);}GF_EXPORTGF_Err gf_rtsp_get_command(GF_RTSPSession *sess, GF_RTSPCommand *com){	GF_Err e;	u32 BodyStart, size;	if (!sess || !com) return GF_BAD_PARAM;	//reset the command	gf_rtsp_command_reset(com);	//if no connection, we have sent a "Connection: Close"	if (!sess->connection) return GF_IP_CONNECTION_CLOSED;	//lock	gf_mx_p(sess->mx);	//fill TCP buffer	e = gf_rtsp_fill_buffer(sess);	if (e) goto exit;	//this is upcoming, interleaved data	if (strncmp(sess->TCPBuffer+sess->CurrentPos, "RTSP", 4)) {		e = GF_IP_NETWORK_EMPTY;		goto exit;	}	e = gf_rtsp_read_reply(sess);	if (e) goto exit;	gf_rtsp_get_body_info(sess, &BodyStart, &size);	e = RTSP_ParseCommandHeader(sess, com, BodyStart);	//before returning an error we MUST reset the TCP buffer	//copy the body if any	if (!e && com->Content_Length) {		com->body = (char *) malloc(sizeof(char) * (com->Content_Length));		memcpy(com->body, sess->TCPBuffer+sess->CurrentPos + BodyStart, com->Content_Length);	}		//reset TCP buffer	sess->CurrentPos += BodyStart + com->Content_Length;	if (!com->CSeq) com->StatusCode = NC_RTSP_Bad_Request;	if (e || (com->StatusCode != NC_RTSP_OK)) goto exit;	//NB: there is no "session state" in our lib when acting at the server side, as it depends	//on the server implementation. We cannot block responses / announcement to be sent	//dynamically, nor reset the session ourselves as we don't know the details of the session	//(eg TEARDOWN may keep resources up or not, ...)	//we also have the same pb for CSeq, as nothing forbids a server to buffer commands (and it 	//happens during aggregation of PLAY/PAUSE with overlapping ranges)	//however store the last CSeq in case for client checking	if (!sess->CSeq) {		sess->CSeq = com->CSeq;	}	//check we're in the right range	else {		if (sess->CSeq >= com->CSeq) 			com->StatusCode = NC_RTSP_Header_Field_Not_Valid;		else			sess->CSeq = com->CSeq;	}	//	//if a connection closed is signal, check this is the good session	// and reset it (the client is no longer connected)	if (sess->last_session_id && com->Session && !strcmp(com->Session, sess->last_session_id) 		&& com->Connection && !stricmp(com->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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -