PJSIP開發指南-第二章


一、模塊

2.1    模塊框架

模塊框架的主要作用是在應用程序組件之間分發SIP消息,PJSIP的所有的組件,包括dialog和transaction都是以模塊方式實現的,沒有模塊,核心協議棧將不知道如何處理SIP消息。

模塊架構思基於簡單但是非常強大的接口抽象,對於到達的消息,Endpoint 按照優先級向所有的模塊分發消息,直到其中一個模塊告知已經處理這個消息。對於出去的消息,endpoint分發消息到所有模塊,在消息未到達網絡之前,允許任何模塊對消息做最后的修改。

2.1.1        模塊聲明

模塊接口再<pjsip/sip_module.h>中聲明,如下:

/**

 * The declaration for SIP module. This structure would be passed to

 * #pjsip_endpt_register_module() to register the module to PJSIP.

 */

struct pjsip_module

{

    /** To allow chaining of modules in the endpoint. */

    PJ_DECL_LIST_MEMBER(struct pjsip_module);

 

    /**

     * Module name to identify the module.

     *

     * This field MUST be initialized before registering the module.

     */

    pj_str_t name;

 

    /**

     * Module ID. Application must initialize this field with -1 before

     * registering the module to PJSIP. After the module is registered,

     * this field will contain a unique ID to identify the module.

     */

    int id;

 

    /**

     * Integer number to identify module initialization and start order with

     * regard to other modules. Higher number will make the module gets

     * initialized later.

     *

     * This field MUST be initialized before registering the module.

     */

    int priority;

 

    /**

     * Optional function to be called to initialize the module. This function

     * will be called by endpoint during module registration. If the value

     * is NULL, then it's equal to returning PJ_SUCCESS.

     *

     * @param endpt   The endpoint instance.

     * @return       Module should return PJ_SUCCESS to indicate success.

     */

    pj_status_t (*load)(pjsip_endpoint *endpt);

 

    /**

     * Optional function to be called to start the module. This function

     * will be called by endpoint during module registration. If the value

     * is NULL, then it's equal to returning PJ_SUCCESS.

     *

     * @return       Module should return zero to indicate success.

     */

    pj_status_t (*start)(void);

 

    /**

     * Optional function to be called to deinitialize the module before

     * it is unloaded. This function will be called by endpoint during

     * module unregistration. If the value is NULL, then it's equal to

     * returning PJ_SUCCESS.

     *

     * @return       Module should return PJ_SUCCESS to indicate success.

     */

    pj_status_t (*stop)(void);

 

    /**

     * Optional function to be called to deinitialize the module before

     * it is unloaded. This function will be called by endpoint during

     * module unregistration. If the value is NULL, then it's equal to

     * returning PJ_SUCCESS.

     *

     * @param mod The module.

     *

     * @return       Module should return PJ_SUCCESS to indicate success.

     */

    pj_status_t (*unload)(void);

 

    /**

     * Optional function to be called to process incoming request message.

     *

     * @param rdata   The incoming message.

     *

     * @return       Module should return PJ_TRUE if it handles the request,

     *           or otherwise it should return PJ_FALSE to allow other

     *           modules to handle the request.

     */

    pj_bool_t (*on_rx_request)(pjsip_rx_data *rdata);

 

    /**

     * Optional function to be called to process incoming response message.

     *

     * @param rdata   The incoming message.

     *

     * @return       Module should return PJ_TRUE if it handles the

     *           response, or otherwise it should return PJ_FALSE to

     *           allow other modules to handle the response.

     */

    pj_bool_t (*on_rx_response)(pjsip_rx_data *rdata);

 

    /**

     * Optional function to be called when transport layer is about to

     * transmit outgoing request message.

     *

     * @param tdata   The outgoing request message.

     *

     * @return       Module should return PJ_SUCCESS in all cases.

     *           If non-zero (or PJ_FALSE) is returned, the message

     *           will not be sent.

     */

    pj_status_t (*on_tx_request)(pjsip_tx_data *tdata);

 

    /**

     * Optional function to be called when transport layer is about to

     * transmit outgoing response message.

     *

     * @param tdata   The outgoing response message.

     *

     * @return       Module should return PJ_SUCCESS in all cases.

     *           If non-zero (or PJ_FALSE) is returned, the message

     *           will not be sent.

     */

    pj_status_t (*on_tx_response)(pjsip_tx_data *tdata);

 

    /**

     * Optional function to be called when this module is acting as

     * transaction user for the specified transaction, when the

     * transaction's state has changed.

     *

     * @param tsx The transaction.

     * @param event   The event which has caused the transaction state

     *           to change.

     */

    void (*on_tsx_state)(pjsip_transaction *tsx, pjsip_event *event);

 

};

 

所有回調函數的指針都是可選的,如果沒有被指定,被默認為返回成功。

Load, start, stop, unload這四個函數指針被enpoint調用,控制模塊的狀態,下面的圖展示了模塊狀態的生命周期:

 

其中on­_rx_request( ) 和 on_rx_response( ) 主要作用是從sip_endpoint或其他的模塊接收SIP消息。Callback函數的返回值非常重要,如果返回非0(相當於true),意味這個模塊已經處理消息,這時,endpoint將停止分發消息到其他的模塊。2.1.3 節呼入消息的處理將會詳細描述。

 

On_tx_request( ) 和 on_tx_response( )在消息被廣播前通過transport manager調用,這給了一些類型模塊(比如:sigcomp 、 message signing)最后修改消息的機會。所有的模塊必須都要返回PJ_SUCCESS(ie zero)。否則分發將會被取消,外出的消息,將會在2.1.4的將會詳細描述。

 

 

On_tsx_state() 函數用來接收事務狀態改變的通知,比如:接收消息、發送消息、定時器事件、傳輸錯誤事件都可能引起通知,在2.1.5節將會詳細的介紹

 

 

2.1.2        模塊的優先級

通過優先級指定回調調用的順序,高優先級模塊將首先調用on_rx_request 和 on_rx_response。最后調用on_tx_request 和 on_tx_response

 

下面是模塊優先級的標准

 

 

/**

 * Module priority guidelines.

 */

enum pjsip_module_priority

{

    /**

     * This is the priority used by transport layer.

     */

    PJSIP_MOD_PRIORITY_TRANSPORT_LAYER = 8,

 

    /**

     * This is the priority used by transaction layer.

     */

    PJSIP_MOD_PRIORITY_TSX_LAYER   = 16,

 

    /**

     * This is the priority used by the user agent and proxy layer.

     */

    PJSIP_MOD_PRIORITY_UA_PROXY_LAYER  = 32,

 

    /**

     * This is the priority used by the dialog usages.

     */

    PJSIP_MOD_PRIORITY_DIALOG_USAGE = 48,

 

    /**

     * This is the recommended priority to be used by applications.

     */

    PJSIP_MOD_PRIORITY_APPLICATION = 64

};

 

注意: 數字越小優先級越高

 

PJSIP_MOD_PRIORITY_TRANSPORT_LAYER 被用於傳輸管理模塊,優先級當前只是被用來控制消息的傳送。低優先級的模塊將在傳輸層調用on_tx_request/on_tx_response回調函數之前調用。高優先級的模塊,將在傳輸層處理之后調用這兩個函數。2.1 4 將詳細介紹outgoing的細節。

 

 

PJSIP_MOD_PRIORITY_TSX_LAYER 是Transaction layer擁有的優先級,事務層接收所有屬於事務層輸入的消息。

 

PJSIP_MOD_PRIORITY_UA_PROXY_LAYER 是UA layer(dialog framework )或 proxy layer 擁有的權限,UA layer 接收所有輸入dialog的消息

 

PJSIP_MOD_PRIORITY_DIALOG_USAGE 是dialog的擁有的優先級,目前,PJSIP實現兩個類型dilalog usage: invite session 和   event subscription(包括refer)。Dialog usage 接收同一個對話的屬於特定session的所有消息。

 

PJSIP_MOD_PRIORITY_APPLICATION 是應用模塊和合適的值,當他采用transaction、dialogs 和 dislog usage時。

 

 

 

2.1.3        處理呼入消息的模塊

當Incoming Message到達時,提供接收消息的緩存區(結構體:pjsip_rx_data,參考第5章的 “Recive Data Buffer”)傳輸管理模塊解析消息,並且把解析的數據結構存放在緩沖區中,把消息傳遞到endpoint.

 

Endpoint 分發接收的消息到每一個注冊模塊,調用on_rx_request和on_rx_response的回調。從高優先級的模塊開始,直到有一個模塊返回非0。當模塊返回非0時, endpoint 不再發送消息到剩余的模塊,因為它假定這個模塊關心該消息的處理。

 

處理消息的模塊可能分發消息到其他模塊,舉例:事務模塊接收到匹配的消息,處理該消息然后再分發到其他到事務用戶(本身也是一個模塊)。Transction傳遞消息,通過回調 on_rx_request 和 on_rx_response 傳遞消息到transction user,在設置transction接收緩沖區以便transction user模塊能其區分transction內部消息和外部消息。

 

下圖顯示模塊的如何重疊調用其他的模塊

 

 

2.1.4        模塊處理呼出消息

出去的請求和響應消息由transmit data buffer(pjsip_tx_data)處理,包含了消息結構體本身、內存池、連續的buffer 和 transport info。

Pjsip_transport_send( ) 被調用發送一個消息,transport manager 調用on­_tx_request 或 on_tx_response 為所有的模塊,處理順序是優先級的低先接收消息。當回調被調用時,消息可能已經或還沒有被transport layer處理。Transport layer 主要負責管理transimit buffer。

l  Transport info

l  打印結構和連續 buffer的結構體

低於PJSIP_MOD_PRIORITY_TRANSPORT_LAYER優先級的模塊,將會接收消息,在這些信息被獲取到之前,這就意味着目標地址沒有被計算出來並且消息還沒有被輸出到連續buffer。

 

如果模塊准備改變消息結構體在打印buffer之前,他一定設置他的優先級高於transport layer的優先級,如果模塊先看真實的packet bytes,再它被傳送到網絡之前,它應該設置優先級低於transport layer。

 

在所有的情況下,模塊一定要返回PJ_SUCCESS. 如果模塊返回錯誤碼,transmission 將被取消,並且錯誤碼將會返回到調用者pjsip_transport_send.

 

2.1.5        事務用戶及狀態回調

回調函數on_tsx_state被用來接收特定事務的通知,當事務狀態發生改變時,回調是唯一的通知路徑。但是transcation的事務改變也可能會因為非消息的事件引起的。比如:超時或者傳輸錯誤

當模塊注冊為事務用戶,才擁有這個回調,在一個事務中,只允許有一個事務用戶,transaction user 能夠被設置為事務再每一個transction基礎上。

 

在dialog創建的事務,transaction user 被設置為 UA layer 模塊,當應用程序手工創建事務時,他們作為事務用戶設置。

 

On_tsx_state回調收到retransmissions的request 和 response消息時,回調將不會再被調用。注意:發送和接收臨時的響應將不會被認為重傳。臨時消息的接收和重傳將會導致回調被調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM