翻譯-pjsip開發者指南(二)模塊

這章有些單詞沒翻譯,感覺不翻譯更好。

 Chapter 2:Module
 在pjsip的應用中Module framework是軟件組件中分發消息的主要方法。所有的軟件組件,包括傳輸層和會話層,都是作爲模塊實現。沒有modules,核心堆棧將不知道如何去處理sip消息。
module基於一個簡單但卻功能強大的抽象接口。對於收到的消息,endpoint將消息 從最高級別的模塊開始發送至所有模塊,直到有一個模塊能夠處理這條消息。對於發出的消息,endpoint允許module按照自己的意願在發送到網絡之前來修改消息。

 2.1.1 Module Declaration
module的接口定義在 <pjsip/sip_module.h>

所有函數指針都是可選的,如果沒有指定,視爲返回成功。
 endpoint調用load, start, stop, and unload  這四個指針來控制module的狀態。下面的圖表展示了module狀態的生命週期。

 on_rx_request() 和 on_rx_response() 函數指針是module從endpoint或者其他modules收取消息的主要手段。這些回調的返回值都很重要。如果回調返回非零(即true),則表示module已經處理了這個消息。在這種情形下,endpoint會停止分發消息到其他模塊。2.1.3小節將會詳細描述modules對收到消息的處理。
 transport manager 在消息傳送後調用on_tx_request() 和 on_tx_response()這兩個指針,允許一些類型的modules對消息(eg消息簽名)做最後的更改。所有modules都必須返回PJ_SUCCESS(le 0),否則傳輸將被取消。2.1.4小節將對模塊對發送消息處理進行詳細描述。

 on_tsx_state()用來接收當傳輸狀態改變時的通知,比如收消息,發消息,timer事務,傳輸錯誤事務。2.1.5小節詳細描述回調函數的信息。

 2.1.2 Module Priorities
模塊的優先級指明瞭處理回調優先調用module的順序。有較高(數字越小)優先級的module最先調用 on_rx_request() 和 on_rx_response(),最後調用 on_tx_request() 和on_tx_response()。
下面是設置模塊優先級的標準

note:優先級的數字越小,代表的優先級越高
 transport manager 使用PJSIP_MOD_PRIORITY_TRANSPORT_LAYER這個優先級。這個優先級目前僅用來控制消息傳輸,優先級比這個低(數字比較大)的module在傳輸層處理消息之前將會調用 on_tx_request()/on_tx_response(),而優先級比這個高的則會在傳輸層已經處理消息之後調用。2.1.4詳細介紹module的消息處理。
 事務層使用PJSIP_MOD_PRIORITY_TSX_LAYER優先級。事務層接收所有屬於該事務的消息。
 UA層(dialog framework)使用PJSIP_MOD_PRIORITY_UA_PROXY_LAYER優先級。UA層接收所有屬於該對話集的消息。
 dialog usages使用PJSIP_MOD_PRIORITY_DIALOG_USAGE優先級。目前PJSIP實現了兩類dialog usages:邀請會話和事務訂閱會話(包括REFER訂閱)。dialog usages 接收所有屬於特定會話中的dialog的消息。
 PJSIP_MOD_PRIORITY_APPLICATION是一般應用程序去使用transactions,dialogs和dialog uasegs的一個特定( appropriate value)值。
 2.1.3 Incoming Message Processing by Modules
當有消息傳入時,放入接收消息緩衝區( receive message buffer)( struct pjsip_rx_data, 5.1小節 “Receive Data Buffer”)。transport manager解析這個消息,然後把解析後的數據放入接收消息緩衝區中發送到endpoint。
 endpoint通過調用on_rx_request() 或 on_rx_response()來向每個註冊過的module分發收到的消息緩存,按照優先級高到低,直到有module返回非零。當有一個module返回非零,意味着已經有module處理這條消息了,所以endpoint會停止向其他的module分發消息。
返回非零的回調module也可以向其他module分發消息。例如,事務層module,根據收到的消息,處理併發送至同樣必須是module的transaction user。  transaction通過調用本模塊的 on_rx_request() 和on_rx_response()發送消息至transaction user。通過在收消息的緩衝區設置transaction field,來區分消息是在事務裏還是事務外。
下面的圖表展示了modules是如何一層層調用其他module的。

 2.1.4 Outgoing Message Processing by Modules
發出的請求和響應放到 傳輸數據緩衝區(transmit data buffer-pjsip_tx_data),其中包含消息結構本身,內存池,連續緩衝區和傳輸信息。
當調用pjsip_transport_send()發送消息時,transport manager調用on_tx_request()或on_tx_response ()從最低優先級開始發往各個module。這些回調函數被調用的時候,消息可能被傳輸層處理了,也可能沒有。傳輸層需要把這些信息放入傳輸緩衝區(transmit buffer):
    #傳輸信息
    #在連續的緩衝區內打印消息結構
優先級低於PJSIP_MOD_PRIORITY_TRANSPORT_LAYER的modules將會在獲得這些信息之前收消息。也就是說沒有計算目標地址,也沒有打印連續緩衝區。
如果modules想要在打印進緩衝區前修改消息結構,設置的優先級就必須比傳輸層的優先級高。如果modules想要在傳輸到網絡時看到真實的數據包字節(logging purpose),就必須設置優先級低於傳輸層。
   note: 設置優先級高於傳輸層的一個實例就是logging module,它想打印已經放入連續緩衝區並且計算過目的地址的發送消息。
這種情況下,module必須以PJ_SUCCESS作爲回調的返回值。如果module返回其他錯誤碼,傳輸會被取消,錯誤碼會返給 pjsip_transport_send()的調用者。

 2.1.5 Transaction User and State Callback
module定義中一個特殊的回調(on_tsx_state)被用於接收事務狀態改變時特定事務的通知。這個回調是唯一的因爲傳輸的狀態可能由非消息相關的事務改變(比如timer超時,傳輸錯誤)。
module在特定的事務中已經註冊爲transaction user後,纔可以調用回調函數。每一個事務中只允許一個transaction user。transaction user可以在每個事務的基礎上添加至事務中。
對於dialog中的事務創建,transaction user在特定的dialog中添加到UA層的module。當應用程序手動創建事務時,可以將自己設爲transaction user。

 收到重傳的請求或響應不會調用 on_tsx_state()。注意傳輸或收到臨時響應不被視爲是重傳,也就是說會調用這個回調函數。

 2.1.6 Module Specific Data
一些PJSIP組件可以放置module的數據。方便的來說這種container叫 mod_data,是void類型的指針數組,以module ID作爲索引。
例如,一個收到數據包的buffer (pjsip_rx_data) 有如下的module數據定義:

mod_data數組以module ID爲索引。module ID在module向endpoint註冊時確定。
當把收到的數據buffer(pjsip_rx_data)傳遞到modules時,module可以把數據(module specific data)以一個合適的索引放到mod_data裏,之後這個值可以被module或者應用程序獲取。例如,事務層在mod_data裏放入匹配的事務實例,UA層放入匹配的會話實例。應用程序可以通過調用簡單的數組查找函數pjsip_rdata_get_tsx()或pjsip_rdata_get_dlg ()來檢索id。如下:
                                
 2.1.7 Callback Summary
下表總結了事務的發生以及特定回調的觸發。on_tsx_state()僅有在程序選擇處理有狀態的請求時調用。

Event

on_rx_request() or
on_rx_response()

on_tsx_state()

Receipt of new requests or responses

收到請求或響應

Called

Called

Receipt retransmissions of requests or
responses.

收到請求或響應的重傳

Called ONLY when
priority number is lower
than transaction layer

僅當優先級高於事務層時調用

Not Called

Transmission of new requests or responses.

傳遞新的請求或相應

Not Called

Called

Retransmissions of requests or responses.

請求或響應的重傳

Not Called

Not Called

Transaction timeout

事務超時

Not Called

Called

Other transaction failure events (e.g. DNS
query failure, transport failure)

事務失敗(DNS,查詢失敗,傳輸失敗)

Not Called

Called

 2.1.8 Sample Callback Diagrams
收到的transaction和dialog外的消息

處理過程如下
1)transport manager(pjsip_tpmgr)向endpoint發送所有收到的消息(解析消息後)。
2)endpoint(pjsip_endpt)向已註冊的回調分發消息。回調列表的第一個是事務層。事務層把消息放到事務表裏,且沒有相匹配的事務。
3)endpoint向回調列表的下一個即UA發送消息。
4)UA把消息放到哈希表中,且沒有匹配的dialog set。
5)endpoint繼續向下一個註冊的回調發送消息直到應用程序。應用程序處理消息(有狀態的響應,創建UAS事務,代理請求,創建dialog)。
收到事務中的消息

處理如下:
1)transport manager(pjsip_tpmgr)向endpoint發送所有的消息(解析消息後)。
2)endpoint(pjsip_endpt)向已註冊的回調分發消息。回調列表的第一個是事務層。事務層把消息放到事務表裏,且有匹配的事務。
3)因爲事務回調返回pj_true,所以endpoint不會繼續分發消息。
4)事務處理響應。如果消息是重發,停止處理。否則把消息發到transaction的transaction user(TU),可以是dialog或應用程序。
5)如果TU是一個dialog,dialog處理響應併發送至dialog user(DU,如應用程序)。
6)如果收到的消息已經改變了事務的狀態,事務將會通知TU這個新狀態。
7)如果TU是一個dialog,可能還會通知應用程序dialog狀態的改變。

收到的消息在dialog裏但不在事務裏

處理如下:
1)transport manager(pjsip_tpmgr)向endpoint發送所有的消息(解析消息後)。
2)endpoint(pjsip_endpt)向已註冊的回調分發消息。回調列表的第一個是事務層。事務層把消息放到事務表裏,並且沒有相匹配的事務。
3)endpoint向modules列表的下一個發送消息,直到UA module
4)UA把消息放到dialog的哈希表中,且有匹配的dialog。
5)UA把消息發送到相應的dialog。
6)dialog爲收到的請求創建事務,然後通過調用dialog usages的on_rx_request()和on_tsx_state ()分發請求。

 2.2 Module Management
pjsip的endpoint管理modules。應用程序必須手動向endpoint註冊每個module,以便於堆棧的識別。
 2.2.1 Module Management API
module管理的API在 <pjsip/sip_endpt.h>

 pj_status_t pjsip_endpt_register_module( pjsip_endpoint *endpt,pjsip_module *module );
向endpoint註冊module。endpoint會調用load和start函數來初始化module,並分配給module一個module ID。

 pj_status_t pjsip_endpt_unregister_module( pjsip_endpoint *endpt,pjsip_module *module );
向endpoint解綁module。endpoint調用stop和unload函數來結束一個module。

 2.2.2 Module Capabilities
module可以向endpoint聲明新的功能。目前endpoint管理如下的功能:
  #允許sip方法(允許的頭字段)
  #支持的sip擴展(支持的頭字段)
  #支持的content type(接受的頭字段)
這些頭字段將根據需要自動添加到發出的請求或響應中。
 module通過調用pjsip_endpt_add_capability()來聲明新的功能。

 

 pj_status_t pjsip_endpt_add_capability( pjsip_endpoint *endpt,
                                        pjsip_module *mod,
                                        int htype,
                                        const pj_str_t *hname,
                                        unsigned count,
                                        const pj_str_t tags[]);
向endpoint註冊新功能。htype參數指明向哪個頭添加功能,比如 PJSIP_H_ACCEPT,PJSIP_H_ALLOW, and PJSIP_H_SUPPORTED。hname是可選項,用來指明核心堆棧無法識別的頭字段功能。count和tags參數指明瞭加入頭字段的tag字符串數組。

 

const pjsip_hdr* pjsip_endpt_get_capability( pjsip_endpoint *endpt,
                                             int htype,
                                             const pj_str_t *hname);
獲取功能頭字段,包含爲特定字段註冊到endpoint的所有功能。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章