SIP協議


1、簡介

SIP(Session Initiation Protocol,會話初始協議)是由IETF(Internet Engineering Task Force,因特網工程任務組)制定的多媒體通信協議。廣泛應用於CS(Circuit Switched,電路交換)、NGN(Next Generation Network,下一代網絡)以及IMS(IP Multimedia Subsystem,IP多媒體子系統)的網絡中,可以支持並應用於語音、視頻、數據等多媒體業務,同時也可以應用於Presence(呈現)、Instant Message(即時消息)等特色業務。所有說,有IP網絡的地方就有SIP協議的存在。

SIP協議與HTTP類似,SIP可以減少應用特別是高級應用的開發時間。

2、SIP消息的兩種會話模式

在SIP IM通信應用中,一般存在兩種會話模式:

  • Session Model
  • Pager Model

2.1 Session Model

會話中,對於消息體內容大於1300字節時,一般采用Session Model。其會話建立過程(整個流程稱為一個Dialogue)如下圖所示:

主叫方A呼叫被叫方B:

  • 步驟1:主叫方A發送INVITE請求到代理服務器;
  • 步驟2:代理服務器發送100 Trying 響應主叫方A;
  • 步驟3~6:代理服務器搜索被叫方B的地址,獲取地址后轉發INVITE請求;
  • 步驟7~9:被叫方B生成的180 振鈴響應,返回給主叫方A;
  • 步驟10~12:被叫方B生成的200 OK響應,返回給主叫方A;
  • 步驟13~17:主叫方A收到被叫方B200 OK響應后,向被叫方B發送一個ACK,會話建立;
  • 步驟18~20:會話結束后,任何參與者(A或B)都可以發送一個BYE請求來終止會話;
  • 步驟21~23:主叫方A發送200 OK響應來確認BYE,會話終止。

2.2 Pager Model

在Sip消息中,對於消息體不大於1300字節時,一般采用Pager Model。Sip消息通信中采用MESSAGE方法,MESSAGE方法本身並不建立Dialog,在多數應用中,每條IM消息都是獨立的,頗似分頁消息。

MESSAGE方法的由來

RFC3428對Sip協議進行了擴展,在Sip協議中增加了MESSAGE請求方法。采用Pager Model進行通信,傳遞不超過1300字節的數據。MESSAGE方法詳細可參考 “SIP-RFC3428” https://tools.ietf.org/html/rfc3428 。

MESSAGE方法消息體

 當User1想給User2發送IM消息時,只需構造一個MESSAGE,發出去即可。

對於其消息體body可以是任何MIME格式。但必須支持plain/text格式,可以選擇支持message/cpim、message/sdp格式,可能用message/cpim會好一點,因為已有的IM系統標准是message/cpim格式。

Pager Model請求流程

以User1向User2發送MESSAGE消息為例:

  • 步驟1:User1發送MESSAGE請求到代理服務器;
  • 步驟2:代理服務器轉發User1的MESSAGE請求給USER2;
  • 步驟3:User2收到User1的消息后,回復200 OK給代理服務器;
  • 步驟7~9:代理服務器轉發200 OK回復給User1

3、SIP消息格式

SIP消息體結構與Http協議結構相似,均由三部分組成:

  • 請求行(request-line) or 狀態行(status-line)
  • 消息頭(header)
  • 正文(body)

3.1 請求行

請求行格式:

Method Request-URI SIP-Version CRLF

請求行舉例:

INVITE sip:bob@zte.com SIP/2.0 /r/n

Method

以下列出了幾種消息Method方法:

Request-URI

指示請求的用戶或者服務的地址信息。

SIP-Version

請求和響應消息都需要包含SIP版本信息。

3.2 狀態行

狀態行格式:

SIP-Version Status-Code Reason-Phrase CRLF

狀態行舉例:

SIP/2.0 200 OK /r/n

Status-Code狀態碼:

狀態代碼由3位數字組成,表示請求是否被理解或被滿足。狀態代碼的第一個數字定義了響應的類別,后面兩位沒有具體的分類。第一個數字有五種可能的取值:

常用的狀態碼舉例:

3.3 消息頭

發送MESSAGE消息給user2

MESSAGE sip:user2@domain.com SIP/2.0
Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse
Max-Forwards: 70
From: sip:user1@domain.com;tag=49583
To: sip:user2@domain.com
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 18

user2, come here.

Header 字段含義說明:

4、SIP消息舉例

4.1 MESSAGE消息(Pager Model)

以User1發送MESSAGE消息給user2為例:

步驟1:User1發送MESSAGE請求到代理服務器

MESSAGE sip:user2@domain.com SIP/2.0

Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse
Max-Forwards: 70
From: sip:user1@domain.com;tag=49583
To: sip:user2@domain.com
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 18

user2, come here.

步驟2:代理服務器轉發User1的MESSAGE請求給USER2,代理服務器收到步驟1請求,到數據庫中查找User2(注冊過程中生成數據庫),隨后生成步驟2的數據。

MESSAGE sip:user2@domain.com SIP/2.0
Via: SIP/2.0/TCP proxy.domain.com;branch=z9hG4bK123dsghds
Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse;received=1.2.3.4
Max-Forwards: 69
From: sip:user1@domain.com;tag=49394
To: sip:user2@domain.com
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 18

user2, come here.

步驟3:User2收到User1的消息后,回復200 OK給代理服務器。直接回應(200-OK) 沒有Body,也不攜帶Contact頭域。

SIP/2.0 200 OK
Via: SIP/2.0/TCP proxy.domain.com;branch=z9hG4bK123dsghds;received=192.0.2.1
Via: SIP/2.0/TCP user1pc.domain.com;;branch=z9hG4bK776sgdkse;received=1.2.3.4
From: sip:user1@domain.com;tag=49394
To: sip:user2@domain.com;tag=ab8asdasd9
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Length: 0

步驟4:代理服務器轉發200 OK回復給User1。代理服務器收到回復后,去掉最頂端的Via,轉發如下消息給User1。

SIP/2.0 200 OK

Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse;received=1.2.3.4
From: sip:user1@domain.com;;tag=49394
To: sip:user2@domain.com;tag=ab8asdasd9
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Length: 0

4.2 REGISTER消息

4.2.1 非鑒權注冊消息

192.168.2.161機器發送注冊消息給192.168.2.89服務器:

REGISTER sip:192.168.2.89 SIP/2.0

Via: SIP/2.0/UDP 192.168.2.161:10586
Max-Forwards: 70
From: <sip:01062237496@192.168.2.89>;tag=ca04c1391af3429491f2c4dfbe5e1b2e;epid=4f2e395931
To: <sip:01062237496@192.168.2.89>
Call-ID: da56b0fab5c54398b16c0d9f9c0ffcf2@192.168.2.161
CSeq: 1 REGISTER
Contact: <sip:192.168.2.161:10586>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER"
User-Agent: RTC/1.2.4949 (BOL SIP Phone 1005)
Event: registration
Allow-Events: presence
Content-Length: 0

當注冊成功(回送200 OK)時,服務器發送的res消息參考如下:

SIP/2.0 200 OK

Via: SIP/2.0/UDP 192.168.2.161:10586
From: <sip:01062237496@192.168.2.89>;tag=ca04c1391af3429491f2c4dfbe5e1b2e;epid=4f2e395931
To: <sip:01062237496@192.168.2.89>;tag=-00834-14d0805b62bc026d
Call-ID: da56b0fab5c54398b16c0d9f9c0ffcf2@192.168.2.161
CSeq: 1 REGISTER
Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,REGISTER,INFO,UPDATE,PRACK,REFER,SUBSCRIBE,NOTIFY,MESSAGE
Contact: sip:192.168.2.161:10586
Content-Length: 0
Expires: 3600

4.2.2 鑒權注冊消息

 當需要鑒權注冊時

  • 請求端192.168.2.161發送注冊消息給192.168.2.89服務器
  • 服務器對192.168.2.161發送“401 Unauthorized”信息給請求端,提示請求端需要帶上鑒權信息重新注冊
  • 請求端帶上鑒權信息后(帶有“Authorization”頭字段)重新向服務器注冊
  • 服務器驗證鑒權頭的正確性,如果鑒權成功,給請求端發送200 OK消息。若失敗,繼續發送401消息。

步驟一:

請求端192.168.2.161發送注冊消息給192.168.2.89服務器

REGISTER sip:192.168.2.89 SIP/2.0

Via: SIP/2.0/UDP 192.168.2.161:8021
Max-Forwards: 70
From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
To: <sip:01062237493@192.168.2.89>
Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
CSeq: 1 REGISTER
Contact: <sip:192.168.2.161:8021>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER"
User-Agent: RTC/1.2.4949 (BOL SIP Phone 1005)
Event: registration
Allow-Events: presence
Content-Length: 0

步驟二:

服務器對192.168.2.161發送401 Unauthorized信息給請求端,提示請求端需要帶上鑒權信息重新注冊:

SIP/2.0 401 Unauthorized

Via: SIP/2.0/UDP 192.168.2.161:8021
From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
To: <sip:01062237493@192.168.2.89>;tag=-001893-38ba013ba3dde36e
Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
CSeq: 1 REGISTER
Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,REGISTER,INFO,UPDATE,PRACK,REFER,SUBSCRIBE,NOTIFY,MESSAGE
Contact: <sip:192.168.2.89:14010>
Content-Length: 0
WWW-Authenticate: Digest realm="192.168.2.89", qop="auth", nonce="e17d377c3d2d9c343e26576a7fd04738481dfc10", opaque="", stale=FALSE, algorithm=MD5

注:

這里192.168.2.89服務器帶了一個WWW-Authenticate頭。里面告知了如下幾個重要的信息:

  • algorithm :加密方式采用MD5
  • nonce:服務器生成的隨機值
  • realm:域名

步驟三:

請求端192.168.2.161通過Authorization頭字段帶上鑒權頭信息,發送一個新的REGISTER消息:

REGISTER sip:192.168.2.89 SIP/2.0

Via: SIP/2.0/UDP 192.168.2.161:8021
Max-Forwards: 70
From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
To: <sip:01062237493@192.168.2.89>
Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
CSeq: 2 REGISTER
Contact: <sip:192.168.2.161:8021>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER"
User-Agent: RTC/1.2.4949 (BOL SIP Phone 1005)
Authorization: Digest username="01062237493", realm="192.168.2.89", qop=auth, algorithm=MD5, uri="sip:192.168.2.89", nonce="e17d377c3d2d9c343e26576a7fd04738481dfc10", nc=00000001, cnonce="12660455546344082314666316435946", response="f57e47ce03162293b9ced07362ce2b79"
Event: registration
Allow-Events: presence
Content-Length: 0

注:

這里比第一次REGIETER消息多了Authorization頭。其中:

  • algorithm:加密方式采用MD5(同401)。
  • nonce:服務器生成的隨機值(同401)。
  • realm:域名(同401)。
  • username:用戶名,這里等同於注冊號碼。
  • cnonce:注冊端生成的隨機值。
  • url:SIP注冊時的url。
  • nc:nonce-count,請求的計數。
  • response:加密后的密碼。

FreeSWITCH加密密鑰生成流程:

其中服務器響應信令如下:

SIP/2.0 401 Unauthorized

Via: SIP/2.0/UDP 172.20.10.6:50024;branch=z9hG4bK-524287-1---e4fb8a53caa2f313;rport=50024

From: "1015"<sip:1015@www.freeswitch.com>;tag=61a25f79

To: "1015" <sip:1015@www.freeswitch.com>;tag=pjeF9m9c63Nym

Call-ID: 89320ZWY3ZWVmNGVhODBiMzUzYWQwM2U3NWE4YTVmMWJlY2Y

CSeq: 1 REGISTER

User-Agent: FreeSWITCH-mod_sofia/1.9.0+git~20180119T195505Z~3f8585f636~64bit

Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, PRACK, NOTIFY, PUBLISH, SUBSCRIBE

Supported: precondition, 100rel, timer, path, replaces

WWW-Authenticate: Digest realm="www.freeswitch.com", nonce="3135ef65-3466-4f70-8035-ec70ff10ae75", algorithm=MD5, qop="auth"

Content-Length: 0
  • HA1:首先我們需要計算HA1,HA1是計算`username:relam:password`字符串的MD5值。除了密碼,其它字段從上述信令中我們能找到,就是計算`1015:www.freeswitch.com:1234`的MD5值(默認密碼為1234)。
HA1 = md5("1015:www.freeswitch.com:1234") = fe7632dead0ef79b9f1b0bde9d71ac7a
  • HA2:HA2是計算method:uri字符串的MD5值。也就是計算REGISTER:sip:www.freeswitch.com的MD5值。
HA2 = md5("REGISTER:sip:www.freeswitch.com") = 357860fa5d775b1ec660c952831a065
  • 加密密碼:最終根據HA1和HA2生成最終的MD5值。即計算`HA1:nonce:nc:cnonce:qop:HA2`字符串的MD5值。從上述信令中找到相關字段。
MD5=md5("fe7632dead0ef79b9f1b0bde9d71ac7a:3135ef65-3466-4f70-8035-ec70ff10ae75:00000001:be28d6ed344661886ad93c8504358936:auth:357860fa5d775b1ec66
  • 最后我們會發現計算出來的值其實就是response字段。FreeSWITCH會按照相同的方式計算加密密碼,並比對來完成鑒權。

步驟四:

服務器驗證鑒權頭的正確性,如果鑒權成功,給請求端發送200 OK消息。若失敗,繼續發送401消息:

SIP/2.0 200 OK

Via: SIP/2.0/UDP 192.168.2.161:8021
From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
To: <sip:01062237493@192.168.2.89>;tag=-001894-a5eb977c8969aa51
Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
CSeq: 2 REGISTER
Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,REGISTER,INFO,UPDATE,PRACK,REFER,SUBSCRIBE,NOTIFY,MESSAGE
Contact: sip:192.168.2.161:8021
Content-Length: 0
Expires: 3600

 


免責聲明!

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



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