翻譯-pjsip開發者指南(三)消息元素

這章的翻譯自己理解的多,並非逐字翻譯。 

Chapter 3:Message Elements
 3.1 Uniform Resource Indicator (URI)
pjsip裏的URI幾乎都是用面向對象的方式(有的人說的基於對象)建模的。所以URI可以統一的被棧處理, 引入新類型的URI也很容易。

 3.1.1 URI “Class Diagram”
下面的圖表展示了URI的設計

下一節將詳細介紹各種對象。

 3.1.2 URI Context
uri context指明何處使用uri(比如request line, From/To header)。context也指明瞭哪裏允許出現uri的元素。比如,傳輸的參數不允許出現在From/To的頭裏。
在PJSIP裏context必須在uri打印進緩衝區或比較兩個uri的時候指定。這樣的話,打印和比較的時候就會忽略那些不允許出現在指定的context中uri。


 3.1.3 Base URI
pjsip_uri的結構體中包含了全部uri可共享的屬性。因此所有的類型都可以放進pjsip_uri裏統一操作。

struct pjsip_uri
{
    pjsip_uri_vptr *vptr;
};


pjsip_uri_vptr指定virtual函數表,它的成員由各類型的uri定義,不建議應用程序直接調用這些函數指針,而是使用更易讀的API(並且這樣可以節省一些類型)。

struct pjsip_uri_vptr
{
    const pj_str_t*   (*p_get_scheme) ( const pjsip_uri *uri);
    pjsip_uri*        (*p_get_uri) ( pjsip_uri *uri);
    int               (*p_print) ( pjsip_uri_context_e context,
    const pjsip_uri   *uri,
    char              *buf, pj_size_t size);
    pj_status_t       (*p_compare) ( pjsip_uri_context_e context,
    const pjsip_uri   *uri1, const pjsip_uri *uri2);
    pjsip_uri *       (*p_clone) ( pj_pool_t *pool, const pjsip_uri *uri);
};

下面的uri函數適用於所有類型的uri對象。這些函數通常以內聯函數的形式實現,在URI的虛函數表中調用相應的函數指針。
 const pj_str_t* pjsip_uri_get_scheme( const pjsip_uri *uri );
Get the URI scheme string (e.g. “sip”, “sips”, “tel”, etc.).

pjsip_uri* pjsip_uri_get_uri( pjsip_uri *uri );
 Get the URI object.通常,除了name address對象將返回name address對象內部的URI之外,所有URI對象都將返回自身。

 pj_status_t pjsip_uri_cmp( pjsip_uri_context_e context,
const pjsip_uri *uri1,
const pjsip_uri *uri2);

Compare uri1 and uri2 according to the specified context
比較的時候會忽略那些context中不允許的uri。如果uri相同會返回PJ_SUCCESS。

 int pjsip_uri_print( pjsip_uri_context_e context,
const pjsip_uri *uri,
char *buffer,
pj_size_t max_size);

根據指定的context打印uri進緩衝區。context中不允許的uri不會打印。

 pjsip_uri* pjsip_uri_clone( pj_pool_t *pool, const pjsip_uri *uri );
用指定的池來深度克隆uri

 3.1.4 SIP and SIPS URI
 pjsip_sip_uri結構體描述了sip和sips URI的方案。 <pjsip/sip_uri.h>中聲明。

 struct pjsip_sip_uri
{
    pjsip_uri_vptr *vptr; // Pointer to virtual function table.
    pj_str_t user; // Optional user part.
    pj_str_t passwd; // Optional password part.
    pj_str_t host; // Host part, always exists.
    int port; // Optional port number, or zero.
    pj_str_t user_param; // Optional user parameter
    pj_str_t method_param; // Optional method parameter.
    pj_str_t transport_param; // Optional transport parameter.
    int ttl_param; // Optional TTL param, or -1.
    int lr_param; // Optional loose routing param, or 0
    pj_str_t maddr_param; // Optional maddr param
    pjsip_param other_param; // Other parameters as list.
    pjsip_param header_param; // Optional header parameters as list.
};

下面的函數是專門用於SIP/SIPS URI對象的。除了這些功能之外,應用程序還可以使用前一節中描述的基本URI函數來處理SIP和SIPS URI。
 pjsip_sip_uri* pjsip_sip_uri_create( pj_pool_t *pool, pj_bool_t secure );
用指定的pool來創建新的SIP URL。如果設置了非零標誌位,則創建SIPS URL。該函數將URL的vptr成員設置爲SIP或SIPS vptr,並將所有其他成員設置爲空值。

 void pjsip_sip_uri_init( pjsip_sip_uri *url, pj_bool_t secure );
初始化SIP URL 結構體

 void pjsip_sip_uri_assign( pj_pool_t *pool,
pjsip_sip_uri *url,
const pjsip_sip_uri *rhs );

執行rhs到url的深度複製

 3.1.5 Tel URI
pjsip_tel_ur 結構體描述tel:URL, <pjsip/sip_tel_uri.h>中聲明。

struct pjsip_tel_uri
{
    pjsip_uri_vptr *vptr; // Pointer to virtual function table.
    pj_str_t number; // Global or local phone number
    pj_str_t context; // Phone context (for local number).
    pj_str_t ext_param; // Extension param.
    pj_str_t isub_param; // ISDN sub-address param.
    pjsip_param other_param; // Other parameters.
};
                                                                       


 下面的函數專門用於TEL URI,除了這些功能之外,應用程序還可以使用前一節中描述的基本URI函數來處理TEL URI。
 pjsip_tel_uri* pjsip_tel_uri_create( pj_pool_t *pool );
創建新的 tel: URI

 int pjsip_tel_nb_cmp( const pj_str_t *nb1, const pj_str_t *nb2 );
這個函數根據RFC3966(tel:URI)的規則比較兩個電話號碼是否相同。它能區分全局和局部數字,並且忽略可視的分隔符。

 3.1.6 Name Address
一個name address( pjsip_name_addr)並非真正定義一個uri類型,而是封裝現有的uri(如sip uri),然後添加display name。

struct pjsip_name_addr
{
    pjsip_uri_vptr *vptr; // Pointer to virtual function table.
    pj_str_t display; // Display name.
    pjsip_uri *uri; // The URI.
};


下面的函數專門用於name address URI對象。除了這些功能之外,應用程序還可以使用前一節中描述的基本URI函數來處理name address對象。

 pjsip_name_addr* pjsip_name_addr_create( pj_pool_t *pool );
創建新的name address。設置初始化虛函數表指針,空白的display name,其他uri成員爲NULL。

 void pjsip_name_addr_assign( pj_pool_t *pool,
pjsip_name_addr *name_addr,
const pjsip_name_addr *rhs );

複製rhs到name_addr

 3.1.7 Sample URI Manipulation Program
 

#include <pjlib.h>
#include <pjsip_core.h>
#include <stdlib.h> // exit()
static pj_caching_pool cp;
static void my_error_exit(const char *title, pj_status_t errcode)
{
    char errbuf[80];
    pjsip_strerror(errcode, errbuf, sizeof(errbuf));
    PJ_LOG(3,(“main”, “%s: %s”, title, errbuf));
    exit(1);
}
static void my_init_pjlib(void)
{
    pj_status_t status;
    // Init PJLIB
     status = pj_init();
     if (status != PJ_SUCCESS) my_error_exit(“pj_init() error”, status);
     // Init caching pool factory.
     pj_caching_pool_init( &cp, &pj_pool_factory_default_policy, 0);
     }
     static void my_print_uri( const char *title, pjsip_uri *uri )
     {
     char buf[80];
     int len;
     len = pjsip_uri_print( PJSIP_URI_IN_OTHER, uri, buf, sizeof(buf)-1);
     if (len < 0)
     my_error_exit(“Not enough buffer to print URI”, -1);
     buf[len] = ‘\0’;
     PJ_LOG(3, (“main”, “%s: %s”, title, buf));
     }
     int main()
     {
     pj_pool_t *pool;
     pjsip_name_addr *name_addr;
     pjsip_sip_uri *sip_uri;
     // Init PJLIB
     my_init_pjlib();
     // Create pool to allocate memory
     pool = pj_pool_create(&cp.factory, “mypool”, 4000, 4000, NULL);
     if (!pool) my_error_exit(“Unable to create pool”, PJ_ENOMEM);
     // Create and initialize a SIP URI instance
     sip_uri = pjsip_sip_uri_create(pool, PJ_FALSE);
     sip_uri->user = pj_str(“alice”);
     sip_uri->host = pj_str(“sip.example.com”);
     my_print_uri(“The SIP URI is”, (pjsip_uri*)sip_uri);
     // Create a name address to put the SIP URI
     name_addr = pjsip_name_addr_create(pool);
     name_addr->uri = (pjsip_uri*) sip_uri;
     name_addr->display = “Alice Cooper”;
     my_print_uri(“The name address is”, (pjsip_uri*)name_addr);
     // Done
 }


 3.2 SIP Methods
3.2.1 SIP Method Representation (pjsip_method)
pjsip中的sip method可以擴展,不需要重編譯庫就可以支持。
 

struct pjsip_method
{
    pjsip_method_e id; // Method ID, from pjsip_method_e.
    pj_str_t name; // Method name, which will always contain the method string.
};

 PJSIP核心庫只聲明核心sip標準(RFC 3261)指定的方法。對於這些核心的方法,pjsip_method的id字段將包含以下枚舉的特定值:

enum pjsip_method_e
{
        PJSIP_INVITE_METHOD,
        PJSIP_CANCEL_METHOD,
        PJSIP_ACK_METHOD,
        PJSIP_BYE_METHOD,
        PJSIP_REGISTER_METHOD,
        PJSIP_OPTIONS_METHOD,
        PJSIP_OTHER_METHOD,
};


 這些枚舉中沒有指定的方法,都是用 PJSIP_OTHER_METHOD這個值。因此,應用程序通過pjsip_method的name字段來獲得相應的方法。
 3.2.2 SIP Method API
下面的參數可以用來處理PJSIP的sip方法對象。

 void pjsip_method_init( pjsip_method *method, pj_pool_t *pool,
const pj_str_t *method_name );

從字符串中初始化method,初始化method字段的id爲一個正確值。

 void pjsip_method_init_np( pjsip_method *method,
pj_str_t *method_name );

從method_name字符串裏面初始化method而不復制字符串( (np stands for no pool))。id字段初始化爲相對應的值。


 void pjsip_method_set( pjsip_method *method,
pjsip_method_id_e method_id );

從method ID的枚舉裏初始化method。name字段初始化爲相對應的值

 void pjsip_method_copy( pj_pool_t *pool,
pjsip_method *method,
const pjsip_method *rhs );

複製rhs到method。


 int pjsip_method_cmp( const pjsip_method *method1,
const pjsip_method *method2 );

比較method1和method2是否相等。相等返回0,小於返回-1,大於返回1。


 3.3 Header Fields
pjsip共享公共頭屬性的所有頭字段,比如 header type,name,short name和虛函數表。因此所有的頭字段都被棧統一處理。
 3.3.1 Header “Class Diagram”
下面的圖標展示了PJSIP header 類圖的一部分,實際的header比這多。PJSIP庫實現了核心SIP規範(RFC 3261)的所有header。其他的header將在PJSIP的擴展模塊實現。

如上圖所示,每一個指定的header通常對特定的header只提供一個函數,也就是說函數創建header實例

 3.3.2 Header Structure
爲了確保頭字段包含公共頭屬性且這些屬性都是正確統一的內存分配,header聲明時候必須調用宏 PJSIP_DECL_HDR_MEMBER作爲header的第一個成員字段,指定header name作爲宏的一個參數。

 #define PJSIP_DECL_HDR_MEMBER(hdr) \
         /** List members. */ \
         PJ_DECL_LIST_MEMBER(hdr); \
         /** Header type */ \
         pjsip_hdr_e type; \
         /** Header name. */ \
         pj_str_t name; \
         /** Header short name version. */ \
         pj_str_t sname; \
         /** Virtual function table. */ \
         pjsip_hdr_vptr *vptr

 3.3.3 Common Header Functions
 pjsip_hdr_vptr指定virtual函數表,有每個header type來實現。表包含以下函數指針:

struct pjsip_hdr_vptr
{
    pjsip_hdr *(*clone) ( pj_pool_t *pool, const pjsip_hdr *hdr );
    pjsip_hdr *(*shallow_clone)( pj_pool_t *pool, const pjsip_hdr *hdr );
    int (*print_on) ( pjsip_hdr *hdr, char *buf, pj_size_t len );
};


儘管應用程序可以自由的直接調用 pjsip_hdr_vptr的函數指針,還是建議使用下面的header API,因爲可以讓程序易讀。
 pjsip_hdr *pjsip_hdr_clone( pj_pool_t *pool,
const pjsip_hdr *hdr );

深度複製hdr header

 pjsip_hdr *pjsip_hdr_shallow_clone( pj_pool_t *pool,
const pjsip_hdr *hdr );

淺克隆hdr header。淺克隆創建一個新的指定頭字段的精準複製,但是很多值的指針依然還是指向原header。通常淺克隆就是從源header到新header的memcpy,因此推測它的操作快於深度克隆。
但是,淺克隆的時候需要仔細。必須明白新的header和舊header共用一個指針。所以,當池中舊的header被銷燬,新的header也無效即使淺克隆的時候使用了不一樣的內存池。或者是舊header的一些值被改了,相應的新header裏的也會改變。
即使這樣,淺克隆依然在庫中廣泛應用。比如,一個dialog一些頭的值總是出現(比如 From, To, Call-Id, Route, and Contac)。當要創建一個請求,dialog淺克隆這個header(而不是全部複製)然後放到請求的消息中。
 int pjsip_hdr_print_on( pjsip_hdr *hdr,
char *buf,
pj_size_t max_size);

將指定的header打印到緩衝區(比如傳輸前)。函數返回打印的字節數,如果溢出返回-1。
 3.3.4 Supported Header Fields
 <pjsip/sip_msg.h>定義PJSIP header的規範。其他的頭字段可能定義在擴展規範裏實現一個特定的功能或者SIP的擴展(比如header使用SIMPLE)。
每個頭字段通常僅定義一個特定的API來操作他們,也就是創建特定頭字段的函數。其他的API通過虛函數表導出。

創建每個頭字段的API以頭字段名後跟_create()來命名。比如,調用函數 pjsip_via_hdr_create()來創建 pjsip_via_hdr 實例。
參考<pjsip/sip_msg.h>中 PJSIP核心定義的完整頭字段列表。
 3.3.5 Header Array Elements
很多的sip header(比如 Require,Contact,via等)可以當成一組放在一起作爲一個單獨的頭字段,以逗號分隔。如:
Contact: <sip:[email protected]>;q=1.0, <tel:+442081234567>;q=0.5
Via: SIP/2.0/UDP proxy1.example.com;branch=z9hG4bK87asdks7, SIP/2.0/UDP
proxy2.example.com;branch=z9hG4bK77asjd

NOTE:PJSIP不支持header裏有複雜header type( Contact, Via, Route, Record-Route)的數組元素,但支持簡單的字符串數組( Require,Supported)。
當解析器遇到上面這種組合的時候,就會把每個數組按照出現的順序分成單獨的header。所以就會被解析爲以下的格式:
Contact: <sip:[email protected]>;q=1.0
Contact: <tel:+442081234567>;q=0.5
Via: SIP/2.0/UDP proxy1.example.com;branch=z9hG4bK87asdks7
Via: SIP/2.0/UDP proxy2.example.com;branch=z9hG4bK77asjd

SIP的規範指明在處理這種header描述方式的消息時不應該有任何區別。所以我們認爲即使不支持頭數組,功能也不會受到影響。

限制這個的原因就是根據經驗,移除了頭數組的確簡化了header的處理。如果支持數組,應用程序不僅要檢查所有的header,還要檢查一些header裏的數組。如果不支持頭數組,應用程序只需要檢查消息的主要頭列表。


 3.4 Message Body (pjsip_msg_body)
 PJSIP的pjsip_msg_body結構體描述SIP消息體。結構體在<pjsip/sip_msg.h>裏。
 

struct pjsip_msg_body
{       
    /** MIME content type.
     * * For incoming messages, the parser will fill in this member with the
     * * content type found in Content-Type header.
     * *
     * * For outgoing messages, application must fill in this member with
     * * appropriate value, because the stack will generate Content-Type header
     * * based on the value specified here.
     * */
    pjsip_media_type content_type;
    /** Pointer to buffer which holds the message body data.
     * * For incoming messages, the parser will fill in this member with the
     * * pointer to the body string.
     * *
     * * When sending outgoing message, this member doesn't need to point to the
     * * actual message body string. It can be assigned with arbitrary pointer,
     * * because the value will only need to be understood by the print_body()
     * * function. The stack itself will not try to interpret this value, but
     * * instead will always call the print_body() whenever it needs to get the
     * * actual body string.
     * */   
    void *data; 
    /** The length of the data.
     * * For incoming messages, the parser will fill in this member with the
     * * actual length of message body.
     * *
     * * When sending outgoing message, again just like the "data" member, the
     * * "len" member doesn't need to point to the actual length of the body
     * * string.
     * */       
    unsigned len;   
    /** Pointer to function to print this message body.
     * * Application must set a proper function here when sending outgoing
     * * message.
     * *
     * * @param msg_body This structure itself.
     * * @param buf The buffer.
     * * @param size The buffer size.
     * *
     * * @return The length of the string printed, or -1 if there is
     * * not enough space in the buffer to print the whole
     * * message body.
     * */
    int (*print_body) ( struct pjsip_msg_body *msg_body,
            char *buf, pj_size_t size );
    /** Pointer to function to clone the data in this message body.
     * */
    void* (*clone_data) ( pj_pool_t *pool, const void *data, unsigned len );
};

下面的API用來操作sip消息對象。

 pj_status_t pjsip_msg_body_clone( pj_pool_t *pool,
pjsip_msg_body *dst_body,
const pjsip_msg_body *src_body);

將消息從src_body複製到dst_body。使用源消息體clone_data成員來複制消息體的正文。

 3.5 Message (pjsip_msg)
 PJSIP的請求和響應消息在結構體pjsip_msg裏,頭文件是<pjsip/sip_msg.h>。下面是一些代碼段,pjsip_msg的描述以及其他支持的結構體。

enum pjsip_msg_type_e
{
    PJSIP_REQUEST_MSG, // Indicates request message.
    PJSIP_RESPONSE_MSG, // Indicates response message.
};
struct pjsip_request_line
{
    pjsip_method method; // Method for this request line.
    pjsip_uri *uri; // URI for this request line.
};
struct pjsip_status_line
{
    int code; // Status code.
    pj_str_t reason; // Reason string.
};
struct pjsip_msg
{
    /** Message type (ie request or response). */
    pjsip_msg_type_e type;
    /** The first line of the message can be either request line for request
     * * messages, or status line for response messages. It is represented here
     * * as a union.
     * */
    union
    {
        /** Request Line. */
        struct pjsip_request_line req;
        /** Status Line. */
        struct pjsip_status_line status;
    } line;
    /** List of message headers. */
    pjsip_hdr hdr;
    /** Pointer to message body, or NULL if no message body is attached to
     * * this mesage.
     * */
    pjsip_msg_body *body;
};




下面的API用來操作sip消息對象。

pjsip_msg* pjsip_msg_create( pj_pool_t *pool,
 pjsip_msg_type_e type);

根據type創建請求或響應消息。

 pjsip_hdr* pjsip_msg_find_hdr( pjsip_msg *msg,
pjsip_hdr_e hdr_type,
pjsip_hdr *start);

在消息中從頭列表的指定的start位置查找指定type的header。如果start是NULL,函數從消息的第一個header搜索。返回NULL說明在這位置後沒有別的header。

 pjsip_hdr* pjsip_msg_find_hdr_by_name( pjsip_msg *msg,
const pj_str_t *name,
pjsip_hdr *start);

在消息中從頭列表指定start位置搜索header版本的長名和短名,根據指定的name查找header。如果start是NULL,函數從消息的第一個header查找。返回NULL說明這位置後沒有別的header。

 void pjsip_msg_add_hdr( pjsip_msg *msg,
pjsip_hdr *hdr);

在消息中加入hdr作爲最後一個header。

 void pjsip_msg_insert_first_hdr( pjsip_msg *msg,
pjsip_hdr *hdr);

在消息中加入hdr作爲第一個header。

 pj_ssize_t pjsip_msg_print( pjsip_msg *msg,
char *buf,
pj_size_t size );

打印這個消息正文到指定緩衝區。函數返回字節數,溢出返回-1。

 3.6 SIP Status Codes
SIP規範(RFC3261)中定義的SIP狀態碼在pjsip_status_code枚舉中,頭文件<pjsip/sip_msg.h>。此外,可以通過調用 pjsip_get_status_text來獲取缺省reason值。

下面的代碼段描述了PJSIP的狀態碼。

 enum pjsip_status_code
 {
     PJSIP_SC_TRYING = 100,
                     PJSIP_SC_RINGING = 180,
                     PJSIP_SC_CALL_BEING_FORWARDED = 181,
                     PJSIP_SC_QUEUED = 182,
                     PJSIP_SC_PROGRESS = 183,
                     PJSIP_SC_OK = 200,
                     PJSIP_SC_MULTIPLE_CHOICES = 300,
                     PJSIP_SC_MOVED_PERMANENTLY = 301,
                     PJSIP_SC_MOVED_TEMPORARILY = 302,
                     PJSIP_SC_USE_PROXY = 305,
                     PJSIP_SC_ALTERNATIVE_SERVICE = 380,
                     PJSIP_SC_BAD_REQUEST = 400,
                     PJSIP_SC_UNAUTHORIZED = 401,
                     ?PJSIP_SC_PAYMENT_REQUIRED = 402,
                     PJSIP_SC_FORBIDDEN = 403,
                     PJSIP_SC_NOT_FOUND = 404,
                     PJSIP_SC_METHOD_NOT_ALLOWED = 405,
                     PJSIP_SC_NOT_ACCEPTABLE = 406,
                     PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED = 407,
                     PJSIP_SC_REQUEST_TIMEOUT = 408,
                     PJSIP_SC_GONE = 410,
                     PJSIP_SC_REQUEST_ENTITY_TOO_LARGE = 413,
                     PJSIP_SC_REQUEST_URI_TOO_LONG = 414,
                     PJSIP_SC_UNSUPPORTED_MEDIA_TYPE = 415,
                     PJSIP_SC_UNSUPPORTED_URI_SCHEME = 416,
                     PJSIP_SC_BAD_EXTENSION = 420,
                     PJSIP_SC_EXTENSION_REQUIRED = 421,
                     PJSIP_SC_INTERVAL_TOO_BRIEF = 423,
                     PJSIP_SC_TEMPORARILY_UNAVAILABLE = 480,
                     PJSIP_SC_CALL_TSX_DOES_NOT_EXIST = 481,
                     PJSIP_SC_LOOP_DETECTED = 482,
                     PJSIP_SC_TOO_MANY_HOPS = 483,
                     PJSIP_SC_ADDRESS_INCOMPLETE = 484,
                     PJSIP_AC_AMBIGUOUS = 485,
                     PJSIP_SC_BUSY_HERE = 486,
                     PJSIP_SC_REQUEST_TERMINATED = 487,
                     PJSIP_SC_NOT_ACCEPTABLE_HERE = 488,
                     PJSIP_SC_REQUEST_PENDING = 491,
                     PJSIP_SC_UNDECIPHERABLE = 493,
                     PJSIP_SC_INTERNAL_SERVER_ERROR = 500,
                     PJSIP_SC_NOT_IMPLEMENTED = 501,
                     PJSIP_SC_BAD_GATEWAY = 502,
                     PJSIP_SC_SERVICE_UNAVAILABLE = 503,
                     PJSIP_SC_SERVER_TIMEOUT = 504,
                     PJSIP_SC_VERSION_NOT_SUPPORTED = 505,
                     PJSIP_SC_MESSAGE_TOO_LARGE = 513,
                     PJSIP_SC_BUSY_EVERYWHERE = 600,
                     PJSIP_SC_DECLINE = 603,
                     PJSIP_SC_DOES_NOT_EXIST_ANYWHERE = 604,
                     PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE = 606,
                     PJSIP_SC_TSX_TIMEOUT = 701,
                     PJSIP_SC_TSX_RESOLVE_ERROR = 702,
                     PJSIP_SC_TSX_TRANSPORT_ERROR = 703,
 };。
 /* Get the default status text for the status code. */
 const pj_str_t* pjsip_get_status_text(int status_code);

PJSIP可以定義消息處理過程(傳輸錯誤,DNS錯誤)中致命錯誤的錯誤碼(7xx)類。這些類只能內部使用,不會傳輸到網絡中。

 3.7 Non-Standard Parameter Elements

在PJSIP中,已知的或者“標準”參數(URI參數,頭字段參數)通常在相應的結構體中作爲單獨的屬性或字段描述。非標準的參數將放入參數列表,每個參數爲一個pjsip_param結構體。非標準參數通常在自己的結構體中聲明爲 other_para字段。


 3.7.1 Data Structure Representation (pjsip_param)
下面的結構體描述了列表中的單獨的參數。

 struct pjsip_param
 {
     PJ_DECL_LIST_MEMBER(struct pjsip_param); // Generic list member.
     pj_str_t name; // Param/header name.
     pj_str_t value; // Param/header value.
 };


舉個例子, pjsip_sip_uri ( 3.1.4小節 “SIP and SIPS URI”)中的other_param和header_param字段描述或者 pjsip_tel_uri (3.1.5小節“Tel URI”)的other_param字段描述。

 3.7.2 Non-Standard Parameter Manipulation
下面是用來操作參數表中非標準參數的函數。
 pjsip_param* pjsip_param_find( const pjsip_param *param_list,
const pj_str_t *name );

不區分大小寫來查找指定參數名

 void pjsip_param_clone( pj_pool_t *pool,
pjsip_param *dst_list,
const pjsip_param *src_list);

參數列表的深(全)克隆。

 void pjsip_param_shallow_clone( pj_pool_t *pool,
pjsip_param *dst_list,
const pjsip_param *src_list);

參數列表的淺克隆。

 pj_ssize_t pjsip_param_print_on( const pjsip_param *param_list,
char *buf,
pj_size_t max_size,
const pj_cis_t *pname_unres,
const pj_cis_t *pvalue_unres,
int sep);

打印參數列表至指定的緩衝區。pname_unres和pvalue_unres分別是pname和pvalue的可允許出現未轉義字符的規範;其他規範之外的字都會被轉義。sep指的是參數之間的分割符(當參數列表是頭參數的時候通常用;或,)。

 3.8 Escapement Rules
PJSIP僅爲以下消息元素在解析期間和打印期間支持自動反轉義:
  #URI的所有類型和元素根據單獨的轉義規則自動反轉義或自動轉義 
  #出現在所有消息元素(URL中的,或者頭字段中的)中的參數自動轉義或反轉義。
  
其他的消息將在堆棧中直接(un-interpreted)傳遞。

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