RvSIP 可靠性临时响应的分析

一、各模块初始化
//对话框管理对象初始化
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错误响应。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值