SIP路由
本文主要討論的是跟SIP消息發送的路由選擇和相關頭域。SIP消息傳輸路徑依靠的是路由集和目標地址(remotetargetURI)。主要參考的是RFC中的第八章(一般用戶代理行為)、第十二章(對話)、第十三四章(會話)、十六章(Proxy行為)。
?
重要概念
Route Set: 路由集。路由集合是一個順序的SIP或者SIPSURI。這些URI描述了傳遞一個請求所必須經歷的代理列表。一個路由集可以是自適應的,因為包頭中包含了Record-Route(記錄路由),也可以是依賴配置得到的。(不包括目標地址)
?
相關頭域說明
Request-URI:目標用戶或者服務的地址。
Via:Via頭域是用來描述請求當前經歷的路徑的,并且標志了應答所應當經過的路徑。Via頭域的branchID參數提供了事務的標志,并且用于proxy來檢查循環路由。只有當需要通過選擇傳輸設備到達下一個節點(hop)的時候,才需要在頭域中包含Via域。
Contact:Contact頭域提供了一個URI,指明了請求的資源或請求發起者,這個URI的含義取決于是在請求還是在應答中。
Record-Route:Record-Route頭域是proxy在請求中增加的,用來強制會話中的后續請求經過本proxy的。
Route:Route頭域用于強制一個請求經過一個proxy路由列表。
?
嚴格路由和松路由處理
1 嚴格路由:Route頭域中的值中包含lr參數部分為嚴格路由。
如果Route頭域的第一個值為嚴格路由,那么UA或Proxy必須根據下列步驟修改這個請求:
- 必須把Request-URI放在Route頭域中的最后一個值。
-必須把第一個Route頭域的值放在Request-URI中,并且從Route頭域中刪去。
2 松路由:Route頭域中的值中不包含lr參數部分為松路由。
如果Route頭域的第一個值為松路由,那么UA或Proxy必須根據下列步驟修改這個請求:
- 如果跟自身URI相符,則把第一個Route頭域的值刪掉。
?
一般UA行為
1UAC
1.1 發起請求時:(對話之外)
Request-URI(必選):最開始的Request-URI頭域應該是TO頭域的的值。在一些特定的情況下,預先設置的路由集(route-set)會影響消息中的Request-URI:如果預設路由集的第一項是嚴格路由,則Request-URI值被修改為路由集的第一個值。
Via(必選):當UAC創建一個請求,它必須在頭域中添加一個Via域。
Contact(必選):Contact頭域提供了訪問后續請求的特定UA實例的聯系方法。
Route(可選):預先設置路由集。
此時路由集為預先設置的路由集。
1.2發起請求時:(對話之內)
此時路由集為應答的路由集。
Route:由應答重構的路由集,即對話的路由集,如果是Route由Record-Route創建的,請求中必須包含該頭域。
Contact:對話的遠端地址。
在對話中的請求可以包含Record-Route和Contact頭域。不過,雖然他們會修改remotetarget的URI,但是這些請求也不會導致對話的路由集被改變。
需要注意的是,雖然UAC會嘗試新的地址(處理3xx應答的時候),但是它依舊使用對話內的路由集合來構造請求的Route頭域。
1.3處理應答
remote targetURI必須設置成為應答中的Contact頭域的URI。當UAC收到一個刷新target請求的2xx應答的時候,如果對話的remotetargetURI存在,那么它必須用這個應答的Contact頭域的值來替換對話的remotetarget URI,并以此值修改對話的目標地址。
如果應答中含有Record-Route頭域,則將該頭域的順序重頭到尾顛倒,但內容不變,此時得到的結果為新的路由集,并以此值修改對話的路由集;如果在應答中沒有Record-Route頭域,那么這個路由集必須設置成為空集合。這個路由集合即便是空的,為了以后的對話中的請求,也要覆蓋任何預先存在(pre-existing)的路由集合。
此時路由集為對話的路由集。
?
可見路由集是在對話建立中完成,在該對話中該路由集不變,而對話的目標地址屬性卻是可修改的。
?
2 UAS
當UAS接收到一個target刷新請求的時候,如果請求中存在Contact頭域,它必須用Contact頭域中的URI來替換對話的remotetarget URI。
UAS必須拷貝所有的請求中的Record-Route頭域到應答中去(包括URI,URI參數,和其他任何Record-Route頭域的參數,無論UAS是不是認識的參數都需要原樣拷貝),并且必須維持這些參數的順序。并按照此方法構建對話的路由集。
UAS必須增加一個Contact頭域給應答。這個Contact頭域包含一個UAS在后續對話請求中接收請求的地址(這個包含了給INVITE請求的2xx應答的ACK請求處理的地址)。
請求中的Via頭域原封不動的移到應答中。
?
UAS存儲路由集和遠端目的地址是為了在對話中發起新的請求時選擇路徑用。
?
Proxy行為
1請求消息
必須按照以下步驟:
1.1 路由信息預處理
根據前面嚴格路由的做法,proxy必須檢查請求中的Request-URI部分。如果Request-URI包含了一個本proxy早先放在Record-Route頭域中的值(參見16.6,4),
proxy必須用Route頭域中的最后一個值來替換Request-URI,并且從Route頭域中刪去這個值。
如果Route頭域的第一個值就是這個proxy,那么proxy必須從請求中把它移去。
1.2 確定請求的目的
如果Request-URI的區域并非本proxy負責的區域,那么Request-URI必須放在目標集合中,并且作為唯一一個目標URI。
如果請求的目標集合沒有像上邊講述的這樣預先設定,那么這就意味著proxy是負責Request-URI所指明的區域的,并且proxy可以用任何機制來決定往哪里發送這個請求。
通過這些機制,我們可以有一個可能的目的地列表,他們的URI被增加到目的地集合。
1.3 請求轉發
當目的地集合不是空的時候,proxy可以開始轉發這個請求。有狀態的proxy可以按照任意的順序處理這個目的地集合。
在拷貝好的請求中的Request-URI必須用目的地的URI進行替換。
如果希望保留這個請求創建的對話中,后續的請求依舊是要經過本proxy,那么本proxy必須增加一個Record-Route頭域值在這個拷貝中,并且增加的這個頭域值應當是在其他現存的Record-Route頭域之前。
如果這個請求已經是一個對話的一部分,proxy如果希望以后這個對話的請求依舊經過本proxy,那么proxy應當增加一個Record-Route頭域值。以上可知,普通的終端操作中,這些Record-Route頭域值不會對終端使用的路由集合造成任何影響。
proxy必須在請求的拷貝中增加一個Via頭域值,并且在其他Via頭域值之前增加。
2應答消息
proxy從應答中移去Via頭域中最上的值。如果在這個應答中沒有這個Via頭域值,那么應答的含義就是說這個應答不應當被這個proxy轉發。
?
如何選擇發送消息的下一節地址
請求消息
消息發送的地址為第一個Route頭域(如果存在),或者在請求的Request-URI(如果Route頭域不存在)。
在建立對話的請求中,如果請求沒有包含Route頭域,那么就沒有對額外的目的地有什么其他的限制了。這個就提供了一個簡單的外發(outbound)proxy的事前路由的選擇。但是,用這樣的方法配置一個外發proxy是不推薦的;應該由單個UPI規定的預先設定的路由集來指定外發proxy。如果請求包含了Route頭域,請求應該發送到Route頭域最上邊的一個位置,但是請求也可能被發給由RFC3261約定的Route或者Request-URI所指定的服務器(同RFC2543定義的相反)。特別的,一個配置了外發proxy的UAC應該首先嘗試把請求發送給由第一個Route頭域值指定的位置,而不是采用把所有消息都發給外發proxy的策略。這就保證了外發的proxy通過不增加Record-Route頭域而不參與后續請求的路徑。這個也允許讓不能分析第一個RouteURI的終端,把請求交給外發proxy來發送。
應答消息
消息發送的地址為請求消息的第一個Via的URI。
?
參考
RFC3261
?
存在的問題因為當前實現方案中,Request-URI和Route都作為當前路由選擇的因素,而為了向后兼容RFC2543,嚴格路由在路由過程中修改Request-URI,導致了路由選擇的混亂。雖然現在使用了松動的路由選擇方式可以解決這個問題(嚴格區分Request-URI和Route的作用域,前者為目標地址,而Route為到達目標要經過的代理列表,后者不應影響前者),但該方式只存在于對話內的請求,而該修
總結
- 上一篇: 普通用户现在能升级iOS 16吗?博主上
- 下一篇: 爷青回!《孤胆枪手2:新纪元》新作6月发