本文將按照RFC3261逐步的介紹SIP協(xié)議,介紹了c和c++語(yǔ)言的實(shí)現,分析了osip庫的使用和實(shí)現。
第一章 概述
一 概述
SIP協(xié)議是一個(gè)基于應用層的會(huì )話(huà)控制協(xié)議。它可以創(chuàng )建、修改、終止多媒體會(huì )話(huà)(會(huì )議),也可以邀請參與者加入到一個(gè)現有的會(huì )話(huà)。
因為SIP是一個(gè)基于應用層的協(xié)議,所以它不是一套完整的通訊系統方案,它需要和其它的方案或者協(xié)議結合起來(lái)實(shí)現整套系統。例如,實(shí)時(shí)傳輸協(xié)議(RTP)(RFC1889)用來(lái)傳輸音視頻等實(shí)時(shí)的流媒體數據。實(shí)時(shí)流協(xié)議(RTSP)(RFC2326)用來(lái)控制媒體流的傳遞。媒體網(wǎng)關(guān)控制協(xié)議(MEGACO)(RFC3015)用來(lái)控制PSTN網(wǎng)關(guān)。
由此可見(jiàn),SIP協(xié)議應該用來(lái)組合其它協(xié)議,從而實(shí)現完整的服務(wù)。但是,SIP基礎的功能和操作不依賴(lài)于其它協(xié)議。
二 第一個(gè)例子
圖1
下面引用RFC3261的例子來(lái)說(shuō)明sip的基本功能,包括:定位終端,發(fā)送通訊請求,協(xié)商會(huì )話(huà)參數,建立會(huì )話(huà)和撤銷(xiāo)建立的會(huì )話(huà)。圖1顯示了用戶(hù)Alice和Bob使用SIP交換信息的一個(gè)典型的例子(每一個(gè)消息用字母F和一個(gè)數字來(lái)標號,標號的前面有一個(gè)簡(jiǎn)短的消息類(lèi)型說(shuō)明)。在這個(gè)例子中,Alice使用一個(gè)在她的PC機中的SIP應用程序呼叫Bob,Bob使用他的SIP電話(huà),這個(gè)SIP電話(huà)登錄了互聯(lián)網(wǎng)。同時(shí),請注意兩個(gè)SIP代理服務(wù)器在A(yíng)lice和Bob的會(huì )話(huà)的建立中起到的作用。
Alice呼叫Bob是使用他的SIP標識符。SIP標識符是一種URI(Uniform Resource Identifier),稱(chēng)之為SIP URI。SIP URI格式很象email地址,包含一個(gè)用戶(hù)名和一個(gè)主機名,如:sip:bob@biloxi.com。這里biloxi.com是Bob的SIP服務(wù)提供者的域名。Alice的SIP URI是:sip:alice@atlanta.com。SIP也支持安全URI,叫做SIPS URI,例如,sips:bob@biloxi.com。一個(gè)向SIPS URI的呼叫使用加密傳輸(也就是TLS)來(lái)攜帶從呼叫者到被呼叫者所有的SIP消息。
SIP是一個(gè)與HTTP協(xié)議很像的,請求/應答式的事務(wù)模型。每一個(gè)事務(wù)最少由一個(gè)要完成特定方法或功能的請求,和服務(wù)器端的一個(gè)應答組成。在這個(gè)例子中,這個(gè)事務(wù)從Alice的軟電話(huà)發(fā)送一個(gè)INVITE請求到Bob的SIP URI開(kāi)始。INVITE是一個(gè)SIP消息,它表示請求者Alice想與Bob通話(huà)。INVITE請求包含一些頭域。頭域被稱(chēng)為屬性,可以提供關(guān)于這個(gè)消息的額外信息。關(guān)于頭域我們一會(huì )兒將會(huì )詳細說(shuō)明它們。圖1中的INVITE信息(F1)可能像這樣:
INVITE sip:bob@biloxi.com SIP/2.0Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhdsMax-Forwards: 70To: Bob <sip:bob@biloxi.com>From: Alice <sip:alice@atlanta.com>;tag=1928301774Call-ID:
a84b4c76e66710@pc33.atlanta.comCSeq: 314159 INVITEContact: <sip:alice@pc33.atlanta.com>Content-Type: application/sdpContent-Length: 142 (Alice's SDP not shown)
第一行文本是這個(gè)請求的方法名(INVITE)。后面的行是多個(gè)頭域。這里只列出了最少需要的頭域。先在這里對這些頭域做一個(gè)簡(jiǎn)要的介紹:
Via頭域包含Alice希望收到對于這個(gè)請求的應答的地址。也就是她告訴請求的接收者,應答應該發(fā)送到 pc33.atlanta.com。后面的branch參數是這個(gè)事務(wù)的標識符。
To頭域包含一個(gè)顯示名(Bob)和一個(gè)SIP URI或者SIPS URI,這里是使用的SIP URI(sip:bob@biloxi.com)。這個(gè)SIP URI就是這個(gè)請求要發(fā)送的目標。
From頭域也包含一個(gè)顯示名(Alice)和一個(gè)SIP URI或者SIPS URI,這里是使用的SIP URI(sip:alice@atlanta.com)來(lái)指出請求的發(fā)起人。這個(gè)頭域還包含了一個(gè)tag參數,這個(gè)參數包含了一個(gè)隨機字符串(1928301774),這個(gè)字符串的數字會(huì )被軟電話(huà)自動(dòng)增加,它主要起到鑒別的作用,后面還會(huì )說(shuō)明它。
Call-ID頭域包含一個(gè)全局唯一標識符來(lái)標識這次呼叫。這個(gè)標識符使用一個(gè)隨即字符串和軟電話(huà)所在的主機名(或者IP地址)一起生成。這樣,To頭域、From頭域和Call-ID這三個(gè)頭域就可以唯一的確定了Alice和Bob的這條點(diǎn)對點(diǎn)的通信關(guān)系,并且將這個(gè)通信關(guān)系交給一個(gè)對話(huà)(dialog)來(lái)處理了。
Cseq頭域(命令序列)包含一個(gè)整數和一個(gè)方法名字。在這個(gè)對話(huà)中每一個(gè)新的請求都會(huì )增加這個(gè)整數的值,保證這個(gè)數值是有序的。
Contact頭域包含一個(gè)SIP URI或者SIPS URI指出一個(gè)能夠接觸到Alice的直接路由,一般這個(gè)SIP URI由用戶(hù)名和一個(gè)完全限定域名(FQDN)構成。因為許多終端系統沒(méi)有注冊域名,所以也可以使用IP地址代替FQDN。Via頭域向對方指出了這個(gè)請求的應答應該發(fā)送到哪里,而Contact頭域向對方指出了將來(lái)的請求應該發(fā)送到哪里。
Max-Forwards頭域限制了在這個(gè)請求傳送到目的地的時(shí)候最多可以有多少跳。它包含一個(gè)整數,在每一跳這個(gè)整數都會(huì )被減少。
Content-Type頭域描述消息體的類(lèi)型(在這個(gè)例子里消息體采用了SDP描述,但是消息體內容沒(méi)有給出)。
Content-Length頭域指出了消息體的字節數。
在后面我們將完整的介紹SIP頭域(RFC3261第20節)。
在會(huì )話(huà)中像媒體類(lèi)型、編碼方式、采樣率等信息都不使用SIP描述,而是在消息體中使用其它會(huì )話(huà)描述協(xié)議的格式。這個(gè)例子中采用了SDP描述(RFC2327)。
軟電話(huà)不知道Bob或者擁有biloxi.com域名的SIP服務(wù)器,它將INVITE請求發(fā)送給為Alice提供服務(wù)的域名為atlanta.com的SIP服務(wù)器。關(guān)于A(yíng)lice如何獲得atlanta.com SIP服務(wù)器的地址,可以使用由Alice的軟電話(huà)指定,或者使用DHCP探測到等方式。
atlanta.com SIP服務(wù)器是一個(gè)SIP代理服務(wù)器。一個(gè)代理服務(wù)器接收SIP請求,為請求的發(fā)送者轉發(fā)請求。在這個(gè)例子中,代理服務(wù)器接收到INVITE請求后發(fā)送一個(gè)100應答(Trying)給Alice的軟電話(huà)。100應答(Trying)指出這個(gè)INVITE請求已經(jīng)被代理服務(wù)器接收到,并且已被經(jīng)進(jìn)一步向目的地路由。SIP中的應答使用3位數字表示,每一個(gè)編號都表示一個(gè)描述短語(yǔ)。這個(gè)100應答(Trying)也同樣包含和INVITE請求一樣的To、From、Call-ID、CSeq和Via以及branch參數,這樣可以使Alice的軟電話(huà)知道這個(gè)應答是對應發(fā)送的INVITE請求的。atlanta.com代理服務(wù)器定位出biloxi.com代理服務(wù)器(這可能需要通過(guò)域名解析服務(wù)器(DNS)等實(shí)現,后面還會(huì )詳細講解)獲得了它的IP地址,并且準備把INVITE請求轉發(fā)給biloxi.com代理服務(wù)器。在轉發(fā)請求之前,atlanta.com代理服務(wù)器增加了一個(gè)額外的Via頭域,這個(gè)Via頭域包含自己的地址(這時(shí)候這個(gè)INVITE請求的第一個(gè)Via頭域包含Alice的軟電話(huà)的地址)。biloxi.com代理服務(wù)器接收到這個(gè)INVITE請求,并且也發(fā)送一個(gè)100(Trying)應答給atlanta.com代理服務(wù)器指出它已經(jīng)接收到這個(gè)INVITE請求,并正在處理這個(gè)請求。biloxi.com代理服務(wù)器知道Bob的IP地址(這可能需要定位服務(wù)),它又在這個(gè)INVITE請求中加入了一個(gè)新的Via頭域,值為自己的地址,然后它把這個(gè)INVITE請求發(fā)送給Bob的SIP電話(huà)。
Bob的SIP電話(huà)接收到這個(gè)INVITE請求,發(fā)送一個(gè)180(Ringing)應答,同時(shí)使用鈴聲通知Bob有一個(gè)來(lái)自Alice的呼叫,讓Bob決定是否接聽(tīng)。這個(gè)180(Ringing)應答反向經(jīng)過(guò)這兩個(gè)代理服務(wù)器被發(fā)送到Alice。每一個(gè)代理服務(wù)器使用Via頭域決定向哪里發(fā)送這個(gè)應答,并且把移除它自己添加的Via頭域。這樣,雖然只有初始的INVITE請求發(fā)送的時(shí)候使用了DNS服務(wù)和定位服務(wù),而這個(gè)180(Ringing)應答沒(méi)有使用,同時(shí)代理服務(wù)器也不需要記錄整個(gè)通訊的狀態(tài),但是這個(gè)應答還是能夠成功的發(fā)送給請求的發(fā)送者Alice。
當alice的軟電話(huà)接收到180(Ringing)應答后,它將這個(gè)消息告訴給Alice,也許使用一個(gè)聲音(彩鈴)或者在A(yíng)lice的屏幕上顯示一個(gè)消息。
在這個(gè)例子中,Bob決定接聽(tīng)電話(huà),當他按下接聽(tīng)按鈕時(shí),他的SIP電話(huà)發(fā)送200(OK)應答表示接受了這個(gè)呼叫。這個(gè)200(OK)應答包含一個(gè)消息體,消息體使用SDP描述Bob準備和Alice建立的會(huì )話(huà)的媒體類(lèi)型等信息。這樣,Alice和Bob交換了一次SIP信息:Alice用INVITE請求發(fā)送一次給Bob,Bob用200(OK)應答發(fā)送一次給Alice。這個(gè)交換實(shí)現了基本的協(xié)商能力和簡(jiǎn)單的offer/answer模型。如果Bob不希望接聽(tīng)電話(huà),或者他現在正忙(接聽(tīng)其它電話(huà)),那么他會(huì )發(fā)送一個(gè)錯誤應答而不是200(OK)應答。一個(gè)錯誤應答將不會(huì )建立會(huì )話(huà)。