![oSIP協(xié)議棧及eXoSIPOrtp等使用入門_第1頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/3502cda7-782e-469b-aeb8-2eecfd402e2e/3502cda7-782e-469b-aeb8-2eecfd402e2e1.gif)
![oSIP協(xié)議棧及eXoSIPOrtp等使用入門_第2頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/3502cda7-782e-469b-aeb8-2eecfd402e2e/3502cda7-782e-469b-aeb8-2eecfd402e2e2.gif)
![oSIP協(xié)議棧及eXoSIPOrtp等使用入門_第3頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/3502cda7-782e-469b-aeb8-2eecfd402e2e/3502cda7-782e-469b-aeb8-2eecfd402e2e3.gif)
![oSIP協(xié)議棧及eXoSIPOrtp等使用入門_第4頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/3502cda7-782e-469b-aeb8-2eecfd402e2e/3502cda7-782e-469b-aeb8-2eecfd402e2e4.gif)
![oSIP協(xié)議棧及eXoSIPOrtp等使用入門_第5頁](http://file1.renrendoc.com/fileroot_temp2/2020-10/1/3502cda7-782e-469b-aeb8-2eecfd402e2e/3502cda7-782e-469b-aeb8-2eecfd402e2e5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、oSIP協(xié)議棧 及eXoSIP Ortp等 使用入門作者:不祥一直沒空仔細(xì)研究下oSIP,最近看到其版本已經(jīng)到了3.x版本,看到網(wǎng)上的許多幫助說明手冊都過于陳舊,且很多文檔內(nèi)容有點誤人子弟的嫌疑Linux下oSIP的編譯使用應(yīng)該是很簡單的,其Install說明文檔里也介紹的比較清楚,本文主要就oSIP在Windows平臺下VC6.0開發(fā)環(huán)境下的使用作出描述。雖然oSIP的開發(fā)人員也說明了,oSIP只使用了標(biāo)準(zhǔn)C開發(fā)庫,但許多人在Windows下使用oSIP時,第一步就被卡住了,得不到oSIP的LIB庫和DLL庫,也就沒有辦法將oSIP使用到自己的程序中去,所以第一步,我們將學(xué)習(xí)如何得到oSIP
2、的靜態(tài)和動態(tài)鏈接庫,以便我們自己的程序能夠使用它們來成功編譯和執(zhí)行我們的程序。第一階段:-先創(chuàng)建新工程,網(wǎng)上許多文檔都介紹創(chuàng)建一個Win32動態(tài)鏈接庫工程,我們這里也一樣,創(chuàng)建一個空白的工程保存。同樣,將oSIP2版本3.0.1 src目錄下的Osipparser2目錄下的所有文件都拷到我們剛創(chuàng)建的工程的根目錄下,在VC6上操作:Project-Add To Project-Files將所有的源程序和頭文件都加入到工程內(nèi),保存工程。這時,我們可以嘗試編譯一下工程,你會得到許多錯誤提示信息,其內(nèi)容無非是找不到osipparser2/xxxxx.h頭文件之類。處理:在Linux下,我們一般是將頭文
3、件,lib庫都拷到/usr/inclue;/usr/lib之類的目錄下,c源程序里直接寫#i nclude xxx.h時,能直接去找到它們,在VC里,同樣的,最簡單的方法就是將oSIP2源碼包中的Include目錄下的osipparser2目錄直接拷到我們的Windows下默認(rèn)包含目錄即可,這個目錄在VC6的Tool-Options-Directories里設(shè)置,(當(dāng)然,如果你知道這一步,也可以不用拷貝文件,直接在這里把oSIP源碼包所在目錄加進來就可以了),默認(rèn)如果裝在C盤,目錄則為C:Program FilesMicrosoft Visual StudioVC98Include。這時,我們
4、再次編譯我們的工程,順利編譯,生成osipparser2.dll,這時,網(wǎng)上很多文檔里可能直接就說,這一步也會生成libs目錄,里面里osipparser2.lib文件,但我們這里沒有生成:)最簡單的方法,不用深究,直接再創(chuàng)建一個工程,同上述創(chuàng)建動態(tài)鏈接庫方法,創(chuàng)建一個Win32靜態(tài)鏈接庫工程,直接編譯,即可得到osipparser2.lib。-上面,我們得到了Osip的解析器開發(fā)庫,下面再編譯完整的Osip協(xié)議棧開發(fā)庫,同樣照上述方法,分別創(chuàng)建動態(tài)鏈接庫工程和靜態(tài)鏈接庫工程,只是要拷的文件換成src下的osip目錄下文件和include下的osip目錄,得到osip2.dll和osip2.l
5、ib。在編譯osip2.dll這一步可能會再次得到錯誤,內(nèi)容含義是找不到鏈接庫,所以,我們要把前面編譯得到的osipparser2.lib也拷到osip工程目錄下,并在VC6中操作:Project-Setting-Link中的Object/Library Modules:kernel32.lib user32.lib.xxx.lib之類的內(nèi)容最后增加:osipparser2.lib保存工程后再次編譯,即可成功編譯osip2.dll。-至此,我們得到了完整的oSIP開發(fā)庫,使用時,只需在我們的程序里包含oSIP的頭文件,工程的鏈接參數(shù)里增加osipparser2.lib和osip2.lib即可。
6、-下面我們驗證一下我們得到的開發(fā)庫,并大概了解一下OSIP的語法規(guī)范。在VC里創(chuàng)建win32控制臺程序工程,將libosip源碼包的SRC目錄下的Test目錄內(nèi)的C源程序隨便拷一個到工程時,直接編譯(工程設(shè)置里照前文方法在link選項里增加osip2.lib,osipparser2.lib引用我們之前成功編譯得到的靜態(tài)庫文件)就可以運行(帶參數(shù)運行,參數(shù)一般為一個文本文件,同樣從Test目錄的res目錄里拷一個與源文件同名的純文本文件到工程目錄下即可)。該目錄下的若干文件基本上是測試了Osip的一些基本功能函數(shù),例如URI解析之類,可以大概了解一下oSIP的語法規(guī)范和調(diào)用方法,同時也能校驗一下
7、之前編譯的OSIP開發(fā)庫能否正常使用,成功完成本項工作后,可以進入下一步具體的oSIP的使用學(xué)習(xí)了。-由于oSIP是比較底層的SIP協(xié)議棧實現(xiàn),新手較難上手,而官方的示例大都是一些偽代碼,需要有實際的例子程序參考學(xué)習(xí),而最好的例子就是同樣官方發(fā)布的oSIP的擴展開發(fā)庫exosip2,使用exoSIP可以很方便地快速創(chuàng)建一個完整的SIP程序(只針對性地適用于SIP終端開發(fā)用,所以我們這里只是用它快速開發(fā)一個SIP終端,用來更方便地學(xué)習(xí)oSIP,要想真正掌握SIP的開發(fā),需要掌握oSIP并熟讀RFC文檔才行,exoSIP不是我們的最終學(xué)習(xí)目的),通過成功編譯運行一個自己動手開發(fā)出的程序,再由淺入深
8、應(yīng)該是初學(xué)都最好的學(xué)習(xí)方法通過對使用exosip開發(fā)庫的使用創(chuàng)建自己的SIP程序,熟悉后再一個函數(shù)一個函數(shù)地深入學(xué)習(xí)exosip提供的接口函數(shù),就可以深入理解osip了,達到間接學(xué)習(xí)oSIP的目的,同時也能從eXoSIP中學(xué)習(xí)到正確使用oSIP的良好的編程風(fēng)格和語法格式。而要成功編譯ExoSIP,似乎許多人被難住了,直接在XP-sp2上,用VC6,雖然你使用了eXoSIP推薦的winsock2.h,但是會得到一個sockaddr_storage結(jié)構(gòu)不能識別的錯誤,因為vc6自帶的開發(fā)庫太古董了,需要升級系統(tǒng)的Platform SDK,下載地址如下:.PSP2FULLInstall.htm(VC
9、6的支持已經(jīng)停止,這是VC6能使用的最新SDK)成功安裝后編譯前需加OSIP_MT宏,以啟用線程庫,否則在程序中使用eXoSIP庫時會出錯,而編譯時也會得到許多函數(shù)未定義的Warning提示,編譯得到exosip2.lib供我們使用,當(dāng)然,在此之前需要成功編譯了osip2和osipparser2,而在之后的實際使用時,發(fā)現(xiàn)oSIP也需要增加OSIP_MT宏,否則OSIP_MT調(diào)用oSIP的線程庫時會出錯,所以我們需要重新編譯oSIP了:),因為eXosip是基于oSIP的(同上方式創(chuàng)建靜態(tài)和動態(tài)鏈接庫工程,并需在Link中手工添加oSIP和oSIPparser的lib庫)。-創(chuàng)建新工程,可以是
10、任意工程,我們從最簡單的Win32控制臺程序開始,為了成功使用oSIP,我們需要引用相關(guān)庫,調(diào)用相關(guān)頭文件,經(jīng)過多次試驗,發(fā)現(xiàn)需要引用如下的庫:exosip2.lib osip2.lib osipparser2.lib WSock32.Lib IPHlpApi.Lib WS2_32.Lib Dnsapi.lib其中,除了我們上面編譯得到的三個oSIP庫外,其它庫都是系統(tǒng)庫,其中有一些是新安裝的Platform SDK所新提供的。至此,我們有了一個簡單的開發(fā)環(huán)境了,可以充分利用網(wǎng)上大量的以oSIP為基礎(chǔ)的代碼片段和官方說明文檔開始具體函數(shù)功能的測試和使用了:)-我們先進行一個簡單的純SIP信令(
11、不帶語音連接建立)的UAC的SIP終端的程序開發(fā)的試驗(即一個只能作為主叫不能作為被叫的的SIP軟電話模型),我們創(chuàng)建一個MFC應(yīng)用程序,對話框模式,照上面的說明,設(shè)置工程包含我們上面得到的oSIP的相關(guān)開發(fā)庫及SDK的一些開發(fā)庫,并且由于默認(rèn)LIBC的沖突,需要排除MSVCRTD開發(fā)庫(其中D代表Debug模式下,沒有D表示Release模式下),直接使用eXosip的幾個主要函數(shù)就可以創(chuàng)建一個基本的SIP軟電話模型。其主要流程為:初始化eXosip庫-啟動事件監(jiān)聽線程-向SIP Proxy注冊-向某SIP終端(電話號碼)發(fā)起呼叫-建立連接-結(jié)束連接初始化代碼:int ret=0;ret=e
12、Xosip_init();eXosip_set_user_agent(#YouToo0.1);if(0!=ret)AfxMessageBox(Couldnt initialize eXosip!n);return false;ret=eXosip_listen_addr(IPPROTO_UDP,NULL,0,AF_INET,0);if(0!=ret)eXosip_quit();AfxMessageBox(Couldnt initialize transport layer!n);return false;啟動事件監(jiān)聽線程:AfxBeginThread(sip_uac,(void*)this);
13、向SIP Proxy注冊:eXosip_clear_authentication_info();eXosip_add_authentication_info(uname,uname,upwd,md5,NULL);real_send_register(30);/*自定義函數(shù)代碼請見源碼*/發(fā)起呼叫(構(gòu)建假的SDP描述,實際軟電話使用它構(gòu)建RTP媒體連接):osip_message_t*invite=NULL;/*呼叫發(fā)起消息體*/int i=eXosip_call_build_initial_invite(&invite,dest_call,source_call,NULL,#YouToo te
14、st demo!);if(i!=0)AfxMessageBox(Intial INVITE failed!n);char localip128;eXosip_guess_localip(AF_INET,localip,128);snprintf(tmp,4096,v=0rno=josua 00 IN IP4%srns=conversationrnc=IN IP4%srnt=0 0rnm=audio%s RTP/AVP 08 101rna=rtpmap:0 PCMU/8000rna=rtpmap:8 PCMA/8000rna=rtpmap:101 telephone-event/8000rna=
15、fmtp:101 0-11rn,localip,localip,9900);osip_message_set_body(invite,tmp,strlen(tmp);osip_message_set_content_type(invite,application/sdp);eXosip_lock();i=eXosip_call_send_initial_invite(invite);eXosip_unlock();掛斷或取消通話:int ret;ret=eXosip_call_terminate(call_id,dialog_id);if(0!=ret)AfxMessageBox(hangup
16、/terminate Failed!);可以看到非常簡單,再借助于oRTP和Mediastreamer開發(fā)庫,來快速為我們的SIP軟電話增加RTP和與系統(tǒng)語音API接口交互及語音編碼功能,即可以快速開發(fā)出一個可用的SIP軟電話,關(guān)于oRTP和Mediastreamer的相關(guān)介紹不是本文重點,將在有空的時候考慮增加相應(yīng)使用教程,后面跟貼中可以下載基本可用的完整SIP軟電話的VC源碼工程文件供參考使用,完全CopyLeft,歡迎轉(zhuǎn)載,但請在轉(zhuǎn)載時注明作者信息,謝謝!第二階段:-得到了一個SIP軟電話模型后,我們可以根據(jù)軟電話的實際運行表現(xiàn)(結(jié)合用Ethereal抓包分析)來進行代碼的分析,以達到利
17、用eXoSIP來輔助我們學(xué)習(xí)oSIP的最終目的(如要快速開發(fā)一個可用的SIP軟電話,請至前面提到的論壇去下載使用oRTP和Mediastreamer快速搭建的一個基本完整可用的SIP軟電話#YouToo 0.1版本的VC源碼工程文件作參考)?,F(xiàn)在從eXosip的初始化函數(shù)開始入手,來分析oSIP的使用,這是第二階段,第三階段就是深入學(xué)習(xí)oSIP的源碼了,但大多數(shù)情況下應(yīng)該沒有必要了,因為在第二階段就有部分涉及到第三階段的工作了,而且oSIP的源碼也就大多是一些SIP數(shù)據(jù)的語法解析和狀態(tài)機的實現(xiàn),能深入理解了SIP協(xié)議后,這些只是一種實現(xiàn)方式,沒必要完全去接受,而是可以用自己的方式和風(fēng)格來實現(xiàn)一
18、套,比如,更輕量化更有適用目的性的方式,oSIP則只起參考作用了。eXosip_init()是eXosip的初始化函數(shù),我們來看看它的內(nèi)部實現(xiàn):首行是定義的osip_t*osip,這在oSIP的官方手冊里我們看到,所有使用oSIP的程序都要在最開始處聲明一個osip_t的指針,并使用osip_init(&osip)來初始化這個指針。我們可以在代碼中看到很多OSIP_TRACE,這是調(diào)試輸出宏調(diào)用了函數(shù)osip_trace,可以用ENABLE_TRACE宏來打開調(diào)試以方便我們開發(fā)調(diào)試。其它就是很多的eXosip_t的全局變量eXosip的一些初始化操作,包括最上面的memset(&eXosip,
19、0,sizeof(eXosip)完全清空和下面的類似eXosip.user_agent=osip_strdup(eXosip/EXOSIP_VERSION)的exosip變量的一些初始值設(shè)置,其中有一個eXosip.j_stop_ua=0應(yīng)該是一個狀態(tài)機開關(guān),后面可以看到很多代碼檢測這個變量來決定是否繼續(xù)流程處理,默認(rèn)置成了0表示現(xiàn)在exosip的處理流程是就緒的,即ua是not stop的。osip_set_application_context(osip,&eXosip)是比較有意思的,它讓下面的eXosip_set_callbacks(osip)給osip設(shè)置大量的回調(diào)函數(shù)時,能讓osi
20、p能訪問到eXosip這個全局變量中設(shè)置的大量程序運行時交互的信息,相當(dāng)于我們在VC下開啟一個線程時,給線程傳入的一個void指針指向我們的MFC應(yīng)用程序的當(dāng)前dialog對象實例,可以用void*osip_get_application_context(osip_t*osip)這個函數(shù)來取出指針來使用,不過好象exosip中并沒有用到它,可能是留給個人自已擴展的吧還能看到初始化代碼前面有一段WIN32平臺下的SOCK的初始化代碼,可以知道eXosip是用的原生的winsock api函數(shù),也就是我們可能以前學(xué)過的用VC和WINAPI寫sock程序時(不是MFC),用到的那段SOCK初始代碼,
21、還有一段有意思的代碼,就是jpipe()函數(shù),它們返回的是一個管道,一個有2個整型數(shù)值的數(shù)組(一個進一個出),查看其代碼發(fā)現(xiàn),非WIN32平臺是直接使用的pipe系統(tǒng)函數(shù),而WIN32下則是用一對TCP的本地SOCK連接來模擬的管道,一個SOCK寫一個SOCK讀,這段代碼是比較有參考價值的:)j=50;while(aport+&j-0)raddr.sin_port=htons(short)aport);if(bind(s,(struct sockaddr*)&raddr,sizeof(raddr)0)OSIP_TRACE(osip_trace(_,Failed to bind one loca
22、l socket%i!n,aport);else break;含義即,依次檢測50個端口,從static int aport=10500;即1050010550端口找出一個可用的本地端口來綁定listen模擬pipe的一對sock。eXosip_set_callbacks(osip)沒有什么好看的,無非是和oSIP官方文檔介紹的一樣,設(shè)置一大堆的回調(diào)函數(shù),關(guān)鍵是回調(diào)函數(shù)的實現(xiàn),這也是許多初學(xué)者使用oSIP被卡殼的主要原因,不知道oSIP構(gòu)建的程序是怎樣跑起來的,隨便選幾個回調(diào)函數(shù)看一下eXosip是怎樣實現(xiàn)的,有許多是形如下文的函數(shù):static void cb_sndbye(int type
23、,osip_transaction_t*tr,osip_message_t*sip)OSIP_TRACE(osip_trace(_,cb_sndbye(id=%i)rn,tr-transactionid);即,只是打印一下調(diào)試,并沒有完整實現(xiàn)什么功能,我們學(xué)習(xí)時,完全可以用相同的方法,定義一大堆回調(diào)函數(shù),并不忙想怎么完全實現(xiàn),先都是只打印一下調(diào)試信息,看具體的應(yīng)用邏輯根據(jù)抓包測試分析和看調(diào)試看程序走到了哪一步,調(diào)用了哪一個回調(diào),來明白具體回調(diào)函數(shù)要實現(xiàn)什么用途,再來實現(xiàn)代碼就方便多了,當(dāng)然,如果看透了RFC文檔,應(yīng)該從字面就能知道各個回調(diào)函數(shù)的用途了,這是后話,不是誰都能快速完全看懂RFC的,
24、所以我們要參考eXosip:)我們對其中的重要的回調(diào)函數(shù)進行逐個的分析:-osip_set_cb_send_message(osip,&cb_snd_message)SIP消息發(fā)送回調(diào)函數(shù)這個函數(shù)可能是最重要的回調(diào)函數(shù)之一,消息發(fā)送,包括請求消息和回應(yīng)消息,一般情況下,狀態(tài)機的狀態(tài)就是由它控制的,發(fā)起一個消息初始化一個狀態(tài)機,回應(yīng)一個消息對狀態(tài)機修改,終結(jié)消息發(fā)送結(jié)束狀態(tài)機看cb_snd_message的函數(shù)實現(xiàn),要以發(fā)現(xiàn),其主要代碼是對參數(shù)中的要發(fā)送的消息osip_message_t*sip進行分析,找出消息要發(fā)送的真實char*host,int port的值(這些參數(shù)可以省略,但要發(fā)送消息
25、肯定需要host和port,所以要從sip中解析),最后根據(jù)sip中解析出的傳輸方式是TCP還是UDP選擇最終進行消息發(fā)送處理的函數(shù)cb_udp_snd_message,cb_tcp_snd_message處理(它們的參數(shù)一致,即本函數(shù)只是補全一些省略的參數(shù)并對消息進行合法性檢查)。*畢竟eXosip是一個通用的開發(fā)庫,它考慮了要支持TCP,UDP,TCPs,IPV4,IPV6,WIN32,*nix,WINCE等等多樣化的復(fù)雜環(huán)境,所以,我們可以略過我們暫時不需要的部分,比如,IPV6相關(guān)的代碼實現(xiàn)等。由于我們大多數(shù)情況下SIP是用的UDP,所以先來看一下cb_udp_snd_message的
26、實現(xiàn),它從全局變量exosip中獲取可用的sock,并盡最大能力解析出host和port(?難道前面的函數(shù)還不夠解析徹底?如最終仍無port信息則默認(rèn)設(shè)置為5060),使用osip_message_to_str(sip,&message,&length)函數(shù)將要發(fā)送的格式化的SIP消息轉(zhuǎn)換成能用SOCK傳輸?shù)暮唵螖?shù)據(jù)并發(fā)送即完成消息發(fā)送,代碼中有許多復(fù)雜的環(huán)境探測和錯誤控制等等等等,我們可以暫時不用過多關(guān)注,可以繼續(xù)向下,結(jié)尾處有一個keeplive相關(guān)代碼,從代碼字面分析,可能是SIP的Register消息的自動重發(fā)相關(guān)代碼,可以在后面再細(xì)化分析。cb_tcp_snd_essage的函數(shù)實現(xiàn)
27、要比上文的udp的實現(xiàn)簡單很多,主要是環(huán)境探測錯誤控制方面,因為畢竟tcp是穩(wěn)定連接的,對比一下代碼,可以看到主要流程還是將SIP消息轉(zhuǎn)換后,發(fā)送到從SIP消息中解析出的host和port對應(yīng)的目標(biāo)??赐陜蓚€函數(shù),可以知道,eXosip需要有兩個sock,是一個數(shù)組,0是給UDP用的,1是給TCP用的,要用SOCK當(dāng)然要初始化,就是下文要介紹的eXosip的網(wǎng)絡(luò)相關(guān)的初始化了,上面的exosip_init可以看成是這個開發(fā)庫的系統(tǒng)初始化吧:)至些,我們應(yīng)該知道了oSIP開發(fā)的SIP應(yīng)用程序的消息是從哪里發(fā)出的吧,對了,就是從這個回調(diào)函數(shù)里,所謂萬事開頭難,就象開發(fā)WIN32應(yīng)用程序時,找到了W
28、IN32程序的main函數(shù)入口下面的工作就好辦了,下面就都是為一些事件消息開發(fā)對應(yīng)的處理函數(shù)而已了:)osip_set_kill_transaction_callback事務(wù)終結(jié)回調(diào)函數(shù)對應(yīng)ICT,IST,NICT,NIST客戶/服務(wù)器注冊/非注冊事務(wù)狀態(tài)機的終結(jié),主要是使用osip_remove_transaction(eXosip.j_osip,tr)將當(dāng)前tr事務(wù)刪除,再加上一系列的清理工作,其中,NICT即客戶端的非Invite事務(wù)的清理比較復(fù)雜一些,要處理的內(nèi)容也比較多,可以根據(jù)實際應(yīng)用的情況進行有必要的清理工作:)cb_transport_error傳輸失敗處理回調(diào)對應(yīng)于上面說到的
29、四種事務(wù)狀態(tài)機,如果它們在處理時失敗,則在這時進行統(tǒng)一處理。從代碼可知,只是在NOTIFY,SUBSCRIBE,OPTION操作失敗才進行處理,其它錯誤可直接忽略。osip_set_message_callback消息發(fā)送處理回調(diào)根據(jù)type不同,表示不同的消息發(fā)送狀態(tài)OSIP_XXX_AGAIN重發(fā)相關(guān)消息OSIP_ICT_INVITE_SENT發(fā)起呼叫OSIP_ICT_ACK_SENT ACK回應(yīng)OSIP_NICT_REGISTER_SENT發(fā)起注冊O(shè)SIP_NICT_BYE_SENT BYE發(fā)出OSIP_NICT_CANCEL_SENT Cancel發(fā)出OSIP_NICT_INFO_SE
30、NT,OSIP_NICT_OPTIONS_SENT,OSIP_NICT_SUBSCRIBE_SENT,OSIP_NICT_NOTIFY_SENT,OSIP_NICT_UNKNOWN_REQUEST_SENT我們可以看到,eXosip沒有對它們作任何處理,我們可以根據(jù)自己需要,比如,重發(fā)2xx消息前記錄一下日志之類的,擴展一下retransmission的處理方式,發(fā)起Invite前記錄一下通話日志等等。OSIP_ICT_STATUS_1XX_RECEIVED uac收到1xx消息,一般是表示對端正在處理中,這時,主要是設(shè)置一下事務(wù)狀態(tài)機的狀態(tài)值,并對會話中的osip的一些參數(shù)根據(jù)返回值進行相應(yīng)
31、設(shè)置,里面有許多條件判斷,但我們常用的一般是100,180,183的判斷而已,暫時可以忽略里面復(fù)雜的判斷代碼。OSIP_ICT_STATUS_2XX_RECEIVED uac收到2xx消息,這里主要跟蹤一下Register情況下的2xx,表示注冊成功,這時會更新一下exosip的注冊字段值,以便讓eXosip能自動維護uac的注冊,BYE的2xx回應(yīng)是終結(jié)消息,Invite的2xx回應(yīng),則主要是初始化一下會話相關(guān)的數(shù)據(jù),表示已成功建立連接。其它4xx,5xx,6xx則分別是對應(yīng)的處理,根據(jù)實現(xiàn)情況進行概要的查看即可。report_event(je,sip)是代碼中用來進行事件處理的一個函數(shù),跟
32、蹤后發(fā)現(xiàn),其最終是使用了我們上文提到的jpipe管道,以便在狀態(tài)機外實時觀測狀態(tài)機內(nèi)的處理信息。OSIP_NIST_STATUS_XXX_SENT即對應(yīng)于上面的uac的處理,這里是uas的對應(yīng)的消息處理,相比較于uac簡單一點。前面簡單介紹了一下大量的回調(diào)函數(shù)及它們的概要處理邏輯,可能會比較混亂,暫時不用管它,只需要記得一個大概的形象,知道一個SIP處理程序是通過osip_set_cb_send_message回調(diào)函數(shù)來實現(xiàn)真實地發(fā)送各種SIP消息,并且SIP的標(biāo)準(zhǔn)事務(wù)模型是由oSIP實現(xiàn)好了,我們只需要給不同的事務(wù)狀態(tài)設(shè)置不同的回調(diào)處理函數(shù)來處理事務(wù),具體的狀態(tài)變化和內(nèi)部邏輯不用管就可以了。
33、下面來說一下消息處理回調(diào)函數(shù)用到的SOCK的初始化函數(shù),即我們上面說的除了系統(tǒng)初始化外的網(wǎng)絡(luò)初始化函數(shù)eXosip_listen_addr:從上文知道了,系統(tǒng)將初始化兩個SOCK,一個UDP一個TCP,但查看代碼發(fā)現(xiàn)還有第三個,TCPs的,但好象還不能實用,現(xiàn)在不管它,代碼首先是根據(jù)傳輸是UDP還是TCP來設(shè)置對應(yīng)的數(shù)組值,并且如果沒有提供IP地址和端口號,系統(tǒng)會自動取出本機網(wǎng)絡(luò)接口并創(chuàng)建可用的SOCK(http_port的方式暫不用考慮)。SOCK初始化后,如何開始SIP事務(wù)的呢?看到這個調(diào)用eXosip.j_thread=(void*)osip_thread_create(20000,_e
34、Xosip_thread,NULL),對的,這里啟用了一個線程,即,eXosip是調(diào)用oSIP的線程函數(shù)(沒用系統(tǒng)提供的線程函數(shù),是為了跨平臺)進行事務(wù)處理的狀態(tài)機邏輯是在一個線程中處理的,這樣就明白了為什么一直沒能看到順序執(zhí)行下來的程序啟動代碼了,接下去看,線程實際處理函數(shù)是_eXosip_thread,這里面的代碼中,我們看到了上文提到的狀態(tài)機控制開關(guān)變量while(eXosip.j_stop_ua=0),即,當(dāng)j_stop_ua設(shè)置為1時,osip_thread_exit()結(jié)束事務(wù)處理即程序終結(jié),再接下去看,_eXosip_execute是最終的處理函數(shù)了,而且它在程序未終結(jié)情況下是一
35、直邏輯在執(zhí)行。看到_eXosip_execute的代碼中有很多時間函數(shù)和變量,仔細(xì)看,調(diào)用了osip_timers_gettimeout而不是系統(tǒng)API為了跨平臺,來實現(xiàn)定時器功能,除去一些控制代碼,主要處理函數(shù)是eXosip_read_message(1,lower_tv.tv_sec,lower_tv.tv_usec),即取出消息,1表示只取出一條消息,其代碼量非常的大,但同樣的,其中也許多的控制代碼和錯誤檢測代碼,我們在查看時可以暫時忽略掉它們。根據(jù)jpipe_read(eXosip.j_socketctl,buf2,499),我們可以估計,buf2中應(yīng)該是保存的我們的控制管道的數(shù)據(jù),具
36、體作用至些還沒有表現(xiàn)出來,應(yīng)該是用來反映一些狀態(tài)機內(nèi)部的警示之類的信息,實際的SIP的處理的狀態(tài)機的數(shù)據(jù)是存放在buf中,使用_eXosip_recvfrom獲取的,獲取后sipevent=osip_parse(buf,i)解析,使用osip_find_transaction_and_add_event(eXosip.j_osip,sipevent)來查詢事件對應(yīng)的事務(wù)狀態(tài)機,找到后就如同其注解所說明的,/*handled by oSIP!*/,即我們上文設(shè)置的那一大堆回調(diào)函數(shù),至此,我們知道了整個SIP應(yīng)用所處理的大概流程了。如果沒有找到事務(wù)狀態(tài)機呢?直接丟棄嗎?不是的,如果這是一個回應(yīng)消息
37、,但沒有事務(wù)狀態(tài)機處理它,那它是一個錯誤的,要進行清理后才能丟棄,而如果是一個請求,那更不能丟棄了,因為UAS事務(wù)狀態(tài)機要由它來啟動創(chuàng)建的。先來看錯誤的回應(yīng)消息的處理函數(shù)eXosip_process_response_out_of_transaction,可以看到其代碼就是一大堆的賦值語句,XXX=NULL,即將一大堆的運行時變量清空,再調(diào)用osip_event_free清空事件,或者就是一些復(fù)雜的情況下,需要通過解析現(xiàn)在的運行時數(shù)據(jù),從中分析出可能的正在等待回應(yīng)的對端,并發(fā)送相關(guān)終結(jié)通知消息等等,可以根據(jù)實際需要進行簡化。請求事件處理eXosip_process_newrequest,首先是
38、對事件進行探測,MSG_IS_INVITE、MSG_IS_ACK、MSG_IS_REQUEST,對事件進行所屬狀態(tài)機分類,隨后使用_eXosip_transaction_init(&transaction,(osip_fsm_type_t)tx_type,eXosip.j_osip,evt-sip)根據(jù)探測結(jié)果進行狀態(tài)機初始化,實際調(diào)用的是osip_transaction_init,初始化后即將事件入狀態(tài)機osip_transaction_add_event(transaction,evt),由狀態(tài)機自動處理后調(diào)用相應(yīng)回調(diào)函數(shù)處理邏輯了。線程調(diào)用的事件處理函數(shù)代碼最后是if(eXosip.keep_alive 0)_eXosip_keep_alive();這段代碼印證了上文提到了,keep_alive是用來設(shè)置是否自動重新注冊,由_eXosip_keep_alive函數(shù)來實現(xiàn)自動將eXosip全局變量中保存的注冊消息解析后自
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- Module 10 Unit 2 You shouldn't be late(說課稿)-2024-2025學(xué)年外研版(一起)英語五年級上冊001
- 16 滑輪 說課稿-2023-2024學(xué)年科學(xué)六年級上冊青島版001
- 3 珍貴的淡水資源(說課稿)-2023-2024學(xué)年四年級科學(xué)下冊大象版
- 3 我不拖拉 第2課時(說課稿)-2023-2024學(xué)年道德與法治一年級下冊統(tǒng)編版
- 2023二年級數(shù)學(xué)上冊 二 角的初步認(rèn)識 銳角和鈍角說課稿 西師大版
- 19《夜宿山寺》說課稿-2024-2025學(xué)年二年級上冊語文統(tǒng)編版
- 2023八年級道德與法治上冊 第四單元 維護國家利益 第八課 國家利益至上 第1框 國家好 大家才會好說課稿 新人教版
- 2024年八年級道德與法治下冊 第三單元 人民當(dāng)家作主 第五課 我國基本制度 第2框 根本政治制度說課稿 新人教版
- 2024年秋九年級歷史上冊 第一單元 古代亞非文明 第3課 古代印度說課稿2 新人教版001
- 2025北京建筑材料購貨合同
- 2022年湖南高速鐵路職業(yè)技術(shù)學(xué)院單招數(shù)學(xué)模擬試題及答案解析
- 小學(xué)生必備古詩
- 人教版英語八年級上冊單詞默寫表
- SRE Google運維解密(中文版)
- 綜合性學(xué)習(xí)公開課《我的語文生活》一等獎?wù)n件
- IBM:中建八局ERP解決方案
- 高考語文復(fù)習(xí)高中語文文言文注釋集萃
- 初中歷史 教材分析與教學(xué)策略 課件
- 幼兒剪紙-打印版
- 中小學(xué)2021年秋季開學(xué)第一課手心班會圖文精品
- 如何提高和加強人力資源隊伍的建設(shè)
評論
0/150
提交評論