在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過程:

推薦閱讀