SIP協議壓縮方案-SIP二進制化實現

       在移動終端和移動網絡的雙重推動下,移動互聯網發展非常迅速。SIP協議做爲音視頻通信的首選標準,應用也越來越廣泛。如衆多明文協議一樣,SIP協議具有非常好的擴展性,但由此帶來的數據包卻非常大,如一個普通的SIP包就有500Bytes左右。如果用SIP協議MESSAGE請求發送文本聊天消息,發一句“你好”,消息頭都可能達到600Bytes,在以流程計費的移動互聯網中,這樣的方式就直接在浪費金錢。一個支持ICE的SDP包通常會超過1500Bytes,在實現應用中,都可能達到3000Bytes。在移動互聯網中,MSS通常在1360Bytes左右,傳輸大於MSS的數據都會被分包,在電信3G網絡實測中,如果某基站連接用戶較多的話,一個MSS大小的TCP包通常需要重傳兩到三次,我曾遇到一個3K的TCP包花費40秒服務器才接收完整,抓包發現其中每個分片都被重傳多次,在音視頻通信應用中,延遲40秒才收到的數據包,一切都爲時已晚。而如果能將SIP協議壓縮到一個MSS以內,是提升網絡傳輸效率有效辦法。
       描述SIP標準壓縮方式的是RFC3468,其採用RFC3320sigcomp壓縮方法,但效果並不理想,本文主要描述SIP協議二進制化壓縮方法。隨便提下另一種較簡單的方法採用整包壓縮,即將整個SIP協議包使用如zlib這樣的技術進行壓縮,壓縮比只能達到50%-70%,其整體效果並不明顯,但相比二進制開發難度要小,週期也會更短。這裏我們主要討論一種將SIP進行二進制化的實現方法。
分析像TCP/UDP/RTP/RTCP這些二進制協議的包頭,其中像端口、IP、標誌這些數據,都是以二進制的方式出現的,比如一個IP地址只固定的4bytes,一個端口只需要2bytes,標誌位都是以bit的方式出現的,一個bytes都可以表示八種情況,這是非常節省空間的,而像SIP這樣的文本協議,所有IP、端口、標誌位都是文本的,浪費的空間不言而喻;比如SIP發送一個REGISTER請求,其method都需要佔8個字節,而其實SIP的Method一共只有15個左右,其實5個bits都完全足夠,剩下的3個bits還可以拿來表示TCP/UDP/TLS等,這也就構成了SIP二進制壓縮的基礎,極致情況下壓縮比可達到15%-20%。下面就詳細討論下二進制壓縮的具體實現。
爲保證二進制化與傳輸層解偶,需要同時支持TCP和UDP方式傳輸,因TCP是流方式傳輸,UAS需要從數據流中將SIP消息完整的提取出來,這就需要有能夠指示SIP消息結束的方式,因此需要先定義一個消息頭,通常包括這些信息:消息開始、版本、消息長度,參考STUN消息的頭,可定義如下:
       0                   1           2               3
       0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |0 0 0 0 0 0 0 0 |ver  |  option |   msg length                             |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
此消息頭共佔用四個字節,第一個字節固定0x00表示消息開始,第二個字節高三位用於表示版本,即最大支持八種不同版本,低五位可用於表示各參數選擇,比如是否帶壓縮(二進制化後一樣可以再壓縮)等。剩餘兩字節表示消息長度,即定義一個消息的最大長度爲65535。
將SIP協議進行二進制化,主要是進行關鍵字替換,端口、數字、IP以二進制方式傳輸,下面分享一些基本思路。
SIP協議的基本格式是以header field + 冒號開始,然後跟着與此header相關的參數,以\r\n結尾,整個消息結束後,再加一個\r\n。在其參數中,有些參數的長度是固定可以變成的,比如端口、IP、CSeq,而有些參數取值是變長的,如branch、tag等,我們就需要定義能夠分別表示這兩種情況的類型。大多數參數的取值在256以內,其長度我們可以使用1byte表示,但有的參數會超過256,就需要兩個bytes表示。我們需要先建立一個字典,對那些固定不變的值進行映射。對SIP消息常用的header和參數進行彙總大約有100個,這樣使用1個byte就足夠,但其中0x00已用於消息頭,需要保留,。下面以僞代碼進行說明:

/*這個定義每個字典的具體信息*/
typedef enum param_type
{
      FIXED_LENGTH,                     /*字典類型是固定長度*/
     VARIABLE_LENGTH_1,             /*參數類型是變長,長度用1字節表示,即長度最大256*/
     VARIABLE_LENGTH_2              /*參數類型是變長,長度用2字節表示,即長度最大65536*/
}dict_type_e;

typedef struct sip_binary
{
     char * name;                    /* 參數名稱 */
     dict_type_e type;               /* 參數類型,即上面定義的是定長還是變長 */
     unsigned short fixed_len;    /* 如果參數類型是固定長度,此變量表示具體值*/
     unsigned char param;           /* 參數編號 */

}sip_binary_t;
static sip_binary_t dict[256];

dict[1].name = "request-line";
dict[1].type = FIXED_LENGTH;
dict[1].fixed_len = 0;
dict[1].param = 1;

dict[2].name = "MESSAGE";
dict[2].type = FIXED_LENGTH;
dict[2].fixed_len = 0;
dict[2].param = 2;

dict[3].name = "URI_SCHEME_SIP";
dict[3].type = FIXED_LENGTH;
dict[3].fixed_len = 0;
dict[3].param = 3;

dict[4].name = "URI_USERNAME";
dict[4].type = VARIABLE_LENGTH_1;
dict[4].param = 4;
...

下面以一個實際的SIP header 說明如何進行二進制化:
MESSAGE sip:[email protected]:48868;transport=TCP;ob SIP/2.0
以上header在SIP消息屬於request line,請求不會大於256,因此我們在字典中選擇1來表示request line,其類型爲VARIABLE_LENGTH_1,即長度佔用一個字節,MESSAGE是屬於sip Method,可直接映射到字典中的一個字符,這裏我們就2來表示,其長度是FIXED_LENGTH且爲0;接下來是是一個SIP URI,URI開始的SIP表示sip scheme,常有SIPS、TEL等,這也可以映射到字典中,這裏用3來表示,其長度是FIXED_LENGTH且爲0;接下來的username就需要使用1byte的變長類型,然後用4來表示是useranme參數;domain需要區別是IP還是域名,可以使用inet_pton進行判斷,如果是IP那就是定長類型,如果是域名就是變長類型,這裏我們用5表示IP,6表示域名;接下來的端口可變成兩個字節長度定長,這裏用7表示端口;transport=tcp可直接使用字典中的一位進行替換,這裏用8,ob也是一樣,用9表示;SIP/2.0這樣的版本信息在二進制化時可以去掉,在二進制轉文本時主動加上就行。那我們這個實際壓縮出來的結果就是這樣:
 request-line    MESSAGE sip:[email protected]:48868;transport=TCP;ob SIP/2.0
0x01  0x19   0x02             0x03  0x04 0x0B 18600000000 0x05  0x0C 0x3B 0x34 0x59 0x07 0xBE 0xB4 0x08 0x09
以上例子plaintext長度是67字節,壓縮完後是25個字節。如果使用以上僞代碼進行二進制化,只需要定義一個parser函數將request line進行解析,然後再將對應項添加入一個二進制BUFFER即可。
以上僅僅是的提供一個例子,具體哪些可以壓以及如何壓也需要根據SIP協議實際情況進行調整。如果還需要再節省,那就需要有接入服務層,將一些與連接相關的數據存在接入服務層,當客戶端連接成功後,後續請求直接由接入服務層添加路由等信息。
對SDP的也可以進行二進制化,SDP使用zlib進行壓縮通常能有40%的壓縮比,如果不是極端要求,SDP使用zlib壓縮也是比較好的選擇。

名詞解釋:
MSS: max segment size,TCP最大傳輸數據包大小,此值通常是MTU - 54

新浪微博:@安靜的發狂者
QQ:229675152
專注於移動互聯網音視頻通信領域,歡迎交流;本文爲原創,轉載請保留版權並聯系作者
kamailio/opensips 技術交流QQ羣:118791050

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