在Vovida的基础上实现自己的SIP协议栈②( 五 )


2>SipSentRequestDB:: processRecv方法:
例如我们接收了一个回应100 Trying这个回应的处理自然落在下面的这个部分:
int statusCode = response->getStatusLine().getStatusCode();
if((statusCode < 200)
((SipTransceiver::myAppContext == APP_CONTEXT_PROXY) &&
(statusCode == 200) &&
(response->getCSeq().getMethod() == INVITE_METHOD) ) )
… …
retVal = new SipMsgQueue;
retVal->push_back(msgContainer->msg.in)
单纯的把消息队列返回上面的应用层;
后续的180(Ringing)也是如此直接返回应用层;
但是到了接受到200(OK) , 那么处理的方式就大不一样了因为OK以后命令交互阶段已经告一段落 , 那么我们通过SipTransactionGC::instance()-> collect的后台方法处理(Thread线程) , 根据Delay的时间的变化:如invCleanupDelay等等 , 删除当前的一些队列中消息所占用的内存(垃圾处理) , (具体处理机制可以参看SipTransactionGC::thread()这个后台处理掉一些孤独的消息 , 例如有Request没有Response的等等 , 并且根据各个消息所占用的Delay时间来释放他们);
但是假如没有收到200呢?假设我们收到了302(呼叫转移)呢?(例如在上面Diagram 1中所表现的那样)
答案在这里:
else if(response->getStatusLine().getStatusCode() >= 200)
{
if(level3Node->val->msgs.response)//这里是检验在消息队列中是否有应答
//产生,也就是Diagram 1中的Second Phase的情况,(第二个Invite消息)
{
SipTransactionList::SipTransListNode *
curr = 0;
if(level3Node->val->myKey == INVITE_METHOD)
{
curr = level2Node->val->level3.getLast();
while(curr)
{
// look for the ACK message
if(curr->val->myKey == ACK_METHOD &&
curr->val->msgs.request)
{
cpLog(DEBUG_NEW_STACK,"duplicate message: %s",
msgContainer->msg.out.logData());
//通过第一个ACK来复制第二个ACK,使用上二者完全相同,
msgContainer->msg.in = 0;
msgContainer->msg.out =
curr->val->msgs.request->msg.out;
msgContainer->msg.type
= curr->val->msgs.request->msg.type;
msgContainer->msg.transport =
curr->val->msgs.request->msg.transport;
msgContainer->msg.netAddr =
curr->val->msgs.request->msg.netAddr;
msgContainer->retransCount = FILTER_RETRANS_COUNT;
break;
}
curr = level2Node->val->level3.getPrev(curr);
}
很明显复制一个ACK消息预备进行下一个新的Invite的发送 , 当然这个是要在有ACK发送以后才可以进行 , 假如没有那么我们可以假定ACK正处在Processing状态;
if(!curr)
{
msgContainer->msg.in = 0;
msgContainer->msg.out = "";
msgContainer->retransCount = 0;
}
}
else
… …
在这个else下面所表示的处理机制是在第一个Message发送出去以后回应大于200的情况 , 也就是在Diagram 1中First Phase的情况,也就是发出第一个302的情况,在下面有一行语句:
msgContainer->msg.out=msgContainer->msg.in->encode()
它的主要目的是用于形成ACK应答,
另外后面介绍Marshal Server的时候向异地发送Invite的时候返回4XX的回应 , 一般都是4XX等恶名招著的Response不会有其他的 , 本地一般采取的处理就是向应用层汇报 , 并且消除Hash队列里的所有驻留的消息 。
大家可以根据上面介绍的方法实验一下其他的情况,基本上都是合适的.
目前来说这个处理机制并不使最优的 , 非凡是在服务器的状态 , 某些情况事实上并没有
一个具体的处理方法:例如4XX的回应 , 可能会造成超时等待过长 。
2.6 在User Agent中的四个重要实例的Run方法:
HeartLessProxy的两个Run方法都介绍完毕了 , 现在我们来看下面将要启动的四个Run过程:

推荐阅读