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

📄 rtsp_func.c

📁 RTSP状态机
💻 C
字号:
#include "rtsp_func.h"
/*
 *	函数 char *get_stat(int err) :
 *	用于获取状态值对应返回状态
 */
char *get_stat(int err)
{
	struct {
		char *token;
		int code;
	} status[] = {
		{
		"Continue", 100}, {
		"OK", 200}, {
		"Created", 201}, {
		"Accepted", 202}, {
		"Non-Authoritative Information", 203}, {
		"No Content", 204}, {
		"Reset Content", 205}, {
		"Partial Content", 206}, {
		"Multiple Choices", 300}, {
		"Moved Permanently", 301}, {
		"Moved Temporarily", 302}, {
		"Bad Request", 400}, {
		"Unauthorized", 401}, {
		"Payment Required", 402}, {
		"Forbidden", 403}, {
		"Not Found", 404}, {
		"Method Not Allowed", 405}, {
		"Not Acceptable", 406}, {
		"Proxy Authentication Required", 407}, {
		"Request Time-out", 408}, {
		"Conflict", 409}, {
		"Gone", 410}, {
		"Length Required", 411}, {
		"Precondition Failed", 412}, {
		"Request Entity Too Large", 413}, {
		"Request-URI Too Large", 414}, {
		"Unsupported Media Type", 415}, {
		"Bad Extension", 420}, {
		"Invalid Parameter", 450}, {
		"Parameter Not Understood", 451}, {
		"Conference Not Found", 452}, {
		"Not Enough Bandwidth", 453}, {
		"Session Not Found", 454}, {
		"Method Not Valid In This State", 455}, {
		"Header Field Not Valid for Resource", 456}, {
		"Invalid Range", 457}, {
		"Parameter Is Read-Only", 458}, {
		"Unsupported transport", 461}, {
		"Internal Server Error", 500}, {
		"Not Implemented", 501}, {
		"Bad Gateway", 502}, {
		"Service Unavailable", 503}, {
		"Gateway Time-out", 504}, {
		"RTSP Version Not Supported", 505}, {
		"Option not supported", 551}, {
		"Extended Error:", 911}, {
		NULL, -1}
	};
	int i;
	for (i = 0; status[i].code != err && status[i].code != -1; ++i);
	return status[i].token;
}
/**********************************************************************/

/*
 *	函数 void RTSP_state_machine(RTSP_buffer * rtsp, int method) :
 *	RTSP协议状态机
 */
void RTSP_state_machine(RTSP_buffer * rtsp, int method)
{
	/*
	 * All state transitions are made here except when the last stream packet
	 * is sent during a PLAY.  That transition is located in stream_event().
	 */
	char *s;
	RTSP_session *p;
	long int session_id;
	char trash[255];

	if ((s = strstr(rtsp->in_buffer, HDR_SESSION)) != NULL) {
		if (sscanf(s, "%254s %ld", trash, &session_id) != 2) {
			printf("Invalid Session number in Session header\n");
			send_reply(454, 0, rtsp);	/* Session Not Found */
			return;
		}
	}
	p = rtsp->session_list;
	if (p == NULL) {
		return;
	}
	switch (p->cur_state) {
	case INIT_STATE:{
			switch (method) {
			case RTSP_ID_DESCRIBE:
				RTSP_describe(rtsp);
				break;
			case RTSP_ID_SETUP:
				if (RTSP_setup(rtsp, &p) == ERR_NOERROR) {
					p->cur_state = READY_STATE;
				}
				break;
			case RTSP_ID_TEARDOWN:
				// if (RTSP_teardown(rtsp) == ERR_NOERROR) { // shawill
				// p->cur_state = INIT_STATE;
				// }
				RTSP_teardown(rtsp);
				break;
			case RTSP_ID_OPTIONS:
				if (RTSP_options(rtsp) == ERR_NOERROR) {
					p->cur_state = INIT_STATE;
				}
				break;
			case RTSP_ID_PLAY:	/* method not valid this state. */
			case RTSP_ID_PAUSE:
				send_reply(455, "Accept: OPTIONS, DESCRIBE, SETUP, TEARDOWN\n", rtsp);
				break;
			default:
				send_reply(501, "Accept: OPTIONS, DESCRIBE, SETUP, TEARDOWN\n", rtsp);
				break;
			}
			break;
		}		/* INIT state */
	case READY_STATE:{
			switch (method) {
			case RTSP_ID_PLAY:
				if (RTSP_play(rtsp) == ERR_NOERROR) {
					p->cur_state = PLAY_STATE;
				}
				break;
			case RTSP_ID_SETUP:
				if (RTSP_setup(rtsp, &p) == ERR_NOERROR) {
					p->cur_state = READY_STATE;
				}
				break;
			case RTSP_ID_TEARDOWN:
				// if (RTSP_teardown(rtsp) == ERR_NOERROR) { // shawill
				// p->cur_state = INIT_STATE;
				// }
				RTSP_teardown(rtsp);
				break;
			case RTSP_ID_OPTIONS:
				break;
			case RTSP_ID_PAUSE:	/* method not valid this state. */
				send_reply(455, "Accept: OPTIONS, SETUP, PLAY, TEARDOWN\n", rtsp);
				break;
			case RTSP_ID_DESCRIBE:
				RTSP_describe(rtsp);
				break;
			default:
				send_reply(501, "Accept: OPTIONS, SETUP, PLAY, TEARDOWN\n", rtsp);
				break;
			}
			break;
		}		/* READY state */
	case PLAY_STATE:{
			switch (method) {
			case RTSP_ID_PLAY:
				// Feature not supported
				printf("UNSUPPORTED: Play while playing.\n");
				send_reply(551, 0, rtsp);	/* Option not supported */
				break;
			case RTSP_ID_PAUSE:
				if (RTSP_pause(rtsp) == ERR_NOERROR) {
					p->cur_state = READY_STATE;
				}
				break;
			case RTSP_ID_TEARDOWN:
				// if (RTSP_teardown(rtsp) == ERR_NOERROR) { // shawill
				// p->cur_state = INIT_STATE;
				// }
				RTSP_teardown(rtsp);
				break;
			case RTSP_ID_OPTIONS:
				break;
			case RTSP_ID_DESCRIBE:
				RTSP_describe(rtsp);
				break;
			case RTSP_ID_SETUP:
				break;
			}
			break;
		}		/* PLAY state */
	default:{		/* invalid/unexpected current state. */
			printf("State error: unknown state=%d, method code=%d\n", p->cur_state, method);
		}
		break;
	}			/* end of current state switch */
}

/**********************************************************************/
 
/*
 *	函数send_reply(int err, char *addon, RTSP_buffer * rtsp) :
 *	服务器回复消息通过此函数存入RTSP_buffer,err为对应的消息号。
 */
int send_reply(int err, char *addon, RTSP_buffer * rtsp)
{
	unsigned int len;
	char *b;
	char *p;
	int res;
	char method[32];
	char object[256];
	char ver[32];

	if (addon != NULL) {
		len = 256 + strlen(addon);
	} else {
		len = 256;
	}

	b = (char *) malloc(len);
	if (b == NULL) {
		printf("send_reply(): memory allocation error.\n");
		return ERR_ALLOC;
	}
	memset(b, 0, sizeof(b));
	sprintf(b, "%s %d %s\r\nCSeq: %d\r\n\r\n", RTSP_VER, err, get_stat(err), rtsp->rtsp_cseq);

	res = bwrite(b, (unsigned short) strlen(b), rtsp);
	free(b);
	
	sscanf(rtsp->in_buffer, " %31s %255s %31s ", method, object, ver);
	printf("%s %s %s %d - - ", method, object, ver, err);
	
	return res;
}

/**********************************************************************/

/**********************************************************************/
 
/*
 *	函数  :
 *	用于获取状态值对应返回状态
 */

/**********************************************************************/

/**********************************************************************/
 
/*
 *	函数  :
 *	用于获取状态值对应返回状态
 */

/**********************************************************************/

/**********************************************************************/
 
/*
 *	函数  :
 *	用于获取状态值对应返回状态
 */

/**********************************************************************/

/**********************************************************************/
 
/*
 *	函数  :
 *	用于获取状态值对应返回状态
 */

/**********************************************************************/

/**********************************************************************/
 
/*
 *	函数 bwrite(char *buffer, unsigned short len, RTSP_buffer * rtsp) :
 *	把buffer中的数据写到RTSP_buffer结构体中
 */
int bwrite(char *buffer, unsigned short len, RTSP_buffer * rtsp)
{
	if ((rtsp->out_size + len) > (int) sizeof(rtsp->out_buffer)) {
		fnc_log(FNC_LOG_ERR,"bwrite(): not enough free space in out message buffer.\n");
		return ERR_ALLOC;
	}
	memcpy(&(rtsp->out_buffer[rtsp->out_size]), buffer, len);
	rtsp->out_buffer[rtsp->out_size + len] = '\0';
	rtsp->out_size += len;
	return ERR_NOERROR;
}
/**********************************************************************/

/**********************************************************************/
 
/*
 *	函数  :
 *	用于获取状态值对应返回状态
 */

/**********************************************************************/

⌨️ 快捷键说明

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