1、關(guān)于PJSIP介紹
PJSIP是開源的SIP協(xié)議棧,在最近的Asterisk版本中,官方已經(jīng)開始使用PJSIP協(xié)議棧作為Asterisk引擎的SIP協(xié)議棧。關(guān)于為什么Asterisk選擇PJSIP作為Asterisk新一代SIP協(xié)議棧的討論讀者可以查閱此鏈接:
SIP Stack Research
https://wiki.asterisk.org/wiki/display/AST/SIP+Stack+Research
PJSIP的核心是SIP endpoint,通過pjsip_endpoint來表示。

pjsip_endpoint負(fù)責(zé)幾個(gè)方面的工作:
- 它具有一個(gè)pool factory, 為SIP模塊分配自己的pool。
- 它支持對每個(gè)SIP模塊實(shí)現(xiàn)定時(shí)器管理。
- 它支持一個(gè)傳輸管理模塊,傳輸管理模塊支持對SIP傳輸和控制消息解析打印。
- 它支持PJLIB的 ioqueue支持網(wǎng)絡(luò)事件的調(diào)度處理。
- 它提供thread安全保護(hù),對每個(gè)應(yīng)用的thread進(jìn)行安全管理。
- 它可以管理PJSIP的相關(guān)模塊,拓展,解析處理等功能。
- 它負(fù)責(zé)從管理模塊接收到的SIP 進(jìn)入的消息,分發(fā)SIP消息到其他模塊。
因?yàn)槠年P(guān)系,筆者在這里不再做太多關(guān)于PJSIP的介紹,網(wǎng)絡(luò)有很多關(guān)于PJSIP協(xié)議棧,PJSIPUA的使用方式,讀者可以安裝練習(xí)。這里,我們主要介紹pjsip_endpoint的作用,因?yàn)樗苯佑绊懼覀兒罄m(xù)章節(jié)中所討論的Asterisk呼叫流程。
2、PJSIP在Asterisk的結(jié)構(gòu)
在Asterisk環(huán)境中,PJSIP通過各自的模塊對終端,業(yè)務(wù)訂閱,認(rèn)證和傳輸都進(jìn)行管理。PJSIP模塊的幾個(gè)核心模塊如下:

Asterisk中PJSIP相關(guān)的幾個(gè)主要包括:
- res_pjsip 模塊,這是一個(gè)基礎(chǔ)模塊,提供對上層其他業(yè)務(wù)的支持。
- res_pjsip_session模塊,提供呼叫,媒體和會(huì)話管理,包括媒體流處理協(xié)商,DTMF,會(huì)話定時(shí)器設(shè)置,PRACK/100rel,SIP 原因頭處理,傳輸設(shè)置和媒體加密。
- res_pjsip_regiestrar, 提供SIP注冊模塊的管理。
- res_pjsip_pubsub, 提供對SIP消息的訂閱發(fā)布。
- res_pjsip_messaging, 提供MWI事件包處理,分機(jī)/設(shè)備的狀態(tài)拓展支持(例如,PIDF,XPIDF,和CPIM-PIDF)。
3、PSJIP相關(guān)的幾個(gè)實(shí)體對象說明
我們現(xiàn)在討論的PJSIP和以前的chan_sip配置文件有所不同。在PJSIP中,Asterisk借用了幾個(gè)實(shí)體概念來部署相關(guān)配置。如果用戶不了解其具體作用的話,可能引起很多的誤解。在前面的介紹中,我們已經(jīng)說明,Endpoint是PJSIP的核心。通過Endpoint關(guān)聯(lián)了很多相關(guān)的配置屬性關(guān)系。以下是一個(gè)ER關(guān)系圖實(shí)例,讀者可以基本了解其配置關(guān)系:

當(dāng)一個(gè)新的SIP請求進(jìn)入到PJSIP時(shí),PJSIP的res_pjsip模塊首先需要確認(rèn)Endpoint在res_pjsip中的注冊類型。注冊類型不同則關(guān)聯(lián)不同的配置參數(shù)設(shè)置。當(dāng)然,Endpoint的確認(rèn)也有不同的優(yōu)先級。用戶可以通過CLI命令來檢查這些Endpoint類型:
- *CLI> pjsip show identifiers
- Identifier Names:
- name not specified
- ip
- username
- anonymous
- header
- auth_username
大部分情況下,PJSIP會(huì)通過“From”頭中的username來查詢Endpoint中的username。如果匹配到了相應(yīng)的username,則繼續(xù)匹配其他的配置參數(shù)。
在res_pjsip中提供了對Endpoint的類型定義,不同的類型又和不同的配置進(jìn)行了綁定,這些具體的配置包括:
- Transport支持,提供對傳輸協(xié)議配置(TCP/UDP),加密配置(TLS/SSL),WS配置。
- AUTH支持,認(rèn)證部分提供對用戶的Inbound和Outbound的Authentication處理,包括用戶注冊信息處理以及認(rèn)證方式。
- AOR(Address of Record)支持,此配置通知Asterisk在那里可以連接endpoint終端。如果沒有AOR記錄的話,不能連接endpoint終端。當(dāng)Asterisk收到一個(gè)注冊請求時(shí),它首先需要查詢可用的AOR記錄。
- REGISTRATION注冊,提供對外SIP服務(wù)器的注冊支持,對接ITSP trunk配置。
- IDENTIFY支持,此配置控制res_pjsip_endpoint_identifier_ip模塊來決定進(jìn)入到系統(tǒng)的數(shù)據(jù)是哪種endpoint終端類型。如果Asterisk收到一個(gè)來自于某個(gè)IP地址的數(shù)據(jù),則匹配這個(gè)地址的相應(yīng)的終端。
- Contact配置選項(xiàng)工作方式類似于SIP URL的別名,保存進(jìn)入到注冊消息。它可以關(guān)聯(lián)單個(gè)獨(dú)立的SIP 用戶代理。
以上ER圖例說明了它們之間的關(guān)聯(lián)關(guān)系。如果用戶對某些概念理解有問題的話,可以查閱筆者的歷史文檔,這里不再對基本概念做過多討論,相關(guān)文章包括:
- B2BUA/SBC/Proxy的SIP消息重構(gòu)和RFC7092詳解
- 一封信讀懂SIP注冊消息關(guān)鍵詞
- 深入理解SIP服務(wù)器的注冊和定位服務(wù)流程中關(guān)于AOR和COntact的說明。
4、Asterisk中PJSIP的處理流程
根據(jù)前面章節(jié)的介紹,一個(gè)呼叫通過SIP呼叫到Asterisk系統(tǒng)中,需要經(jīng)過幾個(gè)模塊的處理。讀者需要更多關(guān)注Res_pjproject.c文件(啟動(dòng)PJSIP,分配模塊資源,設(shè)置log等)和Res_pjsip.c 文件。Res_pjsip.c開始加載其其他的上層模塊的邏輯處理,包括創(chuàng)建thread,監(jiān)聽IP和端口,確認(rèn)Endpoint類型和優(yōu)先級判斷,確認(rèn)endpoint相關(guān)配置,DTMF,管理SDP,Callerd等。以下圖例是關(guān)于Asterisk服務(wù)器中PJSIP協(xié)議如何處理一個(gè)呼叫請求的處理流程。

Asterisk中PJSIP的呼叫處理流程如下:
- 首先啟動(dòng)PJSIP協(xié)議棧。
- 把新的request存放到threadpool中,等待處理。
- 確認(rèn)Endpoint以及其配置類型。
- 如果有NAT支持,則修改NAT配置。如果沒有,則繼續(xù)執(zhí)行下一步流程。
- 如果有re-INVITE則執(zhí)行,修改媒體狀態(tài);如果沒有,則繼續(xù)進(jìn)行下一步操作。
- 創(chuàng)建Dialog。
- 對請求進(jìn)行認(rèn)證處理。
- 創(chuàng)建一個(gè)新的會(huì)話。
- 處理SDP Offer。
- 提取Caller ID,保存提取的值。
- 創(chuàng)建一個(gè)ast_channel object 對象。
- 檢查是否有T38傳真支持處理。如果沒有則繼續(xù)執(zhí)行下一步流程。
- 正式啟動(dòng)IPPBX,進(jìn)入撥號規(guī)則。
5、Asterisk撥號規(guī)則中的PJSIP分機(jī)呼叫流程分析
在Asterisk呼叫中,首先需要根據(jù)呼叫的需求編寫一個(gè)撥號規(guī)則(dialplan)。 這個(gè)撥號規(guī)則定義了呼叫的具體流程。IPPBX的呼叫流程可以非常復(fù)雜,也可以非常簡單。為了配合以上內(nèi)容,我們編寫一個(gè)簡單的撥號規(guī)則來說明PJSIP分機(jī)之間呼叫需要處理的流程。具體撥號規(guī)則的語法如下:

這里需要提前說明,此示例中,分機(jī)已經(jīng)創(chuàng)建,撥號規(guī)則和SIP分機(jī)可以注冊退出注冊。所以,讀者如果需要測試的話,需要提前安裝Asterisk,如果需要real-time的分機(jī)管理的話,需要安裝Asterisk數(shù)據(jù)庫和創(chuàng)建相關(guān)的表(例如,asterisk.ps_endpoints,asterisk.ps_aors等)來存儲(chǔ)PJSIP的AOR,Contacts,Endpoints等數(shù)據(jù)。另外,讀者需要了解關(guān)于PJSIP的CLI命令,方便查看AOR,Contacts,和Auth等數(shù)據(jù)狀態(tài))。以下示例說明了Asterisk環(huán)境中PJSIP分機(jī)呼叫的主要處理流程:

在以上的出來流程中,Asterisk大概需要幾個(gè)步驟來實(shí)現(xiàn)分機(jī)之間的呼叫:
- 注冊的分機(jī)撥打200發(fā)起一個(gè)請求。
- Asterisk檢查此分機(jī)是否屬于特別設(shè)置的context,我們這里是hiastar。如果是,則可以進(jìn)行第三步的流程。這里,讀者可以通過Asterisk CLI 命令檢查AOR 的狀態(tài)。
- 在Asterisk PBX中,首先檢查需要匹配的撥打的號碼,這里用戶撥打了200,當(dāng)然,用戶也可以撥打其他號碼設(shè)置。
- 如果在撥號規(guī)則中匹配檢測通過,則執(zhí)行app 命令Dial,然后撥打PJSIP協(xié)議通道的分機(jī)。
- Asterisk再次檢查分機(jī)的狀態(tài),比如相關(guān)分機(jī)200的AOR和綁定的Contacts。這里,一些新用戶可能比較迷惑,筆者重點(diǎn)說明一下。如果創(chuàng)建了分機(jī)以后,系統(tǒng)可以馬上創(chuàng)建AOR記錄,但是沒有Contacts記錄。如果用戶使用SIP終端注冊登錄以后,Contact 記錄才能顯示,并且綁定了具體的IP地址對象。一個(gè)AOR可以綁定多個(gè)Contacts地址,也就是說,一個(gè)AOR記錄可以支持多臺(tái)SIP終端注冊登錄。在筆者的實(shí)驗(yàn)中,一個(gè)AOR 200,綁定了兩個(gè)SIP 終端,這兩臺(tái)終端都已經(jīng)登錄注冊,所以可以顯示兩個(gè)不同的IP地址。分機(jī)注冊前后的的狀態(tài)


Asterisk檢查到200分機(jī)已經(jīng)注冊,并且獲悉了其IP地址以后,對此SIP分機(jī)發(fā)送INVITE請求,對其發(fā)起呼叫。
通過以上六個(gè)步驟,PJSIP分機(jī)之間的呼叫創(chuàng)建完成。
6、總結(jié)
此文章主要介紹了關(guān)于Asterisk環(huán)境中使用PJSIP分機(jī)撥號的基本處理流程和其相關(guān)的技術(shù)架構(gòu)。首先,筆者簡單說明了PJSIP的介紹了PJSIP的使用原因和官方說明,然后介紹了PJSIP的核心模塊,然后介紹了PJSIP在Asterisk的架構(gòu)和其相關(guān)的應(yīng)用服務(wù)模塊。因?yàn),PJSIP涉及了SIP協(xié)議幾個(gè)主要的概念,筆者又分別說明了幾個(gè)概念之間的綁定關(guān)系。為了讓讀者能夠充分了解Asterisk中PJSIP的處理流程,筆者通過圖例的方式,按照總共13個(gè)步驟說明了PJSIP是如何一步步進(jìn)行呼叫流程的處理的。最后,筆者通過一個(gè)PJSIP分機(jī)呼叫的示例,配合簡單的撥號規(guī)則說明了撥號規(guī)則的處理流程。
參考資料:
www.asterisk.org
www.freepbx.org.cn
www.pjsip.org


關(guān)注微信公眾號:asterisk-cn,獲得有價(jià)值的Asterisk行業(yè)分享
Asterisk freepbx,F(xiàn)reeSBC技術(shù)文檔: www.freepbx.org.cn
融合通信商業(yè)解決方案,協(xié)同解決方案首選產(chǎn)品:www.hiastar.com
Asterisk/FreePBX中國合作伙伴,官方qq技術(shù)分享群(3000人):589995817