/* macchina a stati dell'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) {
			fnc_log(FNC_LOG_INFO,"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
				fnc_log(FNC_LOG_INFO,"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. */
			fnc_log(FNC_LOG_ERR,"State error: unknown state=%d, method code=%d\n", p->cur_state, method);
		}
		break;
	}			/* end of current state switch */
}
Beispiel #2
0
/*rtsp状态机,服务器端*/
void RTSP_state_machine(RTSP_buffer * pRtspBuf, int method)
{

#ifdef RTSP_DEBUG
	trace_point();
#endif

    /*除了播放过程中发送的最后一个数据流,
     *所有的状态迁移都在这里被处理
     * 状态迁移位于stream_event中
     */
    char *s;
    RTSP_session *pRtspSess;
    long int session_id;
    char trash[255];
    char szDebug[255];

    /*找到会话位置*/
    if ((s = strstr(pRtspBuf->in_buffer, HDR_SESSION)) != NULL)
    {
        if (sscanf(s, "%254s %ld", trash, &session_id) != 2)
        {
            fprintf(stderr,"Invalid Session number %s,%i\n", __FILE__, __LINE__);
            send_reply(454, 0, pRtspBuf);              /* 没有此会话*/
            return;
        }
    }

    /*打开会话列表*/
    pRtspSess = pRtspBuf->session_list;
    if (pRtspSess == NULL)
    {
        return;
    }

#ifdef RTSP_DEBUG
    sprintf(szDebug,"state_machine:current state is  ");
    strcat(szDebug,((pRtspSess->cur_state==0)?"init state":((pRtspSess->cur_state==1)?"ready state":"play state")));
    printf("%s\n", szDebug);
#endif

    /*根据状态迁移规则,从当前状态开始迁移*/
    switch (pRtspSess->cur_state)
    {
        case INIT_STATE:                    /*初始态*/
        {
#ifdef RTSP_DEBUG
        	fprintf(stderr,"current method code is:  %d  \n",method);
#endif
            switch (method)
            {
                case RTSP_ID_DESCRIBE:  //状态不变
                    RTSP_describe(pRtspBuf);
					//printf("3\r\n");
                    break;

                case RTSP_ID_SETUP:                //状态变为就绪态
					//printf("4\r\n");
                  if (RTSP_setup(pRtspBuf) == ERR_NOERROR)
                    {
						//printf("5\r\n");
                    	pRtspSess->cur_state = READY_STATE;
                        fprintf(stderr,"TRANSFER TO READY STATE!\n");
                    }
                    break;

                case RTSP_ID_TEARDOWN:       //状态不变
                    RTSP_teardown(pRtspBuf);
                    break;

                case RTSP_ID_OPTIONS:
                    if (RTSP_options(pRtspBuf) == ERR_NOERROR)
                    {
                    	pRtspSess->cur_state = INIT_STATE;         //状态不变
                    }
                    break;

                case RTSP_ID_PLAY:          //method not valid this state.

                case RTSP_ID_PAUSE:
                    send_reply(455, 0, pRtspBuf);
                    break;

                default:
                    send_reply(501, 0, pRtspBuf);
                    break;
            }
        break;
        }

        case READY_STATE:
        {
#ifdef RTSP_DEBUG
            fprintf(stderr,"current method code is:%d\n",method);
#endif

            switch (method)
            {
                case RTSP_ID_PLAY:                                      //状态迁移为播放态
                   if (RTSP_play(pRtspBuf) == ERR_NOERROR)
                    {
                        fprintf(stderr,"\tStart Playing!\n");
                        pRtspSess->cur_state = PLAY_STATE;
                    }
                    break;

                case RTSP_ID_SETUP:
                    if (RTSP_setup(pRtspBuf) == ERR_NOERROR)    //状态不变
                    {
                        pRtspSess->cur_state = READY_STATE;
                    }
                    break;

                case RTSP_ID_TEARDOWN:
                    RTSP_teardown(pRtspBuf);                 //状态变为初始态 ?
                    break;

                case RTSP_ID_OPTIONS:
                    if (RTSP_options(pRtspBuf) == ERR_NOERROR)
                    {
                        pRtspSess->cur_state = INIT_STATE;          //状态不变
                    }
                    break;

                case RTSP_ID_PAUSE:         			// method not valid this state.
                    send_reply(455, 0, pRtspBuf);
                    break;

                case RTSP_ID_DESCRIBE:
                    RTSP_describe(pRtspBuf);
                    break;

                default:
                    send_reply(501, 0, pRtspBuf);
                    break;
            }

            break;
        }


        case PLAY_STATE:
        {
            switch (method)
            {
                case RTSP_ID_PLAY:
                    // Feature not supported
                    fprintf(stderr,"UNSUPPORTED: Play while playing.\n");
                    send_reply(551, 0, pRtspBuf);        // Option not supported
                    break;
/*				//不支持暂停命令
                case RTSP_ID_PAUSE:              	//状态变为就绪态
                    if (RTSP_pause(pRtspBuf) == ERR_NOERROR)
                    {
                    	pRtspSess->cur_state = READY_STATE;
                    }
                    break;
*/
                case RTSP_ID_TEARDOWN:
                    RTSP_teardown(pRtspBuf);        //状态迁移为初始态
                    break;

                case RTSP_ID_OPTIONS:
                    break;

                case RTSP_ID_DESCRIBE:
                    RTSP_describe(pRtspBuf);
                    break;

                case RTSP_ID_SETUP:
                    break;
            }

            break;
        }/* PLAY state */

        default:
            {
                /* invalid/unexpected current state. */
                fprintf(stderr,"%s State error: unknown state=%d, method code=%d\n", __FUNCTION__, pRtspSess->cur_state, method);
            }
            break;
    }/* end of current state switch */

#ifdef RTSP_DEBUG
    printf("leaving rtsp_state_machine!\n");
#endif
}