/* 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 */ }
/*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 }