DSS源码分析--对RTSP请求的状态机处理机制

来源:互联网 发布:卸妆 知乎 编辑:程序博客网 时间:2024/06/06 20:09

DSS(Darwin Streaming Server)对RTSP请求的处理,采用了状态机的方法。通过对其状态机的详细分析,可以了解其原理,并根据自己的项目需要,有针对性的做出修改。

对RTSP Session进行管理的代码在Server.tproj/RTSPSession.cpp中。RTSPSession对象在构造函数中,首先将状态初始化为kReadingFirstRequest。

RTSPSession::RTSPSession( Bool16 doReportHTTPConnectionAddress ): RTSPSessionInterface(),  fRequest(NULL),  fRTPSession(NULL),  fReadMutex(),  fHTTPMethod( kHTTPMethodInit ),  fWasHTTPRequest( false ),  fFoundValidAccept( false),  fDoReportHTTPConnectionAddress(doReportHTTPConnectionAddress),  fCurrentModule(0),  fState(kReadingFirstRequest){......}

RTSPSession::Run()实现了一个状态机,可以看其代码结构:

SInt64 RTSPSession::Run(){    ……    while (this->IsLiveSession())    {        switch (fState)        {            case kReadingFirstRequest:            {                ……                if (err == QTSS_RequestArrived)                    fState = kHTTPFilteringRequest;                if (err == E2BIG)                    fState = kHaveNonTunnelMessage;            }            continue;                        case kHTTPFilteringRequest:            {                               fState = kHaveNonTunnelMessage; // assume it's not a tunnel setup message                                                // prefilter will set correct tunnel state if it is.                PreFilterForHTTPProxyTunnel();                ……            }                                    case kReadingRequest:            {                ……                fState = kHaveNonTunnelMessage;                            }                        case kHaveNonTunnelMessage:            {                   ……                fState = kFilteringRequest;            }                        case kFilteringRequest:            {                ……                if (fRequest->HasResponseBeenSent())                {                    fState = kPostProcessingRequest;                    break;                }                fState = kRoutingRequest;            }            case kRoutingRequest:            {                ……                if(fRequest->SkipAuthorization())                {                    fState = kPreprocessingRequest;                    ……                }                else                    fState = kAuthenticatingRequest;            }                        case kAuthenticatingRequest:            {                ……                if (fRequest->HasResponseBeenSent())                {                    fState = kPostProcessingRequest;                    break;                }                fState = kAuthorizingRequest;            }            case kAuthorizingRequest:            {                if (fRequest->HasResponseBeenSent())                {                    fState = kPostProcessingRequest;                    break;                }                fState = kPreprocessingRequest;            }                        case kPreprocessingRequest:            {                ……                if (fRequest->HasResponseBeenSent())                {                    fState = kPostProcessingRequest;                    break;                }                fState = kProcessingRequest;            }            case kProcessingRequest:            {                ……                fState = kPostProcessingRequest;            }            case kPostProcessingRequest:            {                ……                fState = kSendingResponse;            }            case kSendingResponse:            {                ……                fState = kCleaningUp;            }                        case kCleaningUp:            {                ……                fState = kReadingRequest;            }        }    }        ……}

对于第一次RTSP请求,在kReadingFirstRequest中,如果收到完整的RTSP请求,会转入kHTTPFilteringRequest。在kHTTPFilteringRequest状态,会通过PreFilterForHTTPProxyTunnel()检查这个RTSP请求是否通过HTTP Tunnel。如果是普通的RTSP请求,则进入kHaveNonTunnelMessage状态;如果是走HTTP POST,则进入kSocketHasBeenBoundIntoHTTPTunnel状态;如果是走HTTP GET,则进入kReadingRequest状态。

对于后续的RTSP请求,则直接进入kReadingRequest状态。(第一次RTSP请求结束后,状态被置为kReadingRequest。)

在kReadingRequest状态,确保收到完整的RTSP请求数据后,进入kHaveNonTunnelMessage状态。

在kHaveNonTunnelMessage状态,生成RTSPRequest对象,检查RTSP请求数据的正确性,进入kFilteringRequest状态。

在kFilteringRequest状态,会调用所有注册了QTSS_RTSPFilter_Role角色的模块,随后进入kRoutingRequest状态。

在kRoutingRequest状态,会调用所有注册了QTSS_RTSPRoute_Role角色的模块,然后判断是否需要进行认证,分别进入kAuthenticatingRequest和kPreprocessingRequest状态。

kAuthenticatingRequest状态要解决的问题是:用户是不是这个系统的合法用户。若是合法用户,则进入kAuthorizingRequest状态,这里会解决另一个问题:用户对要访问的资源是否真的有权限。

对RTSP请求的真正处理放在kProcessingRequest阶段,而其前后则有预处理kPreprocessingRequest阶段和后处理kProcessingRequest阶段。然后进入kSendingResponse阶段发回数据,再进入kCleaningUp阶段做清理工作,最后把状态设为kReadingRequest准备处理下一个RTSP请求。


第一次ANNOUNCE时,RTSP请求中不带digest信息,所以kAuthenticatingRequest阶段认证失败,转入kAuthorizingRequest状态。kAuthorizingRequest阶段会调用SendDigestChallenge()要求客户端发回digest信息。第二次ANNOUNCE时,kAuthenticatingRequest阶段根据RTSP请求中的digest信息完成验证,转入kPostProcessingRequest状态。

认证通过以后,RTSP请求的状态会在kReadingRequest->kHaveNonTunnelMessage->kFilteringRequest->kRoutingRequest->kPreprocessingRequest->kProcessingRequest->kPostProcessingRequest->kSendingResponse->kCleaningUp->kReadingRequest

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 咳嗽流清水鼻涕怎么办 脸最近老是过敏怎么办 鼻炎脸特别疼怎么办 宝宝感冒一直流鼻涕怎么办 经常过敏的体质怎么办 一边鼻子堵了怎么办 鼻炎流清水鼻涕怎么办 鼻子总感觉堵塞怎么办 半边鼻子不通气怎么办 鼻炎感冒了鼻塞怎么办 左边鼻子不通气怎么办 婴儿鼻塞不通气怎么办 过敏性鼻炎一直打喷嚏怎么办 一只鼻子流鼻涕怎么办 一个鼻子不通气怎么办 夏天鼻子堵了怎么办 做完鼻子感冒了怎么办 鼻子不通流鼻涕打喷嚏怎么办 一岁半宝宝流鼻涕鼻塞怎么办 没有感昌流鼻涕怎么办 婴儿感冒咳嗽流鼻涕怎么办 小孩经常流鼻子怎么办 5岁宝宝流鼻涕怎么办 小孩鼻涕一直流怎么办 二岁宝宝流鼻涕怎么办 小婴儿有点鼻塞怎么办 宝宝流鼻涕总不好怎么办 孩子鼻炎睡不好怎么办 鼻炎清鼻涕不止怎么办 宝宝持续低烧流鼻涕怎么办 孩子鼻塞不通气怎么办 2月婴儿感冒怎么办 长期流黄鼻涕怎么办 孩子流清水鼻涕怎么办 小孩有点流鼻子怎么办 初生婴儿堵鼻子怎么办? 小孩反复发烧了怎么办 小孩突然发烧了怎么办 40天宝宝鼻塞怎么办 宝宝伤风鼻子不通怎么办 鼻子伤风不通气怎么办