《FreeSWITCH: VoIP實戰》:SIP 模塊 - mod_sofia

 

      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 也是。session

  配置文件

  Sofia 的配置文件是 conf/autoload_configs/sofia.conf.xml,不過,你通常不用直接修改它,由於它實際上直接使用一條預處理指令裝入了 conf/sip_profiles/ 目錄中的 XML 文件:架構

 

<X-PRE-PROCESS cmd="include" data="../sip_profiles/*.xml"/>

 

  因此,從如今起,能夠認爲全部的 Sofia 配置文件都在 conf/sip_profiles/ 中。app

  Sofia 支持多個 profile,而一個 profile 至關於一個 SIP UA,在啓動後它會監聽一個 「IP地址:端口」 對。讀到這裏細心的讀者或許會發現咱們前面的一個錯誤。咱們在講 B2BUA 的概念時,實際上只用到了一個 profile,也就是一個 UA,但咱們仍是說 FreeSWITCH 啓動了兩個 UA(一對背靠背的 UA)來爲 alice 和 bob 服務。是的,從物理上來說,它確實只是一個 UA,但因爲它同時支持多個 Session,在邏輯上就是至關於兩個 UA,爲了避免使用讀者太糾結於這種概念問題中,我在前面沒有太多的分析。但到了本章,你應該很是清楚 UA 的含義了。dom

  FreeSWITCH 默認的配置帶了三個 profile(也就是三個 UA),在這裏,咱們不討論 IPv6,所以只剩下 internal 和 external 兩個。 internal 和 external 的區別就是一個運行在 5060 端口上,另外一個是在 5080 端口上。固然,還有其它區別,咱們慢慢講。ide

internal.xml

internel.xml 定義了一個 profile,在本節,咱們以系統默認的配置逐行來解釋:模塊化

 

<profile name="internal">

 

profile 的名字就叫 internal,這個名字自己並無特殊的意義,也不須要與文件名相同,你能夠改爲任何你喜歡的名字,只是須要記住它,由於不少地方要使用這個名字。ui

 

 
  1. <aliases>

  2. <!-- <alias name="default"/> -->

  3. </aliases>

 

若是你喜歡,能夠爲該 profile 起一個別名。注意默認是加了註釋的,也就是說不起做用。再說一遍,「<!-- -->」在 XML 中的含義是註釋。

 

 
  1. <gateways>

  2. <X-PRE-PROCESS cmd="include" data="internal/*.xml"/>

  3. </gateways>

 

即然 profile 是一個 UA,它就能夠註冊到別的 SIP 服務器上去,它要註冊的 SIP 服務器就稱爲 Gateway。咱們通常不在 internal 這個 profile 上使用 Gateway,這個留到 external 時再講。

 

 
  1. <domains>

  2. <!--<domain name="$${domain}" parse="true"/>-->

  3. <domain name="all" alias="true" parse="false"/>

  4. </domains>

 

定義該 profile 所屬的 domain。它能夠是 IP 地址,或一個 DNS 域名。須要注意,直接在 hosts 文件中設置的 IP-域名可能很差用。

 

<settings>

 

settings 部分設置 profile 的參數。

 

<!--<param name="media-option" value="resume-media-on-hold"/> -->

  若是 FreeSWITCH 是沒有媒體(no media)的,那麼若是設置了該參數,當你在話機上按下 hold 鍵時,FreeSWITCH 將會回到有媒體的狀態。

  那麼什麼叫有媒體無媒體呢?以下圖,bob 和 alice 經過 FreeSWITCH 使用 SIP 接通了電話,他們談話的語音(或視頻)數據要經過 RTP 包傳送的。RTP 能夠 像 SIP 同樣通過 FreeSWITCH 轉發,可是,RTP 佔用很大的帶寬,若是 FreeSWITCH 不須要「偷聽」他們談話的話,爲了節省帶寬,徹底可讓 RTP 直接在二者間傳送,這種狀況對 FreeSWITCH 來說就是沒有 media 的,在 FreeSWITCH 中也稱 bypass media(繞過媒體)。

 

 
  1. FreeSWITCH

  2. SIP / \ SIP

  3. / \

  4. bob ------RTP------ alice

 

<!--<param name="media-option" value="bypass-media-after-att-xfer"/>-->

Attended Transfer 稱爲出席轉移,它須要 media 才能完成工做。但若是在執行 att-xfer 以前沒有媒體,該參數能讓 att-xfer 執行時有 media,轉移結束後再回到 bypass media 狀態。

 

<!-- <param name="user-agent-string" value="FreeSWITCH Rocks!"/> -->

不用解釋,就是設置 SIP 消息中顯示的 User-Agent 字段。

 

<param name="debug" value="0"/>

debug 級別。

 

<!-- <param name="shutdown-on-fail" value="true"/> -->

因爲各類緣由(如端口被佔用,IP地址錯誤等),均可能形成 UA 在初始化時失敗,該參數在失敗時會中止 FreeSWITCH。

 

<param name="sip-trace" value="no"/>

是否開啓 SIP 消息跟蹤。另外,也能夠在控制檯上用如下命令開啓和關閉 sip-trace:

 

 
  1. sofia profile internal siptrace on

  2. sofia profile internal siptrace off

 

<param name="log-auth-failures" value="true"/>

是否將認證錯誤寫入日誌。

 

<param name="context" value="public"/>

context 是 dialplan 中的環境。在此指定來話要落到 dialplan 的哪一個 context 環境中。須要指出,若是用戶註冊到該 profile 上(或是通過認證的用戶,即本地用戶),則用戶目錄(directory)中設置的 contex 優先級要比這裏高。

 

<param name="rfc2833-pt" value="101"/>

設置 SDP 中 RFC2833 的值。RFC2833 是傳遞 DTMF 的標準。

 

<param name="sip-port" value="$${internal_sip_port}"/>

監聽的 SIP 端口號,變量 internal_sip_port 在 vars.xml 中定義,默認是 5060。

 

<param name="dialplan" value="XML"/>

設置對應默認的 dialplan。咱們後面會專門講 dialplan。

 

<param name="dtmf-duration" value="2000"/>

設置 DTMF 的時長。

 

<param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>

支持的來話語音編碼,用於語音編碼協商。global_codec_prefs 是在 vars.xml中定義的。

 

<param name="outbound-codec-prefs" value="$${global_codec_prefs}"/>

支持的去話語音編碼。

 

<param name="rtp-timer-name" value="soft"/>

 

RTP 時鐘名稱

 

<param name="rtp-ip" value="$${local_ip_v4}"/>

RTP 的 IP 地址,僅支持 IP 地址而不支持域名。雖然 RTP 標準說應該域名,但實際狀況是域名解析有時不可靠。

 

<param name="sip-ip" value="$${local_ip_v4}"/>

SIP 的 IP。不支持域名。

 

<param name="hold-music" value="$${hold_music}"/>

UA 進行 hold 狀態時默認播放的音樂。

 

<param name="apply-nat-acl" value="nat.auto"/>

使用哪一個 NAT ACL。

 

<!-- <param name="extended-info-parsing" value="true"/> -->

擴展 INFO 解析支持。

 

<!--<param name="aggressive-nat-detection" value="true"/>-->

NAT穿越,檢測 SIP 消息中的 IP 地址與實際的 IP 地址是否相符,詳見 NAT穿越。

 

 
  1. <!--

  2. There are known issues (asserts and segfaults) when 100rel is enabled.

  3. It is not recommended to enable 100rel at this time.

  4. -->

  5. <!--<param name="enable-100rel" value="true"/>-->

該功能暫時還不推薦使用。

 

<!--<param name="enable-compact-headers" value="true"/>-->

支持壓縮 SIP 頭。

 

<!--<param name="enable-timer" value="false"/>-->

開啓、關閉 SIP 時鐘。

 

<!--<param name="minimum-session-expires" value="120"/>-->

SIP 會話超時值,在 SIP 消息中設置 Min-SE。

 

<param name="apply-inbound-acl" value="domains"/>

對來話採用哪一個 ACL。詳見 ACL。

 

<param name="local-network-acl" value="localnet.auto"/>

默認狀況下,FreeSWITCH 會自動檢測本地網絡,並建立一條 localnet.auto ACL 規則。

 

<!--<param name="apply-register-acl" value="domains"/>-->

對註冊請求採用哪一個 ACL。

 

<!--<param name="dtmf-type" value="info"/>-->

DTMF 收號的類型。有三種方式,info、inband、rfc2833。

  info 方式是採用 SIP 的 INFO 消息傳送 DTMF 按鍵信息的,因爲 SIP 和 RTP 是分開走的,因此,可能會形成不一樣步。

  inband 是在 RTP 包中象普通語音數據那樣進行帶內傳送,因爲須要對全部包進行鑑別和提取,須要佔用更多的資源。

  rfc2833 也是在帶內傳送,但它的 RTP 包有特殊的標記,於是比 inband 方式節省資源。它是在 RFC2833 中定義的。

 

 
  1. <!-- 'true' means every time 'first-only' means on the first register -->

  2. <!--<param name="send-message-query-on-register" value="true"/>-->

如何發送請求消息。true 是每次都發送,而 first-only 只是首次註冊時發送。

 

<!--<param name="caller-id-type" value="rpid|pid|none"/>-->

設置來電顯示的類型,rpid 將會在 SIP 消息中設置 Remote-Party-ID,而 pid 則會設置 P-*-Identity,若是不須要這些,能夠設置成 none。

 

<param name="record-path" value="$${recordings_dir}"/>

錄音文件的默認存放路徑。

 

<param name="record-template" value="${caller_id_number}.${target_domain}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>

錄音文件名模板。

 

<param name="manage-presence" value="true"/>

是否支持列席。

 

<!--<param name="manage-shared-appearance" value="true"/>-->

是否支持 SLA - Shared Line Apperance。

 

 
  1. <!--<param name="dbname" value="share_presence"/>-->

  2. <!--<param name="presence-hosts" value="$${domain}"/>-->

這兩個參數用以在多個 profile 間共享列席信息。

 

 
  1. <!-- This setting is for AAL2 bitpacking on G726 -->

  2. <!-- <param name="bitpacking" value="aal2"/> -->

  3. <!--<param name="max-proceeding" value="1000"/>-->

最大的開放對話(SIP Dialog)數。

 

 
  1. <!--session timers for all call to expire after the specified seconds -->

  2. <!--<param name="session-timeout" value="120"/>-->

會話超時時間。

 

 
  1. <!-- Can be 'true' or 'contact' -->

  2. <!--<param name="multiple-registrations" value="contact"/>-->

是否支持多點註冊,能夠是 contact 或 true。開啓多點註冊後多個 UA 能夠註冊上來,有人呼叫這些 UA 時全部 UA 都會振鈴。

 

 
  1. <!--set to 'greedy' if you want your codec list to take precedence -->

  2. <param name="inbound-codec-negotiation" value="generous"/>

SDP 中的語音編協商,若是設成 greedy,則本身提供的語音編碼列表會有優先權.

 

 
  1. <!-- if you want to send any special bind params of your own -->

  2. <!--<param name="bind-params" value="transport=udp"/>-->

  3. <!--<param name="unregister-on-options-fail" value="true"/>-->

爲了 NAT 穿越或 keep alive,若是 FreeSWITCH 向其它網關注冊時,能夠週期性地發一些 OPTIONS 包,至關於 ping 功能。該參數說明當 ping 失敗時是否自動取消註冊。

 

<param name="tls" value="$${internal_ssl_enable}"/>

是否支持 TLS,默認否。

 

 
  1. <!-- additional bind parameters for TLS -->

  2. <param name="tls-bind-params" value="transport=tls"/>

  3. <!-- Port to listen on for TLS requests. (5061 will be used if unspecified) -->

  4. <param name="tls-sip-port" value="$${internal_tls_port}"/>

  5. <!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->

  6. <param name="tls-cert-dir" value="$${internal_ssl_dir}"/>

  7. <!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->

  8. <param name="tls-version" value="$${sip_tls_version}"/>

下面都是與 TLS 有關的參數,略。

 

<!--<param name="rtp-autoflush-during-bridge" value="false"/>-->

該選項默認爲 true。即在橋接電話是是否自動 flush 媒體數據(若是套接字上已有數據時,它會忽略定時器睡眠,能有效減小延遲)。

 

<!--<param name="rtp-rewrite-timestamps" value="true"/>-->

是否透傳 RTP 時間戳。

 

<!--<param name="pass-rfc2833" value="true"/>-->

是否透傳 RFC2833 DTMF 包。

 

<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->

使用 ODBC 數據庫代替默認的 SQLite。

 

<!--<param name="inbound-bypass-media" value="true"/>-->

將全部來電設置爲媒體繞過。

 

<!--<param name="inbound-proxy-media" value="true"/>-->

將全部來電設置爲媒體透傳。

 

 
  1. <!--Uncomment to let calls hit the dialplan *before* you decide if the codec is ok-->

  2. <!--<param name="inbound-late-negotiation" value="true"/>-->

對全部來電來說,晚協商有助於在協商媒體編碼以前,先前電話送到 Dialplan,於是在 Dialplan 中能夠進行個性化的媒體協商。

 

<!-- <param name="accept-blind-reg" value="true"/> -->

該選項容許任何電話註冊,而不檢查用戶和密碼及其它設置。

 

<!-- <param name="accept-blind-auth" value="true"/> -->

與上一條相似,該選項容許任何電話經過認證。

 

<!-- <param name="suppress-cng" value="true"/> -->

抑制 CNG。

 

<param name="nonce-ttl" value="60"/>

SIP 認證中 nonce 的生存時間。

 

<!--<param name="disable-transcoding" value="true"/>-->

禁止譯碼,若是該項爲 true 則在 bridge 其它電話時,只提供與 a-leg 兼容或相同的語音編碼列表進行協商,以免譯碼。

 

<!--<param name="manual-redirect" value="true"/> -->

容許在 Dialplan 中進行人工轉向。

 

<!--<param name="disable-transfer" value="true"/> -->

禁止轉移。

 

<!--<param name="disable-register" value="true"/> -->

禁止註冊。

 

 
  1. <!-- Used for when phones respond to a challenged ACK with method INVITE in the hash -->

  2. <!--<param name="NDLB-broken-auth-hash" value="true"/>-->

  3. <!-- add a ;received="<ip>:<port>" to the contact when replying to register for nat handling -->

  4. <!--<param name="NDLB-received-in-nat-reg-contact" value="true"/>-->

  5. <param name="auth-calls" value="$${internal_auth_calls}"/>

是否對電話進行認證。

 

 
  1. <!-- Force the user and auth-user to match. -->

  2.  
  3. <param name="inbound-reg-force-matching-username" value="true"/>

強制用戶與認證用戶必須相同。

 

<param name="auth-all-packets" value="false"/>

在認證時,對全部 SIP 消息都進行認證,而不是僅針對 INVITE 消息。

 

 
  1. <!-- external_sip_ip

  2. Used as the public IP address for SDP.

  3. Can be an one of:

  4. ip address - "12.34.56.78"

  5. a stun server lookup - "stun:stun.server.com"

  6. a DNS name - "host:host.server.com"

  7. auto - Use guessed ip.

  8. auto-nat - Use ip learned from NAT-PMP or UPNP

  9. -->

  10. <param name="ext-rtp-ip" value="auto-nat"/>

  11. <param name="ext-sip-ip" value="auto-nat"/>

設置 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。

 

<param name="rtp-timeout-sec" value="300"/>

指定的時間內 RTP 沒有數據傳送,則掛機。

 

<param name="rtp-hold-timeout-sec" value="1800"/>

RTP 處理保持狀態的最大時長。

 

 
  1. <!-- <param name="vad" value="in"/> -->

  2. <!-- <param name="vad" value="out"/> -->

  3. <!-- <param name="vad" value="both"/> -->

語音活動狀態檢測,有三種可能,可設爲入、出,或雙向,一般來講「出」(out)是一個比較好的選擇。

 

<!--<param name="alias" value="sip:10.0.1.251:5555"/>-->

給本 sip profile 設置別名。

 

 
  1. <!--all inbound reg will look in this domain for the users -->

  2. <param name="force-register-domain" value="$${domain}"/>

  3. <!--force the domain in subscriptions to this value -->

  4. <param name="force-subscription-domain" value="$${domain}"/>

  5. <!--all inbound reg will stored in the db using this domain -->

  6. <param name="force-register-db-domain" value="$${domain}"/>

  7. <!--force suscription expires to a lower value than requested-->

  8. <!--<param name="force-subscription-expires" value="60"/>-->

以上選項默認是起做用的,這有助於默認的例子更好的工做。它們會在註冊及訂閱時在數據庫中寫入一樣的域信息。若是你在使用一個 FreeSWITCH 支持多個域時,不要選這些選項。

 

<!--<param name="enable-3pcc" value="true"/>-->

該選項有兩個值,true 或 poxy。 true 則直接接受 3pcc 來電;若是選 proxy,則會一直等待電話應答後纔回送接受。

 

 
  1. <!-- use at your own risk or if you know what this does.-->

  2. <!--<param name="NDLB-force-rport" value="true"/>-->

在 NAT 時強制 rport。除非你很瞭解該參數,不然後果自負。

 

<param name="challenge-realm" value="auto_from"/>

設置 SIP Challenge 是使用的 realm 字段是從哪一個域獲取,auto_from 和 auto_to 分別是從 from 和 to 中獲取,除了這二者,也能夠是任意的值,如 freeswitch.org.cn。

 

<!--<param name="disable-rtp-auto-adjust" value="true"/>-->

大多數狀況下,爲了更好的穿越 NAT,FreeSWITCH 會自動調整 RTP 包的 IP 地址,但在某些狀況下(尤爲是在 mod_dingaling 中會有多個候選 IP),FreeSWITCH 可能會改變原本正確的 IP 地址。該參數禁用此功能。

 

<!--<param name="inbound-use-callid-as-uuid" value="true"/>-->

在 FreeSWITCH 是,每個 Channel 都有一個 UUID, 該 UUID 是由系統生成的全局惟一的。對於來話,你可使用 SIP 中的 callid 字段來作 UUID. 在某些狀況下對於信令的跟蹤分析比較有用。

 

<!--<param name="outbound-use-uuid-as-callid" value="true"/>-->

與上一個參數差很少,只是在去話時可使用 UUID 做爲 callid。

 

<!--<param name="rtp-autofix-timing" value="false"/>-->

RTP 自動定時。若是語音質量有問題,能夠嘗試將該值設成 false。

 

<!--<param name="pass-callee-id" value="false"/>-->

默認狀況下 FreeSWITCH 會設置額外的 X- SIP 消息頭,在 SIP 標準中,全部 X- 打頭的消息頭都是應該忽略的。但並非全部的實現都符合標準,因此在對方的網關不支持這種 SIP 頭時,該選項容許你關掉它。

 

 
  1. <!-- clear clears them all or supply the name to add or the name prefixed with ~ to remove

  2. valid values:

  3. clear

  4. CISCO_SKIP_MARK_BIT_2833

  5. SONUS_SEND_INVALID_TIMESTAMP_2833

  6. -->

  7. <!--<param name="auto-rtp-bugs" data="clear"/>-->

某些運營商的設備不符合標準。爲了最大限度的支持這些設備,FreeSWITCH 在這方面進行了妥協。使用該參數時要當心。

 

 
  1. <!-- the following can be used as workaround with bogus SRV/NAPTR records -->

  2. <!--<param name="disable-srv" value="false" />-->

  3. <!--<param name="disable-naptr" value="false" />-->

這兩個參數能夠規避 DNS 中某些錯誤的 SRV 或 NAPTR 記錄。

最後的這幾個參數容許根據須要調整 sofia 庫中底層的時鐘,通常狀況下不須要改動。

 

 
  1. <!-- The following can be used to fine-tune timers within sofia's transport layer

  2. Those settings are for advanced users and can safely be left as-is -->

  3. <!-- Initial retransmission interval (in milliseconds).

  4. Set the T1 retransmission interval used by the SIP transaction engine.

  5. The T1 is the initial duration used by request retransmission timers A and E (UDP) as well as response retransmission timer G. -->

  6. <!-- <param name="timer-T1" value="500" /> -->

  7. <!-- Transaction timeout (defaults to T1 * 64).

  8. Set the T1x64 timeout value used by the SIP transaction engine.

  9. The T1x64 is duration used for timers B, F, H, and J (UDP) by the SIP transaction engine.

  10. The timeout value T1x64 can be adjusted separately from the initial retransmission interval T1. -->

  11. <!-- <param name="timer-T1X64" value="32000" /> -->

  12.  
  13. <!-- Maximum retransmission interval (in milliseconds).

  14. Set the maximum retransmission interval used by the SIP transaction engine.

  15. The T2 is the maximum duration used for the timers E (UDP) and G by the SIP transaction engine.

  16. Note that the timer A is not capped by T2. Retransmission interval of INVITE requests grows exponentially

  17. until the timer B fires. -->

  18. <!-- <param name="timer-T2" value="4000" /> -->

  19. <!--

  20. Transaction lifetime (in milliseconds).

  21. Set the lifetime for completed transactions used by the SIP transaction engine.

  22. A completed transaction is kept around for the duration of T4 in order to catch late responses.

  23. The T4 is the maximum duration for the messages to stay in the network and the duration of SIP timer K. -->

  24. <!-- <param name="timer-T4" value="4000" /> -->

  25. </settings>

  26. </profile>

  external.xml   它是另外一個 UA 配置文件,它默認使用端口 5080。你能夠看到,大部分參數都與 internal.xml 相同。最大的不一樣是 auth-calls 參數。在 internal.xml 中,auth-calls 默認是 true;而在 external.xml 中,默認是 false。也就是說,發往 5060 端口的 SIP 消息(通常只有 INVITE 消息)須要認證,而發往 5080 的消息則不須要認證。咱們通常把本地用戶都註冊到 5060 上,因此,它們打電話時要通過認證,保證只有在們用戶 directory 中配置的用戶能打電話。而 5080 則不一樣,任何人都可以向該端口發送 SIP 請求。

相關文章
相關標籤/搜索