翻譯-pjsip開發者指南(四)解析器

  Chapter 4:Parser
 4.1 Features

PJSIP解析器的特性
 #自頂向下手寫解析器。使用PJLIB的掃描器,快速並且能夠減少複雜的解析,使解析器可讀。
 #如上所述,解析很快。在一臺P4/2.6HZ的機器上,它能夠在一秒鐘內解析超過68K的典型800字節SIP消息或860K的80字節url。注意速度可能會有不同,不同的PJSIP版本有不同的表現。
  #可重入,在多處理器的機器上可以擴展( It’s reentrant, which will make it scalable on machine with multiprocessors)
  #可擴展,modules可以在解析器裏面添加新的header或者URI


解析器有有許多可實現的方式來實現更高的性能,比如:
  #解析器採用所有消息元素的零拷貝方式,比如解析消息元素(pvalue,),解析器不會把pvalue的值拷到消息的相應字段裏,而是把指針和長度放到相應字段。這個是有可能的,因爲PJSIP在庫中全程使用pj_str_t,且不要求字符串以NULL結尾。
 #解析器在消息結構體中使用PJLIB的內存池作爲內存分配,速度比傳統的malloc()函數快好幾倍。
 #解析器採用零同步,解析器可重入所以不需要同步函數。
 #使用PJLIB的try/catch異常框架,不僅簡化了解析器使其可讀,還能否減少解析中冗餘的錯誤檢查。對於異常框架,只需要在解析器的頂層函數添加一個異常的處理程序(handler)。


還有一個特性是PJSIP的解析器不使用lazy parsing,雖然可能一些人會誇讚它的用處。在設計之初,我們就決定不用lazy pasring,原因如下:
  #使事情複雜化,尤其是錯誤處理。如果使用lazy parsing,基本上程序的所有部分都要爲之後應用程序訪問特殊消息元素解析時的出錯處理做準備。
  #後面我們也相信PJSIP解析器會很快所以不需要lazy parsing。儘管這麼說,PJSIP解析器裏也會有一些開關,來忽略部分類型的應用程序的一些header(比如,proxies,只需要檢查很少的幾個header type)

 

 4.2 Functions
 PJSIP的解析器聲明主要在<pjsip/sip_parser.h>,定義在 <pjsip/sip_parser.c>。其他的庫可可能提供其他的解析函數和擴展解析器(比如 <pjsip/sip_tel_uri.c>解析TEL URI以及向主解析器註冊這個函數)。
pj_status_t pjsip_find_msg( const char *buf,
        pj_size_t size,
        pj_bool_t is_datagram,
        pj_size_t *msg_size);
檢查buf中收到的包是否包含有效的sip消息,如果發現有,就把消息的大小放到msg_size,如果指定了is_datagram,函數將總是返回PJ_SUCCESS。
注意函數期望的緩衝區以NULL結尾。

pjsip_msg* pjsip_parse_msg( pj_pool_t *pool,
        char *buf, pj_size_t size,
        pjsip_parser_err_report *err_list);
將buf中的緩衝區buffer解析爲sip消息。 如果最後消息的request/status 行被成功解析則返回消息。如果不爲空,所有解析的報錯都會放到err_list。
注意函數期望的緩衝區以NULL結尾。


pjsip_msg* pjsip_parse_rdata( char *buf, pj_size_t size,
        pjsip_rx_data *rdata );
解析buf中的緩衝區消息。如果最後消息的request/status 行被成功解析則返回消息。此外,函數將更新rdata中msg_info部分的指向header的指針。
注意函數期望的緩衝區以NULL結尾。


 4.2.2 URI Parsing
pjsip_uri* pjsip_parse_uri( pj_pool_t *pool,
        char *buf, pj_size_t size,
        unsigned option);

解析buf中的數據解析爲SIP URI。如果option參數爲 PJSIP_PARSE_URI_AS_NAMEADDR,函數將會一直把URI作爲地址。如果是 PJSIP_PARSE_URI_IN_FROM_TO_HDR,函數將不會解析URI後面的參數,如果URI沒有以括號結束(視爲header的參數而不是URI參數)。
這個函數可以解析庫識別的各種URI,正確返回URI實例。
注意函數期望的緩衝區以NULL結尾。

 4.2.3 Header Parsing
void* pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname,
        char *line, pj_size_t size,
        int *parsed_len);
根據hname解析line中的header內容(冒號後的頭的一部分)。返回相應header實例。
注意函數期望的緩衝區以NULL結尾。


 pj_status_t pjsip_parse_headers( pj_pool_t *pool,
         char *input, pj_size_t size,
         pj_list *hdr_list );
在input裏找到多個header,將結果放到hdr_list。函數建議用換行符(例如在sip消息裏)或&來分割header。最後一個header的分隔符可加可不加。
注意函數期望的緩衝區以NULL結尾。


 4.3 Extending Parser
註冊函數指針可以解析新類型的header或URI來擴展解析器。
typedef pjsip_hdr* (pjsip_parse_hdr_func)(pjsip_parse_ctx *context);
pj_status_t pjsip_register_hdr_parser( const char *hname,
        const char *hshortname,
        pjsip_parse_hdr_func *fptr);
註冊新函數來解析新的sip消息頭。

typedef void* (pjsip_parse_uri_func)(pj_scanner *scanner, pj_pool_t *pool,
        pj_bool_t parse_params);
pj_status_t pjsip_register_uri_parser( char *scheme,
        pjsip_parse_uri_func *func);
註冊新函數來解析新的URI格式。
 

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