7、關于會話管理討論
前面的章節(jié)包括上一次筆者發(fā)布的文章中,筆者分別討論了offer和answer雙方的消息生成。這里,筆者將討論會話的修改。修改會話是常見的業(yè)務場景,通過修改會話實現另外一個新的流程。在會話的某個點上,任何會話參與方都可以發(fā)出一個新的offer來修改會話的屬性參數。會話修改是offer/answer交互模式的基本操作,它的處理流程其實和我們前面討論的流程完全一致,通過某些流程修改現存會話的某些參數。offer可能和以前的相同,也可能和以前的不同。當討論修改會話時,我們需要涉及上一個或者前面的SDP,上一個SDP提供了其他的會話參數基礎,這些參數可能已經在offer或者answer消息中存在。現在,筆者先說明一下修改會話的一些基本框架和前提條件。如果offer相同,answer可能和從answerer獲得的上一個SDP中的相同,也可能answer不同。如果已提供的SDP和前面的SDP不同,一些特定的限制需要注意。關于這些限定,筆者在后續(xù)部分討論。理論上說,幾乎所有的會話屬性都可以修改。例如,可以增加一個媒體流,可以刪除現存媒體流,可以修改現存媒體流參數。當發(fā)起一個offer,此offer修改需要修改會話時,除了origin域值其版本號必須在前面的SDP版本號基礎上增加一位數以外,新SDP中的"o="行必須等同于前面的SDP中的"o="行。如果在新SDP中,origin域值不能增加的話,此SDP必須等同于同一origin值域的SDP。answerer應答方必須準備接收offer,此offer包含一個無改變origin值域版本的SDP。根據筆者在前面應答方生成answer的流程,雖然answerer接收了這樣的一個offer,然而,answerer仍然必須生成一個有效的answer消息(此answer消息可能和以前SDP相同不同,也可能不同)。如果已提供的SDP和前面的SDP不同的話,這個新的SDP必須有一個媒體流和前面的SDP媒體流中的匹配。換句話說,如果前面的SDP有四個"m="行,那么在新的SDP中必須至少有四個"m="行。前面SDP中的媒體流排序(從最頂端計數)關系必須匹配新的SDP中的媒體流排序(從最頂端計數)關系。為什么需要這樣的匹配關系呢?其實,這樣的匹配關系是非常必要的,answerer應答方決定新的SDP中某個媒體流可以對應前面SDP中的那個媒體流,然后可以綁定SDP媒體流的具體的匹配關系,否則,修改會話就會出現數據混亂。因為為了滿足以上的這些要求,我們看到,媒體流中的"m="行從來不會減少,“m=”行數保持不變或者增加。另外,從前面SDP中刪除的媒體流一定不能從新SDP中移除,不過,這些媒體的屬性不能出現在新的SDP中。
通過Offer/Answer 交互模式修改會話描述
新的媒體流可以通過添加一個新的媒體描述來實現,它可以添加到當前媒體描述的下面,也可以重新使用舊的媒體流的空間來重新激活新的媒體流。注意,這里,舊的媒體流通過端口設置為零以后已經被關閉。如果新的媒體流使用舊媒體流空間的話,新媒體描述需要替換掉舊的媒體描述,但是新媒體描述應該在SDP中和其他媒體描述位置不變。新媒體描述必須出現在已存在媒體描述的下面(這是一個格式規(guī)則)。當answerer應答方收到的SDP中所包含的媒體描述比offerer發(fā)起方發(fā)送的媒體描述多時,或者收到的SDP中包含媒體流,此媒體流占用的以前舊媒體流空間的話(端口為零),應答方就知道這里增加了一個新的媒體流。當然,新增加的媒體流也可以通過answer消息,在answer重構媒體描述接受或者拒絕這個新的媒體流。關于應答發(fā)生成answer的流程,讀者需要參考前面的章節(jié)。
除了在會話中增加媒體流以外,媒體流當然也可以被從會話中移除。如果要移除媒體流的話,需要創(chuàng)建一個新的SDP,在新的SDP中對需要移除的媒體流端口設置為零,這樣就移除了媒體流。媒體描述可以忽略以前出現的所有描述,僅保留單個媒體格式。所有在offer消息中出現被標識為關閉的媒體流(端口設置為零)也必須在anwer標識這些媒體流,并且關閉端口。反之,answer也必須針對offer做同樣的處理流程。在這種情況下,RTP和RTPC的傳輸流程也會停止退出,釋放任何和這些媒體關聯的資源,例如占用的電腦麥克風,攝像頭資源也會關閉。
除了增加媒體流,刪除媒體流以外,本章節(jié)開始時,筆者說過,幾乎所有的會話中的媒體流屬性參數都可以修改,F在,我們主要介紹一下修改地址,端口,傳輸方式,媒體格式,媒體類型,屬性,以及單播媒體等待狀態(tài)處理。
媒體的端口號是可以被修改的。筆者將討論offerer和answerer兩個方向的端口修改。如果要修改媒體的端口號,發(fā)起方offerer需要創(chuàng)建一個新的會話描述,在新會話描述中的“m=”行包含一個端口號,此端口號必須和前面相應媒體SDP中的會話描述中的端口號不同。如果僅修改端口號,那么其他的媒體描述應該保持不變狀態(tài)。因為offerer修改了端口以后,還沒有收到任何answer消息之前,所以,只要offerer發(fā)送了offer以后,offerer發(fā)起方必須準備接收舊端口發(fā)送過來的媒體和新端口發(fā)送過來的媒體。直到收到了answer消息,媒體流從新端口抵達,offerer發(fā)起方才能退出舊端口的偵聽。簡單來說,在使用新端口的媒體抵達之前,發(fā)起方不應該退出舊端口的偵聽,否則,可能出現傳輸的媒體丟失的問題。需要特別注意到是,這里存在一個新舊端口切換的過渡階段,可能一些應用場景中的已接收到媒體流。這里的已接收到媒體可能已經被存放在了一個系統(tǒng)的存儲節(jié)點上,如果有一個緩沖區(qū)的處理列表的話,接收方用戶終端會繼續(xù)偵聽舊端口來的這個媒體流,直到從新端口接收到的媒體流存放在優(yōu)先級最高的空間,這樣,接收方終端才會退出舊端口的媒體偵聽,真正開始偵聽新端口的媒體。
前面,筆者討論了offerer發(fā)起方的端口修改,現在開始討論answerer的端口修改。在answer中相應的媒體流可以和前面answerer發(fā)送的SDP中的媒體流相同也可能不同。如果應答發(fā)接受了一個已更新的媒體流,應答方應該使用新的端口馬上開始發(fā)送此更新的媒體流數據。如果應答方從前面的SDP的端口改變了發(fā)送端口,只要answer消息發(fā)送后,answerer應答方必須準備同時從新端口和舊端口接收媒體流數據。關于新端口和舊端口的偵聽退出和offerer的思路完全相同,筆者這里不再重復。以上我們討論的是answerer接受了offer的更新媒體。如果answerer應答方拒絕了offer的媒體流,offerer發(fā)起方收到拒絕消息后,offerer會停止前面準備接收媒體的端口。
改變媒體發(fā)送地址的處理方式和改變端口的處理方式相同,區(qū)別在于其連接屬性“c=”需要更新,端口沒有修改。媒體傳輸方式也可以修改,處理方式和端口的處理方式是相同的,傳輸方式修改,其端口不能修改。
除了會話中修改地址,端口和傳輸方式以外,會話管理的另外一個功能就是修改媒體格式。在會話中支持的媒體列表中的任何一個媒體格式都可以被修改。如果需要修改媒體格式的話,offer需要創(chuàng)建一個媒體描述,在這個新的媒體描述中,"m="行的媒體格式列表和此媒體流前面SDP中的不同。在新的會話描述中,此媒體列表可以增加新的媒體格式,也可以刪除出現在前面SDP中的媒體格式。具體到RTP的使用中,在此媒體流中,會話期間的這個匹配關聯關系一定不能被修改,具體來說,這個綁定關聯關系是從一個指定的動態(tài)payload類型匹配到一個指定的編碼,它們兩者之間綁定關系在此會話生命周期內是不能修改的。例如,如果Bob端生成了一個offer消息,此offer消息中標識了編碼格式G.711綁定到了一個動態(tài)的payload 類型號46,在此會話期間,在此媒體流中,無論是offer或者answer,這個46 payload 類型號碼一定是表示G.711編碼格式。但是,多個payload 類型號映射到同一編碼格式的這種情況也是可以接受的。因此,一個已更新的offer消息中可以使用其他payload 類型號碼來映射G.711編碼,例如,也可以在更新的offer中使用payload type是72來映射G.711編碼。
Asterisk-18中編碼協商處理流程示例
顯而易見,為了保證SDP信令交互和媒體流之間的同步,在一個會話期間,動態(tài)payload號類型和編碼的映射關系必須維持一個固定狀態(tài)。我們在前面的章節(jié)介紹過在answer中相應的媒體流構建,構建的過程也可能導致修改媒體格式。同樣的,只要應答方發(fā)送answer應答消息,answerer應答方必須開始使用某種媒體格式發(fā)送媒體流,這種媒體格式出現在answer消息中,也出現在了其offer消息中,answerer應該使用offer中優(yōu)先級最高的推薦媒體格式(此媒體格式也出現answer中的媒體格式)。即使某種媒體格式出現在前面的SDP中,如果此媒體格式沒有出現在offer中的話,answerer一定不能使用這種媒體格式。反之亦然,offerer發(fā)起方收到answer后,它發(fā)送媒體時必須使用answer中優(yōu)先級最高的媒體格式。即使某種媒體格式在前面的SDP中出現過,但是在本answer中沒有出現的話,offerer發(fā)起方一定不能使用此媒體格式。當終端agent停止使用某種媒體格式時(這種媒體格式不在offer或answer消息中),它仍然需要在將來一定時間內準備使用此媒體格式接收媒體。這里,agent仍然需要做一個狀態(tài)處理。它自己本身如何知道何時停止使用某種媒體格式接收媒體流呢?它需要一些必要的技巧來處理,使得agent變得“聰明”一點,它可以判斷對端是否停止使用舊媒體格式。第一種處理技巧,agent可以修改端口來修改媒體格式。當媒體抵達新端口后,agent知道對端peer已經停止使用舊媒體格式發(fā)送媒體流,agent也能停止使用此媒體格式接收媒體流。這種處理方式的好處是不依賴于媒體格式,但是,如果涉及了加密處理的話,修改端口要求原來預留的資源也要做出改變,原來安全加密的密鑰需要重新簽發(fā)。接下來,我們討論第二種處理技巧,當一個媒體格式被棄用時,agent使用一組全新的payload動態(tài)類型來映射所有的編碼。agent收到媒體時,它使用了新payload類型中的其中一種格式的話,agent知道對端已經停止使用就媒體格式發(fā)送媒體流。和第一種方式相比,這種方式不會影響預留資源和加密處理,但是需要增加額外的空間重新創(chuàng)建新payload 類型號。最后一種方式是使用定時器。當agent收到一個從對端peer發(fā)送過來的SDP,agent設置一個定時器。當定時器被觸發(fā)后,agent就停止使用舊的媒體格式來接收媒體流。定時器設置為一分鐘的超時設置是完全沒有問題的。在一些使用環(huán)境中,agent也可以不用考慮是否繼續(xù)使用舊媒體格式接收媒體流。因此,agent也無需過多干預。如果agent拒絕了offer的媒體流,對端也收到拒絕消息后也會停止準備使用任何新媒體格式發(fā)送媒體流。第三種方式相對比較適用于簡單的環(huán)境中,通過定時器超時來處理媒體格式的修改響應。
除了前面我們討論的一些媒體描述參數可以修改以外,媒體類型(語音,視頻,數據等)也可以進行修改。對流媒體來說,媒體類型也可以通過一定的處理方式來修改。一般的推薦方式是,如果傳輸的邏輯數據是一樣的,如果修改媒體類型的話,可以通過不同的媒體格式來實現。以前比較常見的示例是傳真部署中的場景,基于VBD(Voiceband Data)的傳真和模擬傳真信號的媒體類型修改。在當媒體流修改為不同的媒體類型。Voiceband Data和傳統(tǒng)傳真是分離的兩種類型,它們可以在路由器,網關和IPPBX之間進行類型修改支持傳真功能。如果需要修改媒體類型的話,offerer方使用一個新的媒體類型創(chuàng)建一個新的媒體描述,替代掉前面SDP中需要修改的媒體類型。在answer中相應的媒體流需要遵從筆者前面討論的answer消息中構建流程。假設媒體流被接受的話,只要answerer應答方收到了offer以后,它應該開始通過新的媒體類型和格式發(fā)送媒體流。收到answer消息后,發(fā)起方offerer必須準備使用舊媒體類型和新媒體類型接收媒體流,新媒體類型的媒體流抵達后,新類型媒體上升到播放緩沖區(qū)頂部,開始正式使用最新媒體類型。
修改會話中的特征屬性也需要通過offer/answer來修改。在媒體描述中其他的屬性也可以通過一個offer消息或answer消息來更新。一般情況下,如果agent收到了一個已修改參數的SDP,agent必須使用新的參數屬性發(fā)送媒體。
在以上所有的會話描述修改中,我們沒有涉及到一個非常普遍使用的應用場景。這個使用場景就是呼叫等待功能。筆者再花費一點時間來進一步和大家說明如何在呼叫等待狀態(tài)中處理單播媒體流。如果在呼叫中,一方(例如,A)把另外一方(例如,B)的呼叫執(zhí)行了電話駐留,讓另外一方處于呼叫等待狀態(tài)(需要暫時停止發(fā)送一個或者多個單廣播媒體流)。這時,呼叫方A會對另一方B發(fā)送一個offer消息,offer消息中包含了一個更新的SDP。如果前面被停靠的媒體是一個被標記為sendrecv的媒體流,現在,這個流媒體將會被替換成標記為sendonly的媒體流。
如果前面被?康拿襟w是一個被標記為recvonly的媒體流,現在,這個流媒體將會被替換成標記為inactive的媒體流。這樣的處理方式表示在每個方向?康暮艚械却襟w可以獨立分別標識。等待狀態(tài)的媒體流都是各自獨立的。在等待狀態(tài)的媒體的offer消息的接收方不應該自動返回一個針對此等待狀態(tài)的answer消息。一個對所有等待狀態(tài)的媒體的SDP看作是已接受的SDP(held SDP)。當answerer對已接受的SDP響應SDP時,某些第三方的呼叫控制方案中,已接受的SDP不能正常工作。比較典型的應用場景是,當終端agent摁 "Hold" 按鍵時,agent端將會在SDP中對所有的流媒體生成一個offer消息,此offer消息表示一個sendonly指向,并且agent自己也執(zhí)行本地靜音,agent也沒有對遠端發(fā)送媒體和播放媒體。還有很多的應用遵從RFC 2543(不再使用),從規(guī)范規(guī)定通過連接地址設置為0.0.0.0來駐留呼叫。這種規(guī)范方式其實已不再推薦為一種?糠绞剑⑶乙膊荒苤С諭Pv6,它不能支持RTCP對媒體流的報表監(jiān)控。但是這種處理方式在初始offer時會非常有用。在發(fā)起時間,當發(fā)起方offerer知道它想使用的具體的一組媒體流和它們的格式,但是此時還不知道接地址和端口,這種處理方式就滿足了初始offer的需求。Agent必須有一個支持能力來接收SDP,此SDP中的連接地址為0.0.0.0,關閉對RTP語音包數據或者RTCP報表數據的發(fā)送。關于呼叫等待的完整的流程介紹,讀者可以參考筆者歷史文檔:
最常用的18個SIP呼叫業(yè)務流程詳解-1-呼叫保持
8、指示能力討論
在agent發(fā)送offer之前,如果知道offer中的媒體格式可以被遠端answerer 應答方接受的話,那將對agent有很大的幫助。SIP協議具有查詢能力,可以對對端進行基本的能力查詢。在SIP響應中的SDP可以用來指示對端的媒體支持能力。讀者可以查閱RFC 3261-11獲得關于查詢能力的介紹。這里,我們討論如何實現類似SDP的構建?赡芤恍┳x者知道,其實,SDP沒有辦法指示此消息來說明為了實現能力指示的目的,SDP只能進行一些簡單的能力查詢。它真正的的能力指示是由更高級的協議層內容完成,SDP的基本能力指示的媒體承載能力是非常有限的。SDP本身不能表達允許參數值范圍,也不能通過offer/answer本身實現并行處理。SDP的這個局限性可能在未來的規(guī)范中得以支持。
使用一個結構化的SDP表示媒體能力支持,其創(chuàng)建過程是這樣的。當然,首先,此SDP必須是一個有效的SDP結構,另外,它可以忽略"e=" 和 "p=" 行(前面討論已提及)。“t=”必須等于“0 0”。agent所支持的每個媒體類型必須有相應的媒體類型的描述。在origin域中的會話ID是唯一的,唯一的會話ID用來支持每個已構建的SDP指示其媒體能力。端口必須設置為零,但是連接地址可以是隨意的。如果一個SDP解析為offer或answer消息的話,使用端口為零的設置手段可以保證一個已經構建好的SDP不會引起媒體流創(chuàng)建,因為此已格式化的SDP僅針對其支持能力,并且端口設置為零。"m="行表示傳輸的媒體類型。對于agent支持的媒體類型中的每個媒體格式來說,"m="行應該有一個媒體格式列表。在RTP使用方面,如果使用了動態(tài)payload類型的話,rtmp屬性必須出現在SDP中,它用來綁定媒體類型和具體的媒體格式。注意,在SDP中沒有辦法指示媒體限定,例如一種編碼可以支持的并發(fā)媒體流數量等。
9、交互示例和其他延伸討論
在前面的幾個章節(jié)包括現在我們正在討論的章節(jié)中,筆者完整介紹了基本的語法概要,offer/answer各自生成消息的流程,還介紹了如何對會話中的媒體描述進行管理。為了保證offer/answer交互模式規(guī)范的標準化,筆者在前面的所有章節(jié)中沒有涉及太多規(guī)范以外的內容。此部分的內容中,筆者結合幾個實例來具體說明offer/answer的交互示例,終端/網關產品中關于媒體協商的示例,還有關于早期offer和后期offer的區(qū)別等延伸討論。說明,因為篇幅有限,在示例中,我們僅列出一般正常的交互方式,不涉及非常特別的或具體每個特殊場景的環(huán)境和參數討論。
首先讀者可以了解一個最簡單的offer/answer交互模式的處理流程,示例中仍然是經典的Alice/Bob舉例。這里,假設Alice在offer中已經包含了以下的媒體描述,描述中一個雙向的語音媒體,兩個雙向的視頻媒體,其中視頻媒體使用了H.261(payload類型是31)和MPEG(payload類型是32)。這里,offer的SDP是這樣的:
v=0
o=alice 2890844526 2890844526 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 51372 RTP/AVP 31
a=rtpmap:31 H261/90000
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
Alice呼叫了Bob,但是,Bob不想接收或發(fā)送第一個視頻媒體流,因此Bob返回了一個answer消息:
v=0
o=bob 2890844730 2890844730 IN IP4 host.example.com
s=
c=IN IP4 host.example.com
t=0 0
m=audio 49920 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 31
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
在每個時間點,Bob想決定修改他的語音媒體流接收端口(從49920修改到65422),同時,他還要增加一個額外的媒體流,此媒體流標識為receive指向狀態(tài),使用的payload 類型支持event(例如DTMF,傳真等)。關于event的介紹,讀者可以參考RFC4734-2。Bob會生成這樣的offer消息返回到Alice:
v=0
o=bob 2890844730 2890844731 IN IP4 host.example.com
s=
c=IN IP4 host.example.com
t=0 0
m=audio 65422 RTP/AVP 0 // 修改了端口
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 31
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
m=audio 51434 RTP/AVP 110
a=rtpmap:110 telephone-events/8000
a=recvonly // 增加的指向
假設Alice接受了額外的媒體流支持請求,Alice生成以下answer:
v=0
o=alice 2890844526 2890844527 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 31
a=rtpmap:31 H261/90000
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
m=audio 53122 RTP/AVP 110
a=rtpmap:110 telephone-events/8000
a=sendonly
通過幾次交互以后,完成雙方會話管理。以上交互流程實際上是Alice對Bob呼叫時的一個會話修改的流程,具體的協商響應和回復需要參考筆者前面介紹的內容。
多選一”One of N Codec“是編碼協商中比較常見的場景,F在,很多物理SIP話機已經非常普及,SIP話機的DSP支持了多種編碼的壓縮。
資源來自于互聯網
有時,編碼一旦被選定以后,編碼不能輕易被修改。以下這個示例演示了通過初始化的offer/answer交互創(chuàng)建會話的流程,然后馬上通過第二個offer選擇編碼組鎖定需要的編碼。從Alice發(fā)送到Bob的初始offer中指示單媒體流可使用三種編碼,這三種編碼都是DSP中支持的編碼。因為Alice還沒有收到媒體流,編碼鎖定以后才能發(fā)送媒體流,因此,這里的媒體流標識為inactive狀態(tài):
v=0
o=alice 2890844526 2890844526 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 62986 RTP/AVP 0 4 18
a=rtpmap:0 PCMU/8000
a=rtpmap:4 G723/8000
a=rtpmap:18 G729/8000
a=inactive
Bob端可以支持動態(tài)切換編碼格式,可以從PCMU和G.723編碼。因此,Bob返回一個answer消息,包含的編碼如下:
v=0
o=bob 2890844730 2890844731 IN IP4 host.example.com
s=
c=IN IP4 host.example.com
t=0 0
m=audio 54344 RTP/AVP 0 4
a=rtpmap:0 PCMU/8000
a=rtpmap:4 G723/8000
a=inactive
Alice收到Bob的answer以后,從收到的兩種編碼中選擇了其中一種編碼G.723,通過一個更新的offer消息,并且標識其媒體流的媒體指向是sendrecv狀態(tài)。
v=0
o=alice 2890844526 2890844527 IN IP4 host.anywhere.com
s=
c=IN IP4 host.anywhere.com
t=0 0
m=audio 62986 RTP/AVP 4
a=rtpmap:4 G723/8000
a=sendrecv
Bob收到更新的offer以后,接受其編碼G.723, 發(fā)送answer給Alice。
v=0
o=bob 2890844730 2890844732 IN IP4 host.example.com
s=
c=IN IP4 host.example.com
t=0 0
m=audio 54344 RTP/AVP 4
a=rtpmap:4 G723/8000
a=sendrecv
如果Bob這里只能支持N選一(one-of-N codecs)的編碼方式的話,Bob將會從offer中提供的編碼中選擇其中一個可用編碼,然后把選擇的編碼通過answer發(fā)送到對端。這種情況下,Alice將會重新發(fā)起一個re-INVITE請求啟用此最后協商的編碼來傳輸媒體流。以上筆者介紹的是在第一次初始化offer中使用了"a=inactive"。對于在第一次交互中使用"a=inactive"指向的方式來說,另外一種處理方式是Alice可以列出所有的編碼,只要她從Bob收到媒體流以后,然后馬上生成一個更新的offer消息,在更新的offer中鎖定一種剛才從Bob收到的媒體格式,使用其鎖定的編碼格式來傳輸媒體流。當然,如果Bob這里只能支持N選一(one-of-N codecs)的編碼方式的話,他的answer中將會包含一種編碼格式,這種情況下,Alice也不需要發(fā)起一個re-INVITE請求鎖定編碼。當然,如果雙方的編碼協商不能成功的話,需要在B2BUA上進行編碼轉換的處理。關于編碼轉換的問題,筆者在歷史文檔中有深入的討論,這里不再重復。讀者可以參考:
編碼轉換處理
以上是一個關于帶物理DSP的SIP話機簡單編碼協商流程。除了SIP終端之間的協商以外,我們在生產環(huán)境中還會看到網關產品的編碼協商處理的使用場景,F在,我們通過一個語音網關的編碼協商的示例來說明編碼協商是如何進行的。再次說明,這里的示例僅是某個廠家的網關的簡單示例(多個“m=”行支持),可能和其他廠家的處理機制在細節(jié)上有所差別,但是原理基本上都是一致的(遵從RFC 3264規(guī)范)。示例中,網關通過offer/answer交互模式,通過第一個“m=”行和端口設置(m=0)接受了所需要的媒體格式,拒絕了不能支持的媒體。注意,這里的編碼優(yōu)先級不會影響offer中編碼的選擇,僅影響answer中編碼選擇方式。
圖例來自于互聯網
語音呼叫環(huán)境中,SIP INVITE進入到網關以后的offer和網關返回的answer消息對比:
Default Codec = G.711 ulaw
m=audio 38400 RTP/AVP 0 m=audio 49500 RTP/AVP 8 m=audio 6000 RTP/AVP 0 // 接受 m=audio 0 RTP/AVP 8 // 拒絕 |
offer中提供了兩種編碼的支持,但是網關發(fā)送到answer接受了payload type為0的媒體格式(在answer中是第一個編碼),拒絕了payload是8的媒體,設置其端口為0。
- 黃金法則:
- Early offer= SDP in INVITE而 Late offer= SDP in ACK
除了以上協商的策略以外,可能還有一個需要問題需要讀者要注意,那就是呼叫流程中“early offer”和“late offer”的問題,因為在B2BUA中涉及了編碼協商的機制和編碼轉換的問題,它們會影響到編碼協商的最終結果。最早的SIP應用場景中很多是使用early offer模式,但是隨著網絡架構和網絡環(huán)境越來越復雜,更多的性能優(yōu)化需要調整編碼能力或者帶寬/QoS等業(yè)務要求,所以,在SIP網絡中使用later offer的場景也逐漸多了。一些讀者可能沒有注意這兩個概念的不同或比較迷惑這兩個概念。首先,討論簡單說明一下什么是“early offer”和“late/delayed offer”。其實,這兩個概念也沒有太難理解的地方,顧名思義,early offer就是在INVITE請求中包含SDP消息,later offer就是在后續(xù)的ACK中包含SDP消息。例如,如果一個UAC發(fā)起一個INVITE請求,并且在INVITE(offer消息)做包括了SDP消息,SDP消息中指示了UAC所支持的媒體格式,例如通常使用的G.711和G.723等編碼。請求的接收方收到SDP消息后解析編碼,然后根據所支持的編碼決定接收方UAS使用何種編碼來進行媒體傳輸。注意,UAC(被呼叫方)首先看到的是UAS(呼叫方)在SDP中的編碼。這種情況下,相當于UAC已經把可以選擇的編碼提供給了被呼叫方,被呼叫方沒有什么選擇的余地,它只能根據UAS提供的編碼進行選擇。所以,其實在early offer中,UAS具有更多的自主權,而UAC只能從編碼中被動選擇需要的編碼。當然,其優(yōu)點是UAS降低了編碼編碼處理的的復雜度。
early offer 示例(INVITE包含SDP)
前面筆者討論了early offer,呼叫方首先提供了一種選擇權讓對方來選擇。和early offer相反的是later offer。從字面意思也可以看到,early或later僅是一個offer SDP的時間問題。Later offer更多的offer消息的選擇權則是由被呼叫方晚一點提供。呼叫方在INVITE呼叫請求發(fā)送時,沒有包含SDP消息,同時雙方也進行正常的INVITE流程處理,被呼叫方返回一個臨時響應,例如,發(fā)送 180振鈴(但是,被呼叫方此時還沒有準備好或意識到使用何種編碼)或者183(帶SDP,下面討論此問題),緊接著發(fā)送 200 ok(帶SDP消息,這時開始發(fā)送offer消息/later offer)。呼叫方收到 200 ok 以后,結合其offer中的SDP消息,然后返回ACK(包含SDP消息體)。實際上,呼叫方最終決定使用何種編碼。
later offer(ACK中包含)
在later offer中的場景中,有兩個比較重要的問題可能會影響呼叫。有時,發(fā)送了200 ok最終響應的設備會馬上發(fā)送媒體流,此時對端可能還沒有收到 200 ok(包括SDP),它們之間的會話也根本沒有創(chuàng)建,因此可能出現語音丟失的問題,語音丟失的長度可能完全取決于雙方最后協商的時間。所以,有時我們經常遇到,通話開始的前幾秒可能雙方都聽不到對方的聲音,或者播放IVR時,IVR語音的前幾秒語音丟失。另外一個問題就是在被呼叫方發(fā)送臨時響應時,它沒有發(fā)送180 振鈴,但是有時發(fā)送的是183(帶SDP),這樣的臨時響應攜帶了媒體。因為此時此刻,沒有協商流程還沒有完成也沒有協商成功,呼叫方的媒體端口或者地址還沒有開啟,因此,SDP中攜帶的媒體流可能就會在中途丟失,例如,聽不到回鈴音,彩鈴或者其他的語音業(yè)務播放的媒體。這些問題可能需要經過一些B2BUA的處理(在Asterisk或者FreeSWITCH都針對兩種offer有相關的具體配置。),有時需要PRACK的支持,在媒體服務器端針對性地進行設置(增加progress 處理,等待,或者answer處理等)或者在其呼叫路徑中增加一個SBC來處理later offer帶來的這些問題。
參考資料:
https://tools.ietf.org/id/draft-ietf-mmusic-ice-sip-sdp-14.html
https://tools.ietf.org/html/draft-ietf-rmcat-cc-codec-interactions-00
https://www.swisscom.ch/content/dam/swisscom/en/about/company/network/all-ip/documents
https://freeswitch.org/confluence/display/FREESWITCH/Codec+Negotiation
https://lists.cs.columbia.edu/pipermail/sip-implementors/2018-December/031167.html
在接下來的章節(jié)中,筆者將繼續(xù)討論SDP offer/answer交互模式中NAT處理以及ICE。
關注微信公眾號:asterisk-cn,獲得有價值的Asterisk行業(yè)分享
Asterisk freepbx FreeSBC技術文檔: www.freepbx.org.cn
融合通信/IPPBX商業(yè)解決方案:www.hiastar.com
如何使用FreeSBC,qq技術分享群:334023047, www.freesbc.cn