此圖例以及以下圖例均來自于互聯(lián)網資源關于其它信令支持方式和WebRTC核心概念,ICE/SDP, Offer/answer模式和主要應用場景等,筆者在下面的鏈接中已經進行了比較詳細地分享說明。今天,我們重點對WebSocket 協(xié)議進行討論。
完整SIP/SDP媒體協(xié)商概論-WebRTC/ICE概覽
完整WebRTC架構ICE連接等技術詳解及應用場景分析
很多用戶可能對WebRTC和WebSocket的概念比較模糊。除了web相同以外,從簡單命名我們就可以看出其基本差異,一個是RTC-實現(xiàn)實時通信,一個是socket-實現(xiàn)連接。實際上,它們兩者之間存在很大不同,包括應用場景,傳輸方式, 技術實現(xiàn)目標都有著某些差別。網絡有很多這方面的資料,讀者可以進一步學習其差別。我們這里主要討論的是基于WebRTC用戶場景中,使用WebSocket協(xié)議實現(xiàn)的SIP子信令的支持,特別重點強調的是RFC7188-The WebSocket Protocol as a Transport for the Session Initiation Protocol (SIP),包括其IP語音方案背景說明和RFC7188規(guī)范詳解。
1-背景說明
隨著WebRTC的部署應用越來越多,無論是基于瀏覽器的終端方面還是IP語音通信的服務器端方面發(fā)布了很多的規(guī)范來支持WebRTC技術,并且重點強調了通過WebSocket實現(xiàn)對SIP協(xié)議的支持,例如,ETSI TS 124 371中規(guī)定的WIC (WebRTC IMS Client) 。很多業(yè)務場景中,比如WebRTC-SIP或者WebSocket gateway網關,SBC,服務器端(例如Asterisk,F(xiàn)reeSWITCH,Kamailio/OpenSIPS和其它商業(yè)解決方案)客戶端(例如,JsSIP)等已經開始支持了WebSocket SIP子協(xié)議。
另外,很多的基于WebSocket的瀏覽器終端除了支持SIP協(xié)議以外,也支持了WebSocket,實現(xiàn)了RFC7188中規(guī)定的SIP WebRTC客戶端(例如jsSIP)的功能定義。
SIP WebSocket Client: A SIP entity capable of opening outbound connections to WebSocket servers and communicating using the WebSocket SIP subprotocol as defined by this document. SIP WebSocket Server: A SIP entity capable of listening for inbound connections from WebSocket clients and communicating using the WebSocket SIP subprotocol as defined by this document.
比較常見的應用場景是SBC,呼叫中心或者IPPBX和WebRTC客戶端的對接。WebRTC客戶端(JsSIP)通過SIP通過WebSocket連接實現(xiàn)和SBC或者WebRTC網關設備進行通信,然后SBC通過SIP通過UDP,TCP或者TLS連接方式和對端SIP終端進行通信。
具體應用示例如下-WebRTC 客戶端通過WebSocket實現(xiàn)SBC對接支持:
2-關于RFC7118 規(guī)范完整詳解
2.1-關于RFC7118 介紹
WebSocket已經有具體的規(guī)范定義,RFC6455對其進行了詳解說明。根據RFC6455的規(guī)范說明,WebSocket是基于TCP連接創(chuàng)建的連接協(xié)議,初始協(xié)議握手使用的是HTTP(RFC2616)協(xié)議,通過主要的方式可以實現(xiàn)WebSocket重用現(xiàn)存的HTTP架構。
隨著互聯(lián)網發(fā)展,很多瀏覽器兼容了更多的功能,同時也支持了更多的協(xié)議棧,W3C也要求支持了WebSocket棧,通過WebSocket API接口實現(xiàn)支持。通過這樣的規(guī)范,個人PC端,智能手機也希望能夠支持這些WebSocket API客戶端應用。RFC7118是針對以上需求發(fā)布的規(guī)范。我們今天重點介紹的RFC7118就是一個這樣的協(xié)議,RFC7118發(fā)布使得瀏覽器支持SIP網絡成為可能。
實際上,RFC7118是RFC6455的一個子規(guī)范,它定義了WebSocket 客戶端和服務器端傳輸SIP消息的機制,它是一個可靠性的,支持SIP消息體邊界預留,針對SIP的傳輸協(xié)議,支持了DNA NAPTR服務值。另外,RFC7118定義了兩個SIP實體(包括了SIP WebSocket 客戶端和SIP WebSocket 服務器端)在部署WebSocket時的流程;赟IP的WebSocket 客戶端可以開啟一個對服務器端的連接,基于SIP的WebSocket 服務器端可以監(jiān)聽一個連接。注意,媒體傳輸不在RFC7118討論范圍之內。
2.2-WebSocket Protocol
在介紹其它細節(jié)之前,我們首先介紹一下關于WebSocket協(xié)議(RFC6455)和其加密TLS支持協(xié)議。此協(xié)議定義了連接握手機制,WebSocket子協(xié)議,擴展協(xié)商,用來發(fā)送應用和控制數據的幀格式,掩碼機制和關閉連接狀態(tài)碼等內容。
協(xié)議通信的連接首先需要處理連接握手。WebSocket協(xié)議握手連接是基于HTTP握手機制,使用Get method配合Upgrade請求來實現(xiàn)?蛻舳税l(fā)送請求,服務器端接收請求,協(xié)商成功后,通過HTTP 101狀態(tài)碼進行回復響應。一旦握手完成后,這個連接就會從HTTP更新為WebSocket協(xié)議。握手協(xié)議設計目的是為了重用HTTP架構。在連接握手期間,客戶端和服務器端都同意在應用層協(xié)議使用WebSocket協(xié)議來進行傳輸,并且在雙方終端之間定義了消息交互的格式和語義。這樣的處理機制可以支持一個自定義的協(xié)議或者一個標準的協(xié)議,具備了一定的靈活性和可擴展性。以下圖例是客戶端和服務器端更新切換協(xié)議的處理機制說明。
這里要注意,一旦HTTP 101 響應處理后,客戶端和服務器端將會重用潛在的TCP來發(fā)送WebSocket消息,控制雙方的幀格式。和HTTP不同的是,這里的HTTP連接是一個持久的連接,可以用來支持多個消息的交互。關于其握手處理方式,讀者可進一步閱讀RFC6455-4章節(jié)的Opening Handshake 了解更多詳情,這里不再進行進一步討論。
除了握手以后進行的數據交互機制以外,RFC6455中的WebSocket也定義了為了進行數據交互,在應用程序中使用的消息單元,因此它提供了一個所謂的message-boundary-preserving transport layer,我們稱之為消息邊界預留傳輸協(xié)議層。這些消息單元可以包含UTF-8文本數據或二進制數據和ping/pong幀數據,并且這些UTF-8文本數據或二進制數據可以進一步分解為多個WebSocket的UTF-8文本數據或二進制數據傳輸幀數據支持WebSocket處理需要。
2.3-The WebSocket SIP Subprotocol
通常情況下,我們這里討論的WebSocket Subprotocol是基于WebSocket連接的應用層的協(xié)議。在RFC7188中我們特別針對的是WebSocket SIP 子協(xié)議,此協(xié)議通過WebSocket連接傳輸SIP請求和響應。在此子協(xié)議中,我們仍然需要從連接握手為切入點來進行討論。在SIP WebSocket 客戶端和服務器端協(xié)商中,雙方WebSocket握手協(xié)商流程是在RFC6455-1.3章節(jié)進行定義的。在此規(guī)范中,我們使用的是SIP協(xié)議。因此,客戶端在握手請求的頭字段Sec-WebSocket-Protocol中必須包括“SIP”值,而且在服務器端的101回復響應中,其相應的Sec-WebSocket-Protocol要必須包含一個“SIP”值。在以下WebSocket 握手連接中,客戶端發(fā)送了一個WebSocket SIP subprotocol,同樣服務器端回復的響應中支持了這個請求:
GET / HTTP/1.1 Host: sip-ws.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://www.example.com Sec-WebSocket-Protocol: sip // 包含的SIP 頭字段 Sec-WebSocket-Version: 13
從服務器端返回的握手響應中支持了WebSocket SIP subprotocol,表示服務器端接受了此WebSocket的握手:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: sip // 包含了SIP 頭字段值
一旦雙方在成功完成了此協(xié)商,WebSocket就創(chuàng)建好了。創(chuàng)建好了以WebSocket的連接以后,這個連接就可以用來發(fā)送SIP 請求和響應。這里一定要注意,此連接僅傳輸SIP請求和響應消息,此連接不支持非SIP請求響應消息的傳輸。關于SIP消息編碼。傳輸完成后,當然接下來還要涉及對SIP消息的解碼。前面我們已說明,WebSocket消息可以通過UTF-8文本幀格式或者二進制幀格式進行傳輸。比較巧合的是,SIP協(xié)議中的請求和響應中也支持文本和二進制的消息體傳輸。因此,SIP WebSocket客戶端和SIP WebSocket服務器端雙方必須接受文本幀格式和二進制幀格式數據。這里需要注意,如果在SIP消息中至少出現(xiàn)了一個非UTF-8格式標識字符(包括SIP頭字段和消息體),那么整個消息一定要以一個WebSocket二進制消息再次發(fā)送。這里,因為JavaScript and the WebSocket API的屬性,RFC7188規(guī)范推薦使用UTF-8編碼對通過WebSocket連接傳輸的SIP消息進行處理。
2.4-SIP WebSocket Transport
根據RFC6455規(guī)范定義,我們知道WebSocket是一種可靠性協(xié)議。因為其繼承關系,我們這里的SIP WebSocket 子協(xié)議也是一種可靠性協(xié)議,也是一種SIP可靠性傳輸協(xié)議。簡言之,無論是SIP客戶端和服務器端之間的事務,使用了WebSocket連接來傳輸的話,它們之間的可靠性傳輸必須按照RFC3261定義的流程和定時器來執(zhí)行。
這里特別說明的是,每個SIP消息一定要通過單個WebSocket消息中傳輸,并且,一個WebSocket消息一定不能包含超過一個以上的SIP消息。因為WebSocket傳輸預留了消息體的邊界設置,因此,當使用WebSocket傳輸SIP消息時,SIP消息中的Content-Length 頭字段不是一個必要的字段。通過這樣的方式可以簡化在SIP客戶端和服務器端的SIP消息解析流程。解析SIP消息時,無論是客戶端還是服務器端無需通過Content-Length來創(chuàng)建消息邊界范圍。在解析SIP消息體時,有幾個比較重要的SIP頭字段需要說明。
首先說明的是Via傳輸參數。我們知道,Via頭字段在SIP消息中發(fā)送傳輸協(xié)議的身份標識。在RFC7188中,這里定義使用的是“WS”值通過普通WbeSocket發(fā)送請求,通過加密的WebSocket連接“WSS”(secure WebSocket)發(fā)送加密的請求,按照RFC5246 TLS傳輸規(guī)范處理。具體消息語法格式如下:
transport =/ "WS" / "WSS"
另外一個比較重要的SIP頭字段是SIP URI 傳輸參數。此規(guī)范定義了針對SIP URL使用的傳輸參數是“WS” 。具體的語法格式如下:
transport-param =/ "transport=" "ws"
還有一個比較重要的SIP頭字段是 Via中的“received”。關于Via "received" 參數的處理需要加以特別的注意。在SIP協(xié)議第18章節(jié)中關于接收請求中,接收請求可以是域名或者IP地址。"received"參數中必須包含一個數據包接收的源地址。
當服務器傳輸通過任何傳輸收到一個請求時,它必須檢查在頂部的 Via 頭值中的“sent-by”參數。如果“sent-by”參數中的 host 主機部分包含一個 domain 名稱 或者如果它包含一個 IP 地址,這個地址不同于數據包源地址,此服務器必須在 Via 頭字段中添加一個“received”參數。這個參數必須包含一個從數據包收到的源地址。這樣做的目的是幫助服務器端傳輸發(fā)送響應,因此,它必須源 IP 地址,這個地址是從請求方來的地址。
www.sip.org.cn
不幸的是,增加對"received"參數支持不能很好地兼容到WebSocket協(xié)議的設計框架中。前面我們已經說明,WebSocket連接握手重用了現(xiàn)存的HTTP架構設計。在現(xiàn)存架構中,SIP WebSocket 客戶端和服務器端之間可能會有大量的未知的HTTP代理和TCP均衡負載服務器。如果服務器端把源地址寫入到Via中的“received”頭字段中,這些地址可能就是SIP實體的前端HTTP或者TCP中介的地址。這樣會引起內部服務器地址或者敏感地址暴露給了客戶端的問題。可能用戶需要考慮一些折中的辦法來對Via中的“received”進行處理。假設這樣的一個場景中,SIP響應僅可以通過現(xiàn)存的WebSocket連接發(fā)送,這樣的話,就不會有太多的Via中的“received”參數使用。因此,為了避免SIP WebSocket內部服務器的敏感地址暴露給客戶端,RFC7188更新了RFC3216中18.2.1章節(jié)的描述。具體描述更新為以下內容:
當一個SIP WebSocket服務器端收到了一個請求時,它可以決定不在TOP Via參數中添加一個“received”參數。因此,無論Via頭中的"sent-by"是否包含域名,SIP WebSocket客戶端必須接受在Top Via中無這樣的參數的響應。
SIP實體的定位服務(Locating a SIP Server)是非常重要的。RFC3261有對SIP服務器定位的定義。在本規(guī)范中,針對SIP WebSocket服務器端定義了自己的方式,此規(guī)范支持NAPTR服務值"SIP+D2W"來實現(xiàn)普通的SIP WebSocket服務器端的定位服務,加密服務提供“SIPS+D2W”實現(xiàn)。這里要提醒用戶,在此規(guī)范發(fā)布時,DNS NAPTR/Service Record (SRV) queries仍然不能很好地支持WebSocket 客戶端(包括一些JavaScript 引擎和頁面瀏覽器)。在DNS NAPTR/Service Record缺省或者聲明端口場景中,對于SIP URL來說仍然使用默認端口,“WS”傳輸端口是默認的80端口,默認加密端口是443端口。
2.5-連接存活機制
我們知道,如果要保證一個socket一直處于連接狀態(tài),雙方都要不斷通過發(fā)送存活消息來驗證其狀態(tài)和心跳。SIP WebSocket 客戶端和服務器端也不例外。如果它們之間要一直保持一個開放狀態(tài)的話,它們需要周期性地發(fā)送一個“Ping或者Pong” 幀數據(乒乓球來回處理)。這個處理機制在RFC6455-5.5.2章節(jié)中有說明。
當前可能存在的問題是,對于某些運行于瀏覽器的應用,它們的WebSocket API不支持類似的處理機制,對客戶端或者服務器端周期性地發(fā)送Ping消息或者回復Pong消息。這些應用完全取決于瀏覽器支持本身或者瀏覽器設置。目前,比較主流的瀏覽器對存活支持還是比較友好的。關于SIP連接的存活機制的討論,用戶可以參考其它兩個規(guī)范RFC5626-3.5.1或者RFC6223規(guī)范來進一步學習存活機制的狀態(tài)設置。
2.6-關于WebSocket客戶端和服務器端之間的認證機制
認證是現(xiàn)代網絡環(huán)境安全運行的必要條件。因為WebSocket應用應用于瀏覽器端,客戶端需要和服務器端執(zhí)行雙向交互實現(xiàn)文本,語音和視頻的交互。而且很多時候,服務器端需要對特定客戶端執(zhí)行特別路由處理,因此,服務器端對客戶端的身份認證是非常必要的。在本規(guī)范RFC7118中利用了其它規(guī)范進行身份認證,其相關協(xié)議包括RFC6455,RFC6265,RFC2617和RFC3261。需要注意的是,在WebSocket 協(xié)議(RFC6455)中沒有具體定義認證機制,但是其協(xié)議公布了一個連接握手時的WebSocket Client Authentication說明。具體來說,RFC6455的關于WebSocket 客戶端認證是這樣描述的,在握手連接期間,RFC6455不提供關于客戶端認證的具體機制,WebSocket 可以使用對一般HTTP服務器支持的任何客戶端的認證機制來進行驗證,例如,cookies, HTTP authentication或者TLS authentication。為了更好地實現(xiàn)客戶端和服務器端認證兼容性支持,在WebSocket 認證層面,RFC7188規(guī)范發(fā)布了強制支持和可選的關于SIP WebSocket 客戶端和服務器端的兼容性列表:
當運行在瀏覽器環(huán)境時,SIP WebSocket 客戶端必須準備添加一個會話cookie, 并且前面已經從頁面服務器獲取了一個會話cookie,此頁面服務器URL域名匹配WebSocket域名。具體規(guī)范參考RFC6265。
當執(zhí)行WebSocket 握手時,SIP WebSocket 客戶端必須準備挑戰(zhàn)由SIP WebSocket服務器返回的帶HTTP 401狀態(tài)碼響應。具體規(guī)范參考RFC2617。
SIP WebSocket客戶端可以使用TLS客戶端認證作為可選認證機制。
當cookies出現(xiàn)在WebSocket握手請求時,SIP WebSocket服務器端必須準備讀取會話cookies,并且使用這些cookies值來決定是否WebSocket 連接已經被HTTP 客戶端初始化,作為SIP WebSocket服務器端正在和同樣域名的網站進行協(xié)商處理。
SIP WebSocket服務器應該可以拒絕一個帶HTTP 401狀態(tài)碼的WebSocket握手請求。這個HTTP狀態(tài)碼是由一個HTTP協(xié)議定義的Basic/Digest challenge提供。
2.7-SIP-WSS場景示例
在SIP應用中,絕大部分的使用場景涉及了SIP注冊和SIP呼叫主要流程。在RFC7118規(guī)范在列出了關于SIP-WSS注冊和SIP INVITE呼叫流程。首先,我們介紹如何通過SIP WSS對SIP WebSocket 服務器端進行注冊的示例。以下圖例說明了Alice客戶端通過SIP WSS對代理服務器進行注冊,注冊大概需要4個流程來完成,它們分別包括:連接握手成功,返回101 狀態(tài)碼,切換為SIP注冊,執(zhí)行SIP注冊,返回成功注冊響應碼。
根據以上圖例,我們具體說明其步驟。首先,Alice使用瀏覽器加載頁面,獲取到帶JavaScript,其代碼應用支持了本規(guī)范規(guī)定的WebSocket SIP子協(xié)議。腳本代碼作為一個SIP WebSocket客戶端嘗試和SIP WebSocket服務器端(proxy.example.com)創(chuàng)建連接握手。基于創(chuàng)建的連接,Alice發(fā)送一個SIP注冊請求,請求中包含了Outbound和GRUU支持。因為,瀏覽器中的腳本代碼無法決定來自于WebSocket連接的本地地址,因此使用了一個任意的".invalid" 域名來支持Via頭字段中的"sent-by"參數和Contact頭字段中的URL的主機端口。 具體流程如下:第一步,發(fā)送GET,開始WS握手:
F1 HTTP GET (WS handshake) Alice -> proxy.example.com (TLS) GET / HTTP/1.1 Host: proxy.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: https://www.example.com Sec-WebSocket-Protocol: sip Sec-WebSocket-Version: 13
第二步:服務器端發(fā)送101狀態(tài)碼,進行協(xié)議切換
F2 101 Switching Protocols proxy.example.com -> Alice (TLS) HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: sip
第三步,通過WSS傳輸進行SIP注冊:
F3 REGISTER Alice -> proxy.example.com (transport WSS) REGISTER sip:proxy.example.com SIP/2.0 Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bKasudf From: sip:alice@example.com;tag=65bnmj.34asd To: sip:alice@example.com Call-ID: aiuy7k9njasd CSeq: 1 REGISTER Max-Forwards: 70 Supported: path, outbound, gruu Contact:;reg-id=1 ;+sip.instance=""
第四步,服務器返回完成SIP注冊消息:
F4 200 OK proxy.example.com -> Alice (transport WSS) SIP/2.0 200 OK Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bKasudf From: sip:alice@example.com;tag=65bnmj.34asd To: sip:alice@example.com;tag=12isjljn8 Call-ID: aiuy7k9njasd CSeq: 1 REGISTER Supported: outbound, gruu Contact:;reg-id=1 ;+sip.instance="" ;pub-gruu="sip:alice@example.com;gr=urn:uuid:f81-7dec-14a06cf1" ;temp-gruu="sip:87ash54=3dd.98a@example.com;gr" ;expires=3600
除了SIP-WSS注冊流程以外,RFC7118規(guī)范列出了一個通過SIP INVITE進行語音呼叫的示例列出。具體流程圖示例如下,呼叫流程大概經過了11個步驟。
根據以上流程圖,首先Alice多Bob的AOR地址進行了呼叫。SIP WebSocket服務器端proxy.example.com作為一個SIP代理服務器,路由此呼叫到相應的Bob的contact地址。代理服務器和Bob之間的SIP呼叫通過UDP傳輸完成。Bob接聽了呼叫,然后掛機。第一步,Alice通過WSS呼叫:
F1 INVITE Alice -> proxy.example.com (transport WSS) // WSS INVITE sip:bob@example.com SIP/2.0 Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks From: sip:alice@example.com;tag=asdyka899 To: sip:bob@example.com Call-ID: asidkj3ss CSeq: 1 INVITE Max-Forwards: 70 Supported: path, outbound, gruu Route:Contact:Content-Type: application/sdp
第二步,代理服務器返回100 trying。
F2 100 Trying proxy.example.com -> Alice (transport WSS) SIP/2.0 100 Trying Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks From: sip:alice@example.com;tag=asdyka899 To: sip:bob@example.com Call-ID: asidkj3ss CSeq: 1 INVITE
第三步,代理服務器呼叫Bob,通過UDP傳輸。
F3 INVITE proxy.example.com -> Bob (transport UDP) INVITE sip:bob@203.0.113.22:5060 SIP/2.0 Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bKhjhjqw32c Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks Record-Route:,From: sip:alice@example.com;tag=asdyka899 To: sip:bob@example.com Call-ID: asidkj3ss CSeq: 1 INVITE Max-Forwards: 69 Supported: path, outbound, gruu Contact:Content-Type: application/sdp
第四步, Bob返回響應,準備接收呼叫。
F4 200 OK Bob -> proxy.example.com (transport UDP) SIP/2.0 200 OK Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bKhjhjqw32c ;received=192.0.2.10 Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks Record-Route:,From: sip:alice@example.com;tag=asdyka899 To: sip:bob@example.com;tag=bmqkjhsd Call-ID: asidkj3ss CSeq: 1 INVITE Contact:Content-Type: application/sdp
第五步,代理服務器對Alice 返回 200 OK:
F5 200 OK proxy.example.com -> Alice (transport WSS) SIP/2.0 200 OK Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bK56sdasks Record-Route:,From: sip:alice@example.com;tag=asdyka899 To: sip:bob@example.com;tag=bmqkjhsd Call-ID: asidkj3ss CSeq: 1 INVITE Contact:Content-Type: application/sdp
第六步,確認 200 OK:
F6 ACK Alice -> proxy.example.com (transport WSS) ACK sip:bob@203.0.113.22:5060;transport=udp SIP/2.0 Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bKhgqqp090 Route:,, From: sip:alice@example.com;tag=asdyka899 To: sip:bob@example.com;tag=bmqkjhsd Call-ID: asidkj3ss CSeq: 1 ACK Max-Forwards: 70
第七步,代理服務器確認 200 OK:
F7 ACK proxy.example.com -> Bob (transport UDP) ACK sip:bob@203.0.113.22:5060;transport=udp SIP/2.0 Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bKhwpoc80zzx Via: SIP/2.0/WSS df7jal23ls0d.invalid;branch=z9hG4bKhgqqp090 From: sip:alice@example.com;tag=asdyka899 To: sip:bob@example.com;tag=bmqkjhsd Call-ID: asidkj3ss CSeq: 1 ACK Max-Forwards: 69
雙方開始RTP語音流,正式通話。然后Bob首先掛機,發(fā)送BYE消息到代理服務器,代理服務器再發(fā)送BYE消息到Alice SIP WebSocket 客戶端。最后,Alice對代理服務器發(fā)送BYE消息的200 OK, 然后代理服務器對Bob發(fā)送BYE消息的200 OK。
F8 BYE Bob -> proxy.example.com (transport UDP) BYE sip:alice@example.com;gr=urn:uuid:f81-7dec-14a06cf1;ob SIP/2.0 Via: SIP/2.0/UDP 203.0.113.22;branch=z9hG4bKbiuiansd001 Route:,From: sip:bob@example.com;tag=bmqkjhsd To: sip:alice@example.com;tag=asdyka899 Call-ID: asidkj3ss CSeq: 1201 BYE Max-Forwards: 70
代理服務器對Alice發(fā)送BYE消息,后續(xù)流程忽略。
F9 BYE proxy.example.com -> Alice (transport WSS) BYE sip:alice@example.com;gr=urn:uuid:f81-7dec-14a06cf1;ob SIP/2.0 Via: SIP/2.0/WSS proxy.example.com:443;branch=z9hG4bKmma01m3r5 Via: SIP/2.0/UDP 203.0.113.22;branch=z9hG4bKbiuiansd001 From: sip:bob@example.com;tag=bmqkjhsd To: sip:alice@example.com;tag=asdyka899 Call-ID: asidkj3ss CSeq: 1201 BYE Max-Forwards: 69
在RFC7188規(guī)范中還規(guī)定了其它的一些安全考慮和語法規(guī)范,例如關于加密WebSocket連接使用,關于SIPS的使用,SIP注冊的進一步說明,部署指南,用戶認證場景等章節(jié)。這些章節(jié)相對不是非常重要的內容,筆者這里不再討論。
3-總結
很多程度上,WebRTC的技術發(fā)展依賴于瀏覽器的技術發(fā)展。通過瀏覽器實現(xiàn)和電腦設備的通信是互聯(lián)網應用的一個大的飛躍,它能夠融合更多的語音,視頻和其它數據交互。在企業(yè)通信方面,WebRTC利用WebSocket傳輸實現(xiàn)SIP語音通信讓企業(yè)通信能力上了一個新的臺階。RFC7188規(guī)范對SIP通信結合WebSocket傳輸進行了完整的規(guī)定,用戶通過SIP websocket 客戶端和服務器端實現(xiàn)瀏覽器和其它應用的對接。筆者首先介紹了WebRTC以及WebSocket的應用場景,包括IMS的規(guī)范要求,另外,詳細介紹了關于RFC7188的核心內容,包括連接握手,存活處理,用戶認證和SIP傳輸以及語法定義和注冊呼叫示例。筆者希望用戶在部署SIP WebSocket客戶端和服務器端的過程中能夠充分考慮到其業(yè)務的局限性,另外可以充分利用SIP WebSocket 客戶端和服務器端的靈活部署能力來服務更強大的業(yè)務場景。
參考資料:
https://libwebsockets.org/
https://www.rfc-editor.org/rfc/rfc7118.html
https://www.rfc-editor.org/rfc/rfc6455.html
www.asterisk.org.cn
www.asterisk.org
www.dinstar.cn
https://jssip.net/
www.sip.org.cn
https://github.com/resiprocate/resiprocate/wiki/WebRTC-and-SIP-Over-WebSockets
https://github.com/SIPp/sipp/issues/124https://www.etsi.org/deliver/etsi_ts/124300_124399/124371/15.02.00_60/ts_124371v150200p.pdf
https://arxiv.org/abs/1601.00184