1. 程式人生 > >《FreeSWITCH: VoIP實戰》:SIP 模組

《FreeSWITCH: VoIP實戰》:SIP 模組

SIP 模組是 FreeSWITCH 的主要模組,所以,值得拿出專門一章來講解。   在前幾章時裡,你肯定見過幾次 sofia 這個詞,只是或許還不知道是什麼意思。是這樣的,Sofia-SIP 是由諾基亞公司開發的 SIP 協議棧,它以開源的許可證 LGPL 釋出,為了避免重複發明輪子,FreeSWITCH 便直接使用了它。   在 FreeSWITCH 中,實現一些互聯協議介面的模組稱為 Endpoint。FreeSWITH 支援很多的 Endpoint, 如 SIP、H232等。那麼實現 SIP 的模組為什麼不支援叫 mod_sip呢?這是由於 FreeSWITCH 的 Endpoint 是一個抽象的概念,你可以用任何的技術來實現。實際上 mod_sofia 只是對 Sofia-SIP 庫的一個粘合和封裝。除 Sofia-SIP 外,還有很多開源的 SIP 協議棧,如 pjsip、osip 等。最初選型的時候,FreeSWITCH 的開發團隊也對比過許多不同的 SIP 協議棧,最終選用了 Sofia-SIP。FreeSWITCH 是一個高度模組化的結構,如果你不喜歡,可以自己實現 mod_pjsip 或 mod_osip 等,它們是互不影響的。這也正是 FreeSWITCH 架構設計的精巧之處。   Sofia-SIP 遵循 RFC3261 標準,因而 FreeSWITCH 也是。   配置檔案   Sofia 的配置檔案是 conf/autoload_configs/sofia.conf.xml,不過,你一般不用直接修改它,因為它實際上直接使用一條預處理指令裝入了 conf/sip_profiles/ 目錄中的 XML 檔案:   所以,從現在起,可以認為所有的 Sofia 配置檔案都在 conf/sip_profiles/ 中。   Sofia 支援多個 profile,而一個 profile 相當於一個 SIP UA,在啟動後它會監聽一個 “IP地址:埠” 對。讀到這裡細心的讀者或許會發現我們前面的一個錯誤。我們在講 B2BUA 的概念時,實際上只用到了一個 profile,也就是一個 UA,但我們還是說 FreeSWITCH 啟動了兩個 UA(一對背靠背的 UA)來為 alice 和 bob 服務。是的,從物理上來講,它確實只是一個 UA,但由於它同時支援多個 Session,在邏輯上就是相當於兩個 UA,為了不使用讀者太糾結於這種概念問題中,我在前面沒有太多的分析。但到了本章,你應該非常清楚 UA 的含義了。   FreeSWITCH 預設的配置帶了三個 profile(也就是三個 UA),在這裡,我們不討論 IPv6,因此只剩下 internal 和 external 兩個。 internal 和 external 的區別就是一個執行在 5060 埠上,另一個是在 5080 埠上。當然,還有其它區別,我們慢慢講。 internal.xml internel.xml 定義了一個 profile,在本節,我們以系統預設的配置逐行來解釋: profile 的名字就叫 internal,這個名字本身並沒有特殊的意義,也不需要與檔名相同,你可以改成任何你喜歡的名字,只是需要記住它,因為很多地方要使用這個名字。 如果你喜歡,可以為該 profile 起一個別名。注意預設是加了註釋的,也就是說不起作用。再說一遍,“”在 XML 中的含義是註釋。 即然 profile 是一個 UA,它就可以註冊到別的 SIP 伺服器上去,它要註冊的 SIP 伺服器就稱為 Gateway。我們一般不在 internal 這個 profile 上使用 Gateway,這個留到 external 時再講。 定義該 profile 所屬的 domain。它可以是 IP 地址,或一個 DNS 域名。需要注意,直接在 hosts 檔案中設定的 IP-域名可能不好用。 settings 部分設定 profile 的引數。   如果 FreeSWITCH 是沒有媒體(no media)的,那麼如果設定了該引數,當你在話機上按下 hold 鍵時,FreeSWITCH 將會回到有媒體的狀態。   那麼什麼叫有媒體無媒體呢?如下圖,bob 和 alice 通過 FreeSWITCH 使用 SIP 接通了電話,他們談話的語音(或視訊)資料要通過 RTP 包傳送的。RTP 可以 像 SIP 一樣經過 FreeSWITCH 轉發,但是,RTP 佔用很大的頻寬,如果 FreeSWITCH 不需要“偷聽”他們談話的話,為了節省頻寬,完全可以讓 RTP 直接在兩者間傳送,這種情況對 FreeSWITCH 來講就是沒有 media 的,在 FreeSWITCH 中也稱 bypass media(繞過媒體)。 FreeSWITCH SIP / \ SIP / \ bob ------RTP------ alice Attended Transfer 稱為出席轉移,它需要 media 才能完成工作。但如果在執行 att-xfer 之前沒有媒體,該引數能讓 att-xfer 執行時有 media,轉移結束後再回到 bypass media 狀態。 不用解釋,就是設定 SIP 訊息中顯示的 User-Agent 欄位。 debug 級別。 由於各種原因(如埠被佔用,IP地址錯誤等),都可能造成 UA 在初始化時失敗,該引數在失敗時會停止 FreeSWITCH。 是否開啟 SIP 訊息跟蹤。另外,也可以在控制檯上用以下命令開啟和關閉 sip-trace: sofia profile internal siptrace on sofia profile internal siptrace off 是否將認證錯誤寫入日誌。 context 是 dialplan 中的環境。在此指定來話要落到 dialplan 的哪個 context 環境中。需要指出,如果使用者註冊到該 profile 上(或是經過認證的使用者,即本地使用者),則使用者目錄(directory)中設定的 contex 優先順序要比這裡高。 設定 SDP 中 RFC2833 的值。RFC2833 是傳遞 DTMF 的標準。 監聽的 SIP 埠號,變數 internal_sip_port 在 vars.xml 中定義,預設是 5060。 設定對應預設的 dialplan。我們後面會專門講 dialplan。 設定 DTMF 的時長。 支援的來話語音編碼,用於語音編碼協商。global_codec_prefs 是在 vars.xml中定義的。 支援的去話語音編碼。 RTP 時鐘名稱 RTP 的 IP 地址,僅支援 IP 地址而不支援域名。雖然 RTP 標準說應該域名,但實際情況是域名解析有時不可靠。 SIP 的 IP。不支援域名。 UA 進行 hold 狀態時預設播放的音樂。 使用哪個 NAT ACL。 擴充套件 INFO 解析支援。 NAT穿越,檢測 SIP 訊息中的 IP 地址與實際的 IP 地址是否相符,詳見 NAT穿越。 該功能暫時還不推薦使用。 支援壓縮 SIP 頭。 開啟、關閉 SIP 時鐘。 SIP 會話超時值,在 SIP 訊息中設定 Min-SE。 對來話採用哪個 ACL。詳見 ACL。 預設情況下,FreeSWITCH 會自動檢測本地網路,並建立一條 localnet.auto ACL 規則。 對註冊請求採用哪個 ACL。 DTMF 收號的型別。有三種方式,info、inband、rfc2833。   info 方式是採用 SIP 的 INFO 訊息傳送 DTMF 按鍵資訊的,由於 SIP 和 RTP 是分開走的,所以,可能會造成不同步。   inband 是在 RTP 包中象普通語音資料那樣進行帶內傳送,由於需要對所有包進行鑑別和提取,需要佔用更多的資源。   rfc2833 也是在帶內傳送,但它的 RTP 包有特殊的標記,因而比 inband 方式節省資源。它是在 RFC2833 中定義的。 如何傳送請求訊息。true 是每次都發送,而 first-only 只是首次註冊時傳送。 設定來電顯示的型別,rpid 將會在 SIP 訊息中設定 Remote-Party-ID,而 pid 則會設定 P-*-Identity,如果不需要這些,可以設定成 none。 錄音檔案的預設存放路徑。 錄音檔名模板。 是否支援列席。 是否支援 SLA - Shared Line Apperance。 這兩個引數用以在多個 profile 間共享列席資訊。 最大的開放對話(SIP Dialog)數。 會話超時時間。 是否支援多點註冊,可以是 contact 或 true。開啟多點註冊後多個 UA 可以註冊上來,有人呼叫這些 UA 時所有 UA 都會振鈴。 SDP 中的語音編協商,如果設成 greedy,則自己提供的語音編碼列表會有優先權. 為了 NAT 穿越或 keep alive,如果 FreeSWITCH 向其它網關注冊時,可以週期性地發一些 OPTIONS 包,相當於 ping 功能。該引數說明當 ping 失敗時是否自動取消註冊。 是否支援 TLS,預設否。 下面都是與 TLS 有關的引數,略。 該選項預設為 true。即在橋接電話是是否自動 flush 媒體資料(如果套接字上已有資料時,它會忽略定時器睡眠,能有效減少延遲)。 是否透傳 RTP 時間戳。 是否透傳 RFC2833 DTMF 包。 使用 ODBC 資料庫代替預設的 SQLite。 將所有來電設定為媒體繞過。 將所有來電設定為媒體透傳。 對所有來電來講,晚協商有助於在協商媒體編碼之前,先前電話送到 Dialplan,因而在 Dialplan 中可以進行個性化的媒體協商。 該選項允許任何電話註冊,而不檢查使用者和密碼及其它設定。 與上一條類似,該選項允許任何電話通過認證。 抑制 CNG。 SIP 認證中 nonce 的生存時間。 禁止譯碼,如果該項為 true 則在 bridge 其它電話時,只提供與 a-leg 相容或相同的語音編碼列表進行協商,以避免譯碼。 允許在 Dialplan 中進行人工轉向。 禁止轉移。 禁止註冊。 是否對電話進行認證。 強制使用者與認證使用者必須相同。 在認證時,對所有 SIP 訊息都進行認證,而不是僅針對 INVITE 訊息。 設定 NAT 環境中公網的 RTP IP。該設定會影響 SDP 中的 IP 地址。有以下幾種可能: 一個IP 地址,如 12.34.56.78 一個 stun 伺服器,它會使用 stun 協議獲得公網 IP, 如 stun:stun.server.com 一個 DNS 名稱,如 host:host.server.com auto , 它會自動檢測 IP 地址 auto-nat,如果路由器支援 NAT-PMP 或 UPNP,則可以使用這些協議獲取公網 IP。 指定的時間內 RTP 沒有資料傳送,則掛機。 RTP 處理保持狀態的最大時長。 語音活動狀態檢測,有三種可能,可設為入、出,或雙向,通常來說“出”(out)是一個比較好的選擇。 給本 sip profile 設定別名。 以上選項預設是起作用的,這有助於預設的例子更好的工作。它們會在註冊及訂閱時在資料庫中寫入同樣的域資訊。如果你在使用一個 FreeSWITCH 支援多個域時,不要選這些選項。 該選項有兩個值,true 或 poxy。 true 則直接接受 3pcc 來電;如果選 proxy,則會一直等待電話應答後才回送接受。 在 NAT 時強制 rport。除非你很瞭解該引數,否則後果自負。 設定 SIP Challenge 是使用的 realm 欄位是從哪個域獲取,auto_from 和 auto_to 分別是從 from 和 to 中獲取,除了這兩者,也可以是任意的值,如 freeswitch.org.cn。 大多數情況下,為了更好的穿越 NAT,FreeSWITCH 會自動調整 RTP 包的 IP 地址,但在某些情況下(尤其是在 mod_dingaling 中會有多個候選 IP),FreeSWITCH 可能會改變本來正確的 IP 地址。該引數禁用此功能。 在 FreeSWITCH 是,每一個 Channel 都有一個 UUID, 該 UUID 是由系統生成的全域性唯一的。對於來話,你可以使用 SIP 中的 callid 欄位來做 UUID. 在某些情況下對於信令的跟蹤分析比較有用。 與上一個引數差不多,只是在去話時可以使用 UUID 作為 callid。 RTP 自動定時。如果語音質量有問題,可以嘗試將該值設成 false。 預設情況下 FreeSWITCH 會設定額外的 X- SIP 訊息頭,在 SIP 標準中,所有 X- 打頭的訊息頭都是應該忽略的。但並不是所有的實現都符合標準,所以在對方的閘道器不支援這種 SIP 頭時,該選項允許你關掉它。 某些運營商的裝置不符合標準。為了最大限度的支援這些裝置,FreeSWITCH 在這方面進行了妥協。使用該引數時要小心。 這兩個引數可以規避 DNS 中某些錯誤的 SRV 或 NAPTR 記錄。 最後的這幾個引數允許根據需要調整 sofia 庫中底層的時鐘,一般情況下不需要改動。   external.xml   它是另一個 UA 配置檔案,它預設使用埠 5080。你可以看到,大部分引數都與 internal.xml 相同。最大的不同是 auth-calls 引數。在 internal.xml 中,auth-calls 預設是 true;而在 external.xml 中,預設是 false。也就是說,發往 5060 埠的 SIP 訊息(一般只有 INVITE 訊息)需要認證,而發往 5080 的訊息則不需要認證。我們一般把本地使用者都註冊到 5060 上,所以,它們打電話時要經過認證,保證只有在們使用者 directory 中配置的使用者能打電話。而 5080 則不同,任何人均可以向該埠傳送 SIP 請求。