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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值