一、各模块初始化
//对话框管理对象初始化
SipCallLegMgrConstruct
//当前上层配置manualPrack为FALSE,由rv stack自己管理PRACK
pMgr->manualPrack = pCfg->manualPrack;
//事务管理对象初始化
TransactionMgrInitialize
//当前上层配置manualPrack为FALSE,由rv stack自己管理PRACK
pTranscMgr->manualPrack = pCfg->manualPrack;
//根据上层是否配置了PRACH开启,来初始化status100rel
for(i=0;i<pCfg->extensionListSize;i++)
if(strcmp(pCfg->supportedExtensionList[i],"100rel") == 0)
pTranscMgr->status100rel = RVSIP_TRANSC_100_REL_SUPPORTED;
二、接收INVITE请求
HandleRequestInInitialState
switch (eMethod)
case (RVSIP_METHOD_INVITE):
//处理INVITE
HandleInviteInInitialState(pTransc, hMsg);
//更新PRACK状态
TransactionUpdateReliableStatus(pTransc, hMsg)
//远端含有Require: 100rel,则事务relStatus更新为
// RVSIP_TRANSC_100_REL_REQUIRED
bHeaderFound =
SipMsgDoesOtherHeaderExist(hMsg,"Require","100rel",NULL);
if(bHeaderFound == RV_TRUE)
pTransc->relStatus = RVSIP_TRANSC_100_REL_REQUIRED;
//远端含有bHeaderFound = Supported: 100rel或压缩格式的K: 100rel
//则事务relStatus更新为RVSIP_TRANSC_100_REL_SUPPORTED
SipMsgDoesOtherHeaderExist(hMsg,"Supported","100rel",NULL);
if(bHeaderFound == RV_TRUE)
pTransc->relStatus = RVSIP_TRANSC_100_REL_SUPPORTED;
bHeaderFound = SipMsgDoesOtherHeaderExist(hMsg,"k","100rel",NULL);
if(bHeaderFound == RV_TRUE)
pTransc->relStatus = RVSIP_TRANSC_100_REL_SUPPORTED;
//远端不支持100rel
pTransc->relStatus = RVSIP_TRANSC_100_REL_UNDEFINED;
------------------------------------------------------------------------------------------------------------------------------
在收到INVITE请求后,上层应用代码使用RvSipCallLegGet100RelStatus函数可以获取当前对话框中pTransc->relStatus的状态值,应用程序根据需要确认是否要发送含有100rel的临时应答,通常情况下,如果relStatus状态为RVSIP_TRANSC_100_REL_REQUIRED,则一定要发送含有100rel的临时应答,调用如下代码发送。
RvSipCallLegProvisionalResponseReliable(pcall,code);
CallLegSessionProvisionalResponse(pCallLeg,status,RV_TRUE)
//当前需要处理可靠的临时响应,b_isReliable为RV_TRUE
if(b_isReliable == RV_FALSE)
xxx
else
RvSipTransactionRespondReliable(hTransc,status,NULL)
TransactionControlSendResponse(pTransc,responseCode,strReasonPhrase,
RVSIP_TRANSC_REASON_USER_COMMAND, RV_TRUE);
//发送应答
TransactionControlGenerateAndSendResponse(pTransc,responseCode,
strReasonPhrase,bIsReliable)
//创建应答消息
TransactionCreateResponseMessage(pTransc, responseCode,
strReasonPhrase, bIsReliable, pTransc->hOutboundMsg);
if(b_isReliable)
//添加可靠应答所必须的RSeq头域
AddReliableInfoToMsg(pTransc,hMsg);
//生成一个新的RSeq值
if(pTransc->localRSeq.bInitialized == RV_FALSE)
pTransc->localRSeq.val=
(TransactionRand(pTransc) % 1000)+1;
pTransc->localRSeq.bInitialized = RV_TRUE;
else
pTransc->localRSeq.val++;
//添加Require:100rel字段
SipMsgAddNewOtherHeaderToMsg(hMsg,
"Require","100rel",NULL);
//添加RSeq头域
RvSipRSeqHeaderConstructInMsg(hMsg,RV_FALSE,
&hRSeq);
RvSipRSeqHeaderSetResponseNum(hRSeq,
pTransc->localRSeq.val)
三、接收1XX应答
TransactionMsgReceived
if (RVSIP_MSG_RESPONSE == bMsgType)
if ((100 <= responseCode) && (responseCode < 200))
//处理临时应答
HandleProvisionalResponse(pTransc, hMsg)
//临时应答是否忽略的处理
ret = IgnoreProvsionalResponse(pTransc,responseCode,hMsg,&bReliable1xx,
&rseqStep)
//如果已经收到最终应答,则忽略本地临时应答
switch (pTransc->eState)
case RVSIP_TRANSC_STATE_CLIENT_INVITE_FINAL_RESPONSE_RCVD:
……
return RV_TRUE;
//不忽略100应答
if(respCode == 100)
return RV_FALSE;
//非INVITE的通用事务满足此条件,不忽略对通用事务的应答处理
if(pTransc->eState != RVSIP_TRANSC_STATE_CLIENT_INVITE_CALLING
&&pTransc->eState != RVSIP_TRANSC_STATE_CLIENT_INVITE_PROCEEDING)
return RV_FALSE;
//如果本端不支持PRACK,不忽略应答处理
if(pTransc->pMgr->status100rel ==
RVSIP_TRANSC_100_REL_UNDEFINED)
return RV_FALSE;
//如果对端没有要求必须处理PRACK,则不忽略应答处理,即意味着
//下面流程的处理都已经确定对端含有Require: 100rel
isReliable = IsReliableProvisionalResponse(hMsg);
if(isReliable == RV_FALSE)
return RV_FALSE;
//校验1XX是否含有合法的RSeq头域,如果没有,则忽略本次应答
CheckRel1xxRseqHeader(hMsg, prseqStep, &isLegal);
if(isLegal == RV_FALSE)
return RV_TRUE;
//最终标记,对端含有Require: 100rel,要求本端执行PRACK机制的
//处理。
*bReliable1xx = RV_TRUE;
//如果上面校验,此次临时应答无效,则忽略
If ( ret == RV_TRUE )
return RV_OK;
//如果要求本端执行PRACK机制
if(pTransc->eState != RVSIP_TRANSC_STATE_TERMINATED && bReliable1xx ==
RV_TRUE)
//使用回调通知收到了含有Require:100rel的应答,该回调函数为
//CallLegTranscEvRelProvRespRcvdEv
TransactionCallbackCallRelProvRespRcvdEv(pTransc, rseqStep)
----------------------------------------------------------------------------------------------------------------------------
TransactionCallbackCallRelProvRespRcvdEv
HandleRelProvRespRcvd(pCallLeg, rseqResponseNum, hMsg);
//保存1XX的cseq值到incomingRel1xxCseq,后续发送PRACK请求时,使用该值
//设置PRACK请求的cseq
GetCseqStepFromMsg(pCallLeg, hMsg,&cseqStep);
SipCommonCSeqSetStep(cseqStep,&pCallLeg->incomingRel1xxCseq);
//将1XX中RSeq的值保存到pCallLeg->incomingRSeq.val中
CallLegSetIncomingRSeq(pCallLeg,rseqResponseNum);
//当前上层配置自动发送PRACK
if(pCallLeg->pMgr->manualPrack == RV_TRUE)
xxx
else
//发送PRACK请求
CallLegSessionSendPrack(pCallLeg)
//添加Rack头域
AddPrackInfoToMsg(pCallLeg, hMsg)
四、接收PRACK请求
HandleRequestInInitialState
//处理PRACK
switch (eMethod)
case (RVSIP_METHOD_PRACK):
//如果本端不支持PRACK,则按普通事务处理
if(pTransc->pMgr->status100rel == RVSIP_TRANSC_100_REL_UNDEFINED)
return HandleGeneralInInitialState
//查找PRACK对应的INVITE事务
TransactionMgrHashFindMatchPrackTransc(pTransc->pMgr, pTransc, hMsg,
&pPrackPair);
//保存这个INVITE事务到hPrackParent中
pTransc->hPrackParent = (RvSipTranscHandle)pPrackPair;
//处理PRACK
HandlePrackInInitialState(pTransc, hMsg)
//如果已经发出去含有100rel的1XX应答,收到PRACK则取消当前定时器
if (RVSIP_TRANSC_STATE_SERVER_INVITE_REL_PROV_RESPONSE_SENT ==
pRelRespTransc->eState)
TransactionTimerReleaseAllTimers(pRelRespTransc);
//处理PRACK请求
TransactionStateSrvPrackReqRecvd(RVSIP_TRANSC_REASON_REQUEST_RECEIVED,
pTransc, hMsg);
pPrackPair = (Transaction*)pTransc->hPrackParent;
//如果本端不支持PRACK,则标记发送405应答
if(pTransc->pMgr->status100rel != RVSIP_TRANSC_100_REL_SUPPORTED)
responseCode = 405;
//如果当前PRACK没有匹配到任何100rel的INVITE事务,则标记发送481
//应答
else if(pPrackPair == NULL)
responseCode = 481;
//否则标记发送200应答
else
responseCode = 200;
//通用请求的正常处理
TransactionStateSrvGeneralReqRecvd(eReason, pTransc);
//当前配置了PRACK自动处理,进入此流程,自动回应PRACK请求。
if((pTransc->pMgr->manualPrack == RV_FALSE || responseCode >= 300) &&
pTransc->eState == RVSIP_TRANSC_STATE_SERVER_GEN_REQUEST_RCVD)
TransactionControlSendResponse(pTransc,responseCode,NULL,
RVSIP_TRANSC_REASON_TRANSACTION_COMMAND, RV_FALSE);
五、发送200应答为INVITE请求
RvSipCallLegAccept
CallLegSessionAccept
//在PRACK配置为手工方式下,如果已经收到PRACK请求,但本地还没有回PRACK
//请求的应答,这里应用层确直接发送最终应答了,这时候sip stack将自动回复
//PRACK请求的应答。
if (pCallLeg->pMgr->manualPrack == RV_TRUE &&
pCallLeg->ePrackState == RVSIP_CALL_LEG_PRACK_STATE_PRACK_RCVD)
CallLegSessionSendPrackResponse(pCallLeg, 200);
六、接收最终应答为PRACK请求
HandleTranscStateGeneralFinalResponseRcvd
//收到PRACK的最终应答
if(eMethod == SIP_TRANSACTION_METHOD_PRACK)
//使用回调pfnPrackStateChangedEvEvHandler通知用户侧PRACK的请求收到的最终
//应答,当前我们没有设置此回调,不进行处理。
CallLegCallbackPrackStateChangedEv(pCallLeg,
RVSIP_CALL_LEG_PRACK_STATE_PRACK_FINAL_RESPONSE_RCVD,
RVSIP_CALL_LEG_REASON_UNDEFINED, responseStatusCode,hTransc);
//如果收到的是401或407应答,并且没有设置应用层的回调,并且当前PRACK配置为
//自动模式,则sip stack自动重发PRACK请求,在重发的PRACK请求中会协带鉴权信
//息。
if((responseStatusCode == 401 || responseStatusCode == 407) && pCallLeg->callLegEvHandlers->pfnPrackStateChangedEvEvHandler == NULL &&
RV_FALSE == pCallLeg->pMgr->manualPrack)
CallLegSessionSendPrack(pCallLeg)
七、定时器
这里没有去仔细分析,大体上是按照RFC3262的标准,如果发送了可靠的临时应答(1XX中含有Require: 100rel及Rseq头域),则启动事务传送的主定时器和长定时器,非可靠性的临时应答是不启动事务传送定时器的。在主定时器内超时后进行可靠的临时应答重传,如果事务传送的长定时器超时,就回应500错误响应。
RvSIP 可靠性临时响应的分析
最新推荐文章于 2021-02-03 17:29:07 发布