
此圖例和以下討論均來自于互聯(lián)網(wǎng)資源
在后續(xù)的章節(jié)中,我們將討論answer如何回應offer,會話修改的細節(jié)處理,向對方指示協(xié)商能力,offer/answer交互模式的拓展ICE。
1、背景介紹和基本操作
首先,我們介紹一下我們討論的基本背景環(huán)境。到目前為止,我們討論的核心話題涉及了SDP和準備要討論的offer/anser交互模式。基本上我們都是圍繞兩個核心的規(guī)范來討論,其中,RFC4566(SDP)為基本藍圖,然后配合RFC3264關于offer/answer交互模式。關于SDP的內容,我們在前面的章節(jié)已經(jīng)有完整的介紹(SDP基礎),那個章節(jié)涵蓋了SDP的核心定義/專有名詞,語法,特征屬性,使用場景等相關細節(jié),讀者可以查閱上一個章節(jié)的內容,這里不再贅述。根據(jù)上一個章節(jié)的內容,我們在本章節(jié)進一步討論SDP協(xié)商時使用的交互模式-offer/answer模式。在本章節(jié),我們將重點以RFC3264為藍本,介紹offer/anwer交互模式。筆者主要以offer和answer兩個部分為核心主線,分別按照兩個部分中的單播媒體和多播媒體的處理方式的不同來展開討論。這里提醒讀者,為了更好地支持IPv4,在RFC3264的基礎上,RFC6157對媒體描述管理進行了更新。因此,如果讀者涉及了在IPv6環(huán)境中關于SDP中的媒體描述,讀者可以查閱RFC 6157-4.1章節(jié)的細節(jié)。如果讀者對SDP協(xié)商模式有興趣的話,可以結合具體的代碼示例來做進一步的研究。以下示例是開源SIP協(xié)議棧-PJSIP中關于SDP協(xié)商狀態(tài)機的處理流程示意圖:

鏈接:https://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__SDP__NEG.htm#details
很多技術人員,一說到offer/answer交互模式,就不假思索說這個概念其實非常簡單。事實上,很多人對此概念有不少誤解或者還在半桶水的認知狀態(tài)。因為很多技術人員經(jīng)常排除的問題基本上都是一個簡單的雙方呼叫(單播會話),排查的交互會話描述也就雙方的會話參數(shù),并沒有涉及到多播會話使用場景,例如IP廣播,會議等處理。另外,關于單播和多播場景中的RTP媒體流的處理也非常不同(可參考RFC 6284-7.1.2的端口映射),需要讀者對這些概念有一個充分的理解。因此,很多具體的協(xié)商需要大家了解。

此圖片以及以下圖例均來自互聯(lián)網(wǎng)資源
我們需要首先提醒讀者這些問題,在offer/answer交互模式下,單播會話和多播會話的處理方式是有差別的。SDP(RFC 4566)當時設計的構想是提供一種方式來描述多播骨干網(wǎng)中傳輸?shù)亩嗖。SAP(RFC 2947)的設計構想是作為一種多播機制傳輸SDP消息的。在很多業(yè)務場景中,雖然規(guī)范中支持也允許支持單播操作,但是規(guī)范中支持單播操作相對不太完整。多播會話操作需要覆蓋全部會話參與者的操作,單播會話則僅涉及了兩個參與者以及其各自的認同的工作參數(shù)。具體來說,多播會話比單播會話涉及了更多的關于處理機制和處理方式,在offer/answer交互模式下有不同的處理方式。因此,提醒讀者,我們在下面的討論中,針對各種環(huán)境都會分別介紹單播會話和多播會話的處理方式,希望讀者千萬不要迷惑。例如,如果是多播會話的話,它要求針對具體的媒體流對所有參與方地址發(fā)送一個單多播地址,如果是單播會話的話,它僅需要雙方的兩個地址即可。再比如,如果是多播會話的話,它僅要求標識出會話所使用的具體編碼即可,通知所有會話參與方僅使用標識的編碼,但是,如果是單播會話中,則需要列出一個編碼支持列表,雙方可能都支持某些重復的編碼,通過二次協(xié)商才能決定使用何種編碼。另外,讀者可以想象一下,在單播會話環(huán)境中,隨著技術和網(wǎng)絡環(huán)境的不斷發(fā)展,終端支持的各種編碼或者協(xié)商標識越來越多,盡管雙方的SDP提供了豐富的足夠的會話描述信息,但是因為會話描述定義越來越多,它們所帶來的問題也越來越多,例如定義的語法格式問題,操作細節(jié)的統(tǒng)一性問題。因此,會話雙方究竟如何成功協(xié)商,在技術方面,這仍然存在很多爭議,這也直接導致了很多環(huán)境下,軟硬件終端包括服務器端的雙方SDP協(xié)商不成功的問題。因此,為了實現(xiàn)協(xié)商的簡化和規(guī)范化,RFC 3264基于SDP規(guī)定了一種簡化的offer/answer 交互模式。接下來,我們簡單介紹一下其基本工作原理。
“如無必要,勿增實體”-剃刀原理
在offer/answer交互模式環(huán)境中,會話中的發(fā)起方(offerer)生成一個offer數(shù)據(jù),offer中包括媒體流參數(shù)和傳輸編碼,希望接收媒體的IP地址和端口。offer數(shù)據(jù)傳遞到對端接收方(answerer),接收方也生成一個answer數(shù)據(jù)回復給offerer發(fā)起方,在answer回復數(shù)據(jù)中包含了已匹配的媒體會話描述參數(shù),表示其媒體是否可以接受。然后通過協(xié)商好的傳輸編碼,通過offer消息中的地址和端口對offerer發(fā)起方發(fā)送媒體流。無論是單播會話還是多播會話都可以支持offer/answer交互模式。注意,讀者如果對交互模式下的offer/offerer和answer/answerer有歧義,最好查閱SDP基礎章節(jié)中核心定義全解的內容。
現(xiàn)在,我們討論一些關于協(xié)議層操作的流程。offer/answer模式工作的前提基于一些高級協(xié)議,例如SIP協(xié)議存在,SIP協(xié)議有能力支持SDP的協(xié)商來實現(xiàn)基于代理之間的對會話創(chuàng)建支持。協(xié)議層的操作從一方代理對另外一方發(fā)起初始化的offer開始。對端的代理可以接受offer,并且返回一個answer或者拒絕這個offer。拒絕offer取決于高級協(xié)議層。這里強調一點,offer/answer交互模式是atomic級的,這表示它具有一定的制鎖功能。如果這個answer被拒絕的話,會話將回復到offer之前的狀態(tài)。任何時間其中一個代理都可以生成一個新的offer來更新此會話狀態(tài)。但是,如果代理已經(jīng)收到了一個offer,代理還沒有接受或者拒絕,此代理一定不能生成新的offer。此外,如果代理已經(jīng)生成了一個較早的offer,這個代理在還沒有收到針對較早的offer返回的answer消息或者拒絕消息,此代理一定不能生成一個新的offer。簡單來說,就是代理在沒有收到較早offer的回應結果(應答或者拒絕)之前,它一定不能再生成一個新的offer。有時,我們可能會看到一種特殊狀態(tài),代理已經(jīng)發(fā)送了一個offer后,但是在沒有收到此offer的answer前,如果代理收到了一個offer的話,這種狀態(tài)稱之為 “glare condition”。

Glare Case 狀態(tài)
雙方代理可能同時對對方發(fā)送一個更新offer。這種特殊情況下的處理機制需要更高層協(xié)議來對這種特殊狀態(tài)進行數(shù)據(jù)包發(fā)送到排序處理。如果讀者對glare case 或者異常處理有興趣做進一步研究的話,可以參考RFC 6337-4章節(jié)。接下來,我們開始討論生成offer的流程處理,以及在生成初始化offer中關于單播媒體和多播媒體的處理方式。
2、關于生成初始化offer處理流程
我們討論生成offer消息之前,首先我們一定要確定,無論是offer消息還是answer消息,它們一定是一個有效的SDP消息。
在SDP中針對offer/answer的構成語法可以忽略“e”或者“p=”行。筆者不清楚為什么在offer/answer的消息中可以忽略“e”或者“p=”行,難道因為這兩個會話描述不是十分重要的協(xié)商參數(shù)? “o“行中的會話ID的數(shù)值和版本號必須是一個64位的有符號整形數(shù),并且版本的初始值必須小于(2**62) ? 1,這樣可以防止翻轉。在SDP規(guī)范中,可以允許多個SDP會話描述拼接在一起構成一個大的SDP消息,但是SDP消息使用在offer/answer交互模式下時,一個SDP消息必須包含一個完整的會話描述。
讀者知道,SDP中的"s="傳遞會話主題,這種定義方式對多播會話方式是非常合理的,但是對單播會話方式存在一定問題。因此,一般推薦是”s“行有一個單空格字符或一個破折號構成。SDP "t="行負責傳遞會話時間,通常情況下,對單播會話的媒體來說,它的創(chuàng)建或者結束一般來自于外部的信令的控制,例如,我們現(xiàn)在討論的SIP協(xié)議。那種情況下,"t="行應該設定為”0 0.“。
offer消息中包含零個或者多個媒體流,每個媒體流通過”m=“行的媒體會話和其關聯(lián)特征屬性進行說明。讀者可能不明白,為什么offer消息中可能會包含零媒體信息?其實,包含零媒體仍然有它的原因。如果offer消息中包含零個媒體,這表示發(fā)起方-offerer希望和對端通信,但是發(fā)起方會在將來某一時間時間在此會話中添加那個媒體,添加媒體的方式是通過發(fā)送一個修改的offer來處理。 此媒體可以是一個單播和多播的混合。如果是多播的媒體,那offer消息中需要在"c="行添加多播地址。它們的構成方式取決于它們的媒體是單播還是多播媒體。簡單理解,這里的零媒體不是表示offer沒有什么可做,這表示發(fā)起方可能將來在某一時間發(fā)起媒體流,但是不是現(xiàn)在。如果將來發(fā)起媒體流,offerer會更新offer再次提醒對端answerer。下面,我們繼續(xù)討論offer中的單播媒體場景的處理流程。
3、關于offer的單播媒體處理討論
這里,我們花費一點時間需要詳細說明offer中的單播媒體處理流程。在offer中的單播媒體處理中,offer對媒體的發(fā)送和接收標注涉及了多個方向指示特征屬性(a=sendonly,a=recvonly,a=sendrecv,a=inactive-參考RFC3108和RFC2327),多個特征屬性又具有不同的含義,所以請讀者在閱讀本部分內容時一定要特別注意。讀者也可以查閱筆者的歷史文檔來學習關于這三種屬性應用場景示例。
如果offer僅希望對對端發(fā)送媒體時,offer必須對此媒體標注為send-only的表示,通過特征屬性"a=sendonly"行來標識。如果媒體發(fā)送的方向屬性作為媒體媒體流屬性或者會話屬性出現(xiàn)的話,我們就會認為此媒體標注了媒體發(fā)送方向。同理,如果此offer僅希望從對端接收媒體的話,offer必須對此媒體標識為recvonly,表示僅為接收狀態(tài),通過特征屬性“a=recvonly”表示。如果,offer希望和對端通信,但是,此時,offer既不想發(fā)送媒體也不行接收媒體時,它通過對媒體標識為"a=inactive"行來表示其當時狀態(tài)。
這里,筆者需要提醒一下,因為很多最新的規(guī)范已經(jīng)對RTP協(xié)議的實時應用程序傳輸協(xié)議-RFC3550進行了更新(包括5761,6051,6222,7022,7160,7164,8083和8108),因此一些特別的處理流程需要提醒讀者。如果是涉及了RFC3550中描述的實時傳輸協(xié)議和實時傳輸控制需要的話,為了支持以上三種方向指示的狀態(tài),RTCP同樣需要被發(fā)送和接收。這種情況下,媒體流的方向指示不會影響RTCP的使用。如果offer希望對對端發(fā)送和接收媒體的話,它可以通過"a=sendrecv"行來標識也可以忽略其屬性設置(因為此屬性為默認設置屬性)。
讀者需要注意,offer消息中三種媒體流向的方向有一些不同。對于標記了“a=recvonly”和“a=sendrecv”的媒體流來說,在offer消息中,端口號和地址表示發(fā)起方offerer希望接收媒體流的端口和地址。對于標識為“a=sendonly” RTP 媒體流,端口號和地址間接指示為offerer希望接收RTCP數(shù)據(jù)的地址。除非有明確表示說明,否則RTCP報表數(shù)據(jù)將會發(fā)送到比標識的端口高一位的端口(這是默認的RTCP端口發(fā)送方式)。很多時候,讀者可能對offer中的IP地址和端口使用有一些誤解,這里筆者做進一步的解釋。在offer中出現(xiàn)的ip地址和端口不能指示將要由發(fā)起方offerer發(fā)送出去的RTP/RTCP的源地址,源端口。在offer消息中,如果端口數(shù)為零,這表示媒體已經(jīng)被經(jīng)過offer消息處理,但是此媒體一定不能被使用,因為此初始的offer中沒有任何有效的語法參數(shù)。有時,如果設置端口零可以結束現(xiàn)存的媒體流。一般來說,端口數(shù)量為零表示此媒體流不是offer/answer雙方需要的媒體流。但是,一些特殊的環(huán)境下,編碼類型一樣,但是可能因為payload不同的話,也可能需要做一些協(xié)商處理。針對標識為”a=sendonly“ 或“a=sendrecv”的媒體,在answer的消息中同樣的媒體可能標識了不同的payload。offerer發(fā)起方收到answerer回復后,重新發(fā)送一個offer。這次發(fā)送中,offerer發(fā)起方必須包含一個和answer消息中一樣的媒體payload。這樣才能保證雙方的媒體的payload一致性。有時,為了保證和H323的兼容性,每個方向可以支持不同的payload類型號。
在所有的RTP流使用場景中,fmtp 媒體格式類型可能出現(xiàn)來支持更多的媒體格式類型描述。所有的媒體描述應該包含"a=rtpmap"行,它用來映射相應的payload 類型號碼來對編碼進行編碼處理。如果沒有"a=rtpmap"行的話,應該使用默認的當前的屬性設置(RTP/AVP)。具體默認屬性設置,讀者可查閱RFC3551-6。
offer的協(xié)商過程中,讀者需要另外注意幾個經(jīng)常使用的媒體描述參數(shù)。在協(xié)商過程中,offer消息中必須提供一個"m="行的格式列表,通過偏好優(yōu)先級的順序來通知對端offer中推薦使用的優(yōu)先級編碼格式。優(yōu)先級最高的是最優(yōu)先使用的編碼格式。有時,我們在配置軟交換或者媒體服務器時,雙方呼叫失敗,有可能是編碼不匹配導致,比如說沒有匹配的prefered的編碼。所以,編碼列表的順序是非常重要的,技術人員需要對照服務器端的編碼列表實現(xiàn)對照本地終端的編碼列表順序檢查。比如FreeSWITCH中的編碼優(yōu)先級設置:
或者思科設備設置:
- Cisco-router(config-class)#codec preference 1 g723r63
- Cisco-router(config-class)#codec preference 2 g729br8
- Cisco-router(config-class)#codec preference 3 g711ulaw
- Cisco-router(config-class)#codec preference 4 g726r32 bytes 240
如果ptime特征屬性出現(xiàn)offer中,它表示offer所期望的收到的打包時長,當然,ptime必須大于零。如果offer中出現(xiàn)了bandwidth的話,它表示offer所期望帶寬來傳輸媒體流。當然,帶寬值也允許設置為零(不建議),這表示沒有媒體發(fā)送,同時也關閉了RTCP數(shù)據(jù)發(fā)送。
如果是offerer中的多媒體的話,根據(jù)多媒體類型的不同處理方式也有一定的差別。如果在offer中出現(xiàn)了不同類型的多媒體流(語音,視頻,文本等),這表示發(fā)起方offerer希望同時使用這些多媒體流。比較典型的例子就是視頻會議,視頻會議中,語音和視頻媒體流被同時使用。如果在offer中出現(xiàn)來同樣的媒體類型的話,這表示offerer發(fā)起方期望同時接收或發(fā)送那種同一類型的媒體流。關于同一類型的媒體流收發(fā),雙方可能有一定的規(guī)則策略需要遵守,這取決于本地資源(例如,麥克風/攝像頭和錄像終端)和業(yè)務需求的設置。另外一些限制也可能影響多媒體的本地處理策略,例如不同語音或者視頻媒體流的混音/混屏處理,按需錄像錄音處理等業(yè)務需求。
Offerer發(fā)送方需要根據(jù)不同的指示標識調整為一個相應的狀態(tài)。一旦發(fā)起方Offerer發(fā)送了offer消息以后,發(fā)起方必須準備接收offer描述的任何標識為recvonly的媒體。另外,發(fā)起方必須準備發(fā)送和接收在offer中標識為sendrecv的媒體,并且準備發(fā)送在offer中標識為sendonly的媒體。當然,何時發(fā)送還要取決于對端answer的地址和端口。在RTP的環(huán)境中,雖然可能offerer在answer消息到達之前,提前收到了媒體流,但是發(fā)起方仍然需要收到answer消息后,它才能發(fā)送RTCP接收方報告數(shù)據(jù)。
4、關于offer的多播媒體處理討論
在offer中,如果一個會話描述中包含一個多播媒體流,此多播媒體流列為僅接收或者發(fā)送狀態(tài),這表示參與者(包括了發(fā)起方offerer和接收方answerer)僅能接收或發(fā)送媒體流。和多播媒體流處理方式相比,單播媒體處理僅是發(fā)起方和接收方媒體流的直接收發(fā)。除了以上這個區(qū)別以外,offer中的多播媒體的語法定義可以查閱RFC4566的規(guī)范說明。
參考資料:
https://www.rfc-editor.org/rfc/rfc3264
https://tools.ietf.org/html/rfc6284
https://tools.ietf.org/html/rfc5939
https://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__SDP__NEG.htm

關注微信公眾號:asterisk-cn,獲得有價值的Asterisk行業(yè)分享
Asterisk freepbx FreeSBC技術文檔: www.freepbx.org.cn
融合通信/IPPBX商業(yè)解決方案:www.hiastar.com
如何使用FreeSBC,qq技術分享群:334023047, www.freesbc.cn