閱讀《FreeSWITCH 權(quán)威指南》筆記。
簡單使用
windows 安裝 FreeSwitch
自己的電腦系統(tǒng)是 xubuntu 22.10 Ubuntu Kinetic Kudu (development branch) 版本,linx 安裝 FreeSwitch 需要自己編譯安裝,里面安裝編譯會(huì)出錯(cuò),所以采用虛擬機(jī) windows 安裝。windows 安裝很方便,不再贅述。
freeswitch 默認(rèn)開啟了 1000~1019 的號(hào)碼,默認(rèn)密碼為 1234。
可通過配置文件 安裝目錄下\conf\directory\default\ 內(nèi)查看各個(gè)號(hào)碼的配置信息,其中的變量如 $${default_password} 在 安裝目錄\conf\vas.xml 中定義。
啟動(dòng) freeswitch 在開始菜單的列表中 右鍵程序-以管理員身份運(yùn)行 進(jìn)行啟動(dòng),當(dāng)出現(xiàn)如下界面時(shí)即啟動(dòng)完成。

sip客戶端安裝、登陸、呼叫
在 Windows 中用的是 MicroSip,安裝和使用都很方便(僅使用于 Windoes)。下載鏈接
手機(jī)端用的是 SipDroid,在手機(jī)瀏覽器中找的下載鏈接。配置登陸號(hào)碼見下方截圖(域名即 FreeSwitch 所安裝機(jī)器的 IP 地址)。
手機(jī)端和 MicroSip 的配置幾乎是一樣的,不過需要在同一個(gè)局域網(wǎng)中。我是用手機(jī)分出了 Wifi 讓主機(jī)連接,然后 VirtualBox 使用橋接的方式連上主機(jī)網(wǎng)絡(luò)。多個(gè)終端也可以通過多開幾個(gè)虛擬機(jī)安裝 MircoSip 的方式實(shí)現(xiàn)。

不同客戶端通過登陸不同的號(hào)碼,就可以通過電話進(jìn)行呼叫和通話了。

啟動(dòng) FS 后,在安裝包中還有一個(gè) fs-cli 是可以連接到 FS 的客戶端,和 FS 一樣的輸入輸出,但關(guān)閉不影響服務(wù)程序。
FreeSwitch 基本命令
sofia status profile internal reg # 查看已注冊(cè)(登陸)設(shè)備(號(hào)碼)
originate user/1000 &park # 通過 1000 撥打電話到 park 程序
# 程序(APP)其實(shí)為 freeswitch 內(nèi)置的函數(shù)(注意使用時(shí)加上 & 符號(hào)):
# park 掛起(聽不到任何聲音)
# hold 掛起(能聽到聲音,Music On Hold, MOH)
# playback(/root/welcome.wav) 播放特定的聲音文件
# record(/tmp/rec.wav) 錄音文件
# bridge(user/1001) 轉(zhuǎn)接到 1001
show channels # 顯示通話中的一些信息,包含 UUID
uuid_bridge <uuid1> <uuid2> # 將兩個(gè) channel 橋接起來
help # 幫助
sofia help # 模塊幫助
sofia global siptrace on # 開啟 sip 信息的顯示,用 off 可以關(guān)閉。
FreeSWITCH 架構(gòu)
以下 FS 表示 FreeSWITCH 的縮寫。
總體架構(gòu)
總體來說包括 核心 和 外圍模塊 組成。核心短小精悍高穩(wěn)定高安全,外圍模塊通過調(diào)用核心提供的 API 與核心進(jìn)行通信,核心通過讓外圍模塊注冊(cè)回調(diào)函數(shù)執(zhí)行外圍模塊代碼。
核心主要有四部分:DB、公共接口(Public API)、抽象接口和事件(Event)。
DB 默認(rèn)使用 SQLite,SQLite 是一種嵌入式數(shù)據(jù)庫。FS 使用核心數(shù)據(jù)庫(在
安裝目錄/db/core.db)來記錄系統(tǒng)接口、任務(wù)(tasks)及當(dāng)前的通道(channels)、通話(calls)等實(shí)時(shí)數(shù)據(jù)。模塊也有自己的數(shù)據(jù)庫(表)在 db 目錄下。公共接口(Public API)可以被外圍模塊調(diào)用。如創(chuàng)建或釋放媒體流、Json處理函數(shù)等等。
抽象接口,抽象接口是核心沒有實(shí)現(xiàn)的接口,一般由外圍模塊負(fù)責(zé)實(shí)現(xiàn)并向核心層 注冊(cè),核心通過 回調(diào) 的方式調(diào)用具體的實(shí)現(xiàn)。
事件(Event),F(xiàn)S 在內(nèi)部使用消息和 事件機(jī)制 進(jìn)行進(jìn)程間和模塊間通信。事件的產(chǎn)生和消費(fèi)是異步的,事件可以在 FS 中通過 綁定(Bind)回調(diào)函數(shù) 進(jìn)行捕獲,即 FS 在時(shí)間發(fā)生時(shí)會(huì)依次回調(diào)這些函數(shù)。
外圍接口實(shí)現(xiàn)
- Endpoint,是 FS 的最外圍(再向外就不是 FS 了),主要 包含了不同 呼叫控制協(xié)議的接口,實(shí)現(xiàn)與不同電話系統(tǒng)的通信。
- Dialplan,撥號(hào)計(jì)劃,提供電話路由功能。系統(tǒng)默認(rèn)是由 mod_dialplan_xml 提供。
- Chatplan,聊天計(jì)劃,提供對(duì)文本消息的路由,由 mod_sms 實(shí)現(xiàn)。
- APP,應(yīng)用程序,F(xiàn)S 提供了一些內(nèi)置的 APP。如 mod_voicemail 實(shí)現(xiàn)語音留言;mod_conference 實(shí)現(xiàn)多方會(huì)議。
- FSAPI,命令接口,是對(duì)外的命令接口。
- XML 接口,支持多種 XML 的讀取,如 本地文件、DB、遠(yuǎn)程 HTTP 請(qǐng)求等。但對(duì)于應(yīng)用和擴(kuò)展在外圍模塊中完成,如 mod_xml_rpc、mod_xml_curl 等。
- Codec,編解碼器(是 COde 與 DECode 的組合)。FS 的實(shí)現(xiàn)可以橋接不同采樣頻率的電話或會(huì)議電話。
- 語音識(shí)別及語音合成(ASR/TTS)。
- 格式、文件接口(Format, File Interface),支持不同格式文件的回放、錄音。
- 日志(Logger),控制日志寫到 控制臺(tái)、文件、系統(tǒng)日志(syslog)、遠(yuǎn)程日志服務(wù)器等。
- 定時(shí)器(Timer),F(xiàn)S 最理想的工作始終頻率是 1000Hz,許多默認(rèn) Linux 發(fā)行版內(nèi)核默認(rèn)是 100Hz 或 250 Hz,在這種情況下可以重新編譯內(nèi)核調(diào)整始終頻率。
- 嵌入式語言(Embeded Language),支持 Lua、Javascript、Perl 等控制呼叫流程。
- 事件套接字(Event Socket),可以使用任何其他語言通過事件套接字控制呼叫流程、擴(kuò)展 FS 功能。
目錄結(jié)構(gòu)
在安裝目錄下
sounds 提供各種聲音文件,sounds/music 提供 MOH(Music On Hold,保持音樂)
storage 存放從其他 HTTP 服務(wù)器下載下來的語音文件緩存及錄音留言文件
conf 存放配置文件
著重介紹下配置文件,配置文件由眾多 XML 組成系統(tǒng)裝載時(shí),會(huì)將 XML 組織在一起 Load 到內(nèi)存,成為 XML 注冊(cè)表。
-
conf/freeswitch.xml是主入口,是所有 XML 文件的黏合劑。標(biāo)簽X-PRE-PROCESS是預(yù)處理命令,是在加載階段只進(jìn)行簡單的替換不會(huì)被解析,所以對(duì)它進(jìn)行注釋仍然會(huì)發(fā)生替換,需要注意一些影響。 -
vars.xml是通過X-PRE-PROCESS定義的一些全局變量,在后續(xù)以$${var}的方式進(jìn)行引用??梢酝ㄟ^global_getvar命令來查看變量值。 - autoload_configs 目錄下是模塊級(jí)的配置文件,命令方式
模塊名.conf.xml(無前綴 mod_),會(huì)在系統(tǒng)啟動(dòng)的時(shí)候 Load。各模塊查找是通過 configuration 標(biāo)簽的 name 屬性查找的。如 mod_sofia 在啟動(dòng)時(shí)會(huì)向 XML 注冊(cè)表中查找 configuration 標(biāo)簽為 sofia.conf 的配置。- autoload_configs 下的 modules.conf.xml 定義了啟動(dòng)時(shí)自動(dòng)加載哪些模塊。
- autoload_configs 下的 post_load_modules.conf.xml 中定義的模塊是最后加載的。
-
conf/dialplan目錄中的 XML 是路由計(jì)劃 -
conf/ivr_menues中存放了默認(rèn)的 IVR 菜單 -
conf/directory中存放了用戶配置目錄(用戶目錄)。FS 的 用戶目錄 支持多個(gè)域(Domain)。
XML 用戶目錄
SIP 不要求一定要注冊(cè)才可以打電話,但通話前仍需用戶認(rèn)證,認(rèn)證參數(shù)即中用戶目錄中進(jìn)行配置。即用戶目錄決定了哪些用戶能注冊(cè)到 FS 中。
<include>
<domain name="$${domain}">
<params>
<param name="dial-string" value="..."/>
</params>
<variables>
<variable name="record_stereo" value="true"/>
</variables>
<groups>
<group name="sales">
<users>
<user id="1000" type="pointer"/>
</users>
</group>
</groups>
</domain>
</include>
default.xml 是自帶默認(rèn)的配置文件。其中 $${domain} 默認(rèn)變量值是主機(jī) IP 地址,可以將他修改為一個(gè)域名。
-
params標(biāo)簽中定義 domain 下所有用戶的公共參數(shù)。 - params 定義的
dial-string變量很重要,F(xiàn)S 會(huì)使用 user/username 或 sofia/internal/username@domain 呼叫時(shí)會(huì)根據(jù) username 等信息找到 dial-string 最終擴(kuò)展成用戶實(shí)際 SIP 地址。 -
variables標(biāo)簽定義了一些 Channel 級(jí)別的公共變量,在通話中會(huì)綁定到相應(yīng)的 Channel 上形成 Channel Variables。 -
groups、group組標(biāo)簽,是不必要的,但可以方便地進(jìn)行群呼、代接之類的業(yè)務(wù)。 -
users、user標(biāo)簽可以是完整的 XML,也可以是指向已存在用戶的“指針”(type="pointer",通過<user id="xxx">來找到)。 - 注:params 和 variables 可以出現(xiàn)在 user、group 或 domain 中,優(yōu)先級(jí)按作用域的減小而增大。
呼叫相關(guān)概念
兩種典型流程:
- Bob -> FS -> Alice
- FS -> Bob && FS -> Alice
市場上有對(duì)方式二的變種,流程為 a) B -> FS 隨即 FS 掛掉電話;b) FS -> B && FS -> A。好處:接電話不會(huì)被收費(fèi)。(華為中 Welink 呼叫就是這個(gè)流程)。
- 來話,針對(duì)與 FS 是到達(dá) FS 的呼叫
- 去話,針對(duì)于 FS 是從 FS 出去的呼叫
- Session,無論來話去話 FS 都會(huì)啟動(dòng)一個(gè) Session(會(huì)話)用于控制整個(gè)呼叫
- Channel,每個(gè) Session 控制這一個(gè) Channel(信道、通道),是一對(duì) UA 間通信的實(shí)體,相當(dāng)于 FS 的一條腿。每個(gè) Channel 都用一個(gè)唯一的 UUID 來標(biāo)識(shí),稱為 Channel UUID;每個(gè) Channel 上可以綁定一些呼叫參數(shù),稱為 Channel Variables(通道變量)。
- Call,F(xiàn)S 的作用是將兩個(gè) Channel 橋接 到一起組成一個(gè)通話,稱為一個(gè) Call。
- 回鈴音和 Early Media,假設(shè)A、B 不在同一交換機(jī)(服務(wù)器)上通話,中間會(huì)經(jīng)過兩臺(tái)交換機(jī) a、b:
A <-> a <-> b <-> B。在早期,A 呼 B 在 B 開始振鈴時(shí),A 能聽到單一的回鈴音(Ring Back Tone),這里 b 只向 a 傳送了個(gè)信令傳達(dá)到 B 的信號(hào),由 a 交換機(jī)生成來鈴流;后來,為了支持讓 A 聽 B 端定制的鈴流,必須由交換機(jī) b 返回鈴流,這就是 Early Media(早期媒體)。在 SIP 通信中是由 183 消息(帶有 SDP)描述的。
Early Media 的流量不包含在通信費(fèi)中,一般是在月租或套餐中的收費(fèi)的,所以可以將真正的話音數(shù)據(jù)偽裝成 Early Media 實(shí)現(xiàn)“免費(fèi)通話”。但這種應(yīng)用有一定的限制,大多數(shù)交換機(jī)允許的 Early Media 不會(huì)太常,如 1 分鐘,以避免這種免費(fèi)通話。
- 全局變量和局部變量,全局變量在服務(wù)加載時(shí)只求值一次,用
$${var}形式引用;局部變量即 Channel Variables,在每次創(chuàng)建 Channel 時(shí)求值(生命周期),用${var}引用。部分變量在顯示時(shí)有 variable_ 前綴,但在使用時(shí)不需要此前綴。
撥號(hào)計(jì)劃 DialPlan
找到了本章的在線讀書筆記可參考。
從配置文件看工作流程
配置文件的撥號(hào)計(jì)劃又叫 XML DialPlan,下文還會(huì)降到 內(nèi)聯(lián)撥號(hào)計(jì)劃。
撥號(hào)計(jì)劃默認(rèn)用 XML 格式配置。DailPlan 的完整結(jié)構(gòu)的配置是這樣的嵌套結(jié)構(gòu)(簡寫了 xml 文件):
- document
- section(name: dialplan)
- context
- extension # extension 與 extension 之間在邏輯上是隔離的
- condition(field="xxx" expression="^echo|1234$") # 測試條件,指定表達(dá)式
- action(application="info" data="xxx") # 執(zhí)行動(dòng)作
- 修改配置文件后要用
reloadxml命令或 F6鍵 重載配置文件 - DailPlan 的匹配順序是按先后順序進(jìn)行匹配的,所以注意(不清楚整體情況時(shí))自己修改的放到前面
- 注意修改權(quán)限,我在 sublime 中修改保存成功但實(shí)際 reloadxml 不成功,在整個(gè)文件夾的上加修改權(quán)限后成功
- 按 F8 或
console loglevel debug設(shè)置 console 的 log 級(jí)別為 debug -
extension標(biāo)簽有個(gè)continue="true"屬性,表示匹配完當(dāng)前 extension 后還可以匹配后方的 extension,默認(rèn) continue 為 false。 -
condition標(biāo)簽,為空表示匹配所有條件- 驗(yàn)證用戶信息的 field(可以是內(nèi)置變量,用戶目錄中的外置變量要用
${})與 expression(正則)是否匹配 -
condition標(biāo)簽可疊加,表示與關(guān)系 -
condition標(biāo)簽中break參數(shù)可以做邏輯判斷,如break="on-true"表示 在執(zhí)行完本 cond 中的 action 后if true break,另外有 on-false(默認(rèn)),always,never
- 驗(yàn)證用戶信息的 field(可以是內(nèi)置變量,用戶目錄中的外置變量要用
-
action標(biāo)簽是執(zhí)行動(dòng)作,application表示設(shè)置執(zhí)行的應(yīng)用,data為傳進(jìn)去的字段,現(xiàn)知的應(yīng)用有:- info:輸出所有變量到日志中
- answer:接聽電話,相當(dāng)于 FS 響應(yīng)應(yīng)答消息,后面可以設(shè)置一些媒體流如放音、轉(zhuǎn)到語音信箱等。
- echo(數(shù)字號(hào)碼 9196):回聲,可以聽到自己的聲音,另外還有個(gè)延遲回聲
delay_echo(9195)。 - log:輸出日志,
- hangup:掛斷電話
- set:設(shè)置一個(gè)當(dāng)前 leg 的變量綁定到 Channel 上。如設(shè)置 greeting 變量的 data:
data="greeting=good-morning.wav" - export:設(shè)置一個(gè)雙方 leg 的變量,同時(shí)還設(shè)置一個(gè)
export_vars=greeting,當(dāng) data 開頭為nolocal:時(shí)表示只設(shè)置到對(duì)方 leg 上。 - hash:設(shè)置變量到內(nèi)存哈希表中,data 的格式為
operator/key/scope/value - bridge:作用,將兩條腿橋接起來(在這里創(chuàng)建 b-leg),data 是標(biāo)準(zhǔn)的呼叫字符串(Dial string),內(nèi)部
{c=d}可以設(shè)置 b-leg 的通道變量 c = d 。birdge 會(huì)一直阻塞等待 b-leg 接聽或掛機(jī)等操作。 - sleep:表示暫停的 ms 數(shù)
- conference,會(huì)議,可以配置 condition 將呼叫某一(類)號(hào)碼的用戶都轉(zhuǎn)到會(huì)議中(會(huì)議分組看 data 格式)。
- bind_meta_app,根據(jù)用戶輸入的 number(加星號(hào))執(zhí)行操作。
- transfer,將當(dāng)前通話重新轉(zhuǎn)移到 Routing 階段。
- playback(9664),播放一個(gè)聲音文件
- record,開啟錄音,data 中傳保存位置
<extension name="My Echo Test"> <!-- 測試時(shí)名字沒改,忽略其意義就好 -->
<condition expression="^1234(\d+)$" field="destination_number">
<action application="log" data="INFO you called ${destination_number}"/> <!-- log 數(shù)據(jù)首單詞可設(shè)置級(jí)別 -->
<action application="log" data="NOTICE the suffix is $1"/>
<action application="hangup"/>
</condition>
</extension>

- 注意執(zhí)行階段,解析階段,執(zhí)行階段
- 日志級(jí)別:CONSOLE、ALERT、CRIT、ERR、WARNING、NOTICE、INFO、DEBUG
- 反動(dòng)作標(biāo)簽
anti-action,當(dāng) condition 不匹配時(shí)可以執(zhí)行 內(nèi)部 的anti-action標(biāo)簽(神奇的設(shè)定)。
工作機(jī)制
Channel 狀態(tài)機(jī)轉(zhuǎn)換工程: NEW - INIT - ROUTING/HUNTING - EXECUTE - HANGUP - REPORTING - DESTROY
新建 Channel - 初始化 - 路由(查找解析 Dialplan) - 執(zhí)行動(dòng)作 - 掛機(jī)(某一方執(zhí)行)- 包好(統(tǒng)計(jì)計(jì)費(fèi)) - 銷毀(釋放資源)
在 執(zhí)行 階段,也可以發(fā)生轉(zhuǎn)移(Transfer),轉(zhuǎn)移到同一個(gè) Context 下不同 Extension,轉(zhuǎn)移后會(huì)重新進(jìn)入 Routing 階段。
注意:
- 默認(rèn)情況下,Routing 階段會(huì)查到到 執(zhí)行計(jì)劃 中的所有 Extension,并把 action 放到一個(gè)隊(duì)列中,然后才進(jìn)入 Execute 階段執(zhí)行。所以在 action 標(biāo)簽中改變某值去影響路由的邏輯是不對(duì)的(除非用 inline 屬性)。
- action 標(biāo)簽上
inline="true"屬性可以讓 action 在 Routing 階段執(zhí)行 - 可用
inline屬性的 app 不多,一般都是很快地存取變量的操作。
內(nèi)聯(lián)撥號(hào)計(jì)劃
可以把前面講到的撥號(hào)計(jì)劃成為“XML 撥號(hào)計(jì)劃”。內(nèi)聯(lián)撥號(hào)計(jì)劃(Inline Dialplan),用于快速測試不同的 action,可以直接在命令行中寫出對(duì)應(yīng)的命令:
originate user/1000 answer,playback:/tmp/a.wav,record:/tmp/b.wav inline
# 解釋:使用 1000 撥打,首先 answer,然后放音 a.wav,然后錄音到 b.wav
如上注釋中的解釋,不再重復(fù)了,其中:
- 不同于之前用
&指定的 APP,用內(nèi)聯(lián)形式不需加&且可以指定多個(gè) APP(是個(gè)流程) - 帶參數(shù)的 APP 用
APP:args格式來書寫 - 多個(gè) APP 間默認(rèn)用 逗號(hào) 分隔
- 當(dāng)參數(shù)中有空格時(shí),用單引號(hào)括住參數(shù)
- 當(dāng)參數(shù)中有逗號(hào)時(shí),可以用 m 語法修改分隔符為其他字符,如
m:^:xxx表示 xxx 中用 ^ 表示分隔符
調(diào)用 API
在撥號(hào)計(jì)劃中可以調(diào)用一些 API,使用方法和引用變量一樣,不過變量為函數(shù),如 ${version()} 獲取版本。 ${expr(1+1)} 計(jì)算一個(gè)表達(dá)式。
調(diào)試技巧
一般流程:發(fā)現(xiàn)問題 - 定位問題 - 分析問題 - 解決問題。
- 撥打內(nèi)置的 APP 看現(xiàn)象縮小定位范圍,如 echo(9196)、playback(9664)
- 通過
uuid_debug_media <uuid> both on打開媒體調(diào)試開關(guān)(uuid 通過show channels查看) - 通過
console loglevel debug打開 FS debug 日志,檢查消息的到達(dá) - 檢查日志中掛機(jī)原因(Hangup Cause),一般 CALL_REJECTED 表示呼叫拒絕,可能是認(rèn)證錯(cuò)誤,USER_NOT_REGISTERED 說明對(duì)方未注冊(cè)。
- 經(jīng)過網(wǎng)關(guān)通過
bgapi originate sofia/gateway/gw1/Bob &echo“分段”查看網(wǎng)關(guān)后半段通信,bgapi 在后臺(tái)執(zhí)行線程,不阻塞控制臺(tái) -
sofia profile external siptrace on打開 external 的 profile siptrace,sofia global siptrace on打開所有 Profile 的。 -
sofia loglevel all 9打開 Sofia 底層協(xié)議棧的調(diào)試,換為 0 為關(guān)閉 - 使用 fs_cli 進(jìn)行如上操作,可以隨時(shí)關(guān)閉打開調(diào)試信息、固定消息內(nèi)容等操作,而不影響主進(jìn)程
- 抓包工具:tcpdump、wireshark、tshark(wireshark 的命令行版,參考)、ngrep(類似于 grep 在文本界面中方便),pcapsipdump(能將不同通話 IP 包存到不同的文件中,在通話量大時(shí)很好用)
-
tcpdump -nq -s 0 -A -vvv -i eth0 -w abc.pcap port 5060,-n、-q 表示不進(jìn)行域名翻譯及減少輸出內(nèi)容,-s 0 表示不限制包長,-A 表示以易讀的 ASCII 方式輸出,-v 表示詳細(xì)程度,v 越多越詳細(xì),-i eth0 表示指定網(wǎng)卡 etho,-w 為寫出到指定文件。對(duì)于搜索條件udp指定抓 udp 包,可以分析 RTP 流;host 1.2.3.4過濾 IP 地址;與用 and,或用 or。
originate 命令詳解
originate # 使用 FS 發(fā)起呼叫(默認(rèn)主叫號(hào)碼是 000000000)
-USAGE: <call url> <exten>|&<application_name>(<app_args>) [<dialplan>] [<context>] [<cid_name>] [<cid_num>] [<timeout_sec>]
- 同振,同時(shí)呼叫多個(gè)用戶,某個(gè)接聽另一個(gè)自動(dòng)掛斷:
originate user/1000,user/1001 &echo - 順振,呼叫某一個(gè)號(hào)碼,如果失敗呼叫下一個(gè):
originate user/1000|user/1001 &echo - call url 即呼叫字符串,格式
類型/參數(shù)/參數(shù),如user/1000,類型表示 Channel 的類型,不存在的類型會(huì)報(bào)錯(cuò)ERR CHAN_NOT_IMPLEMENTED - 第二個(gè)參數(shù)是分機(jī)號(hào)(exten)或者 &app。若是分機(jī)號(hào)時(shí),會(huì)轉(zhuǎn)入 Dialplan 去路由,路由的目的是查找到 enten
-
<dialplan>第三個(gè)參數(shù)是 Dialplan 的類型,如果不設(shè)置默認(rèn)是 XML -
<context>是 Dialplan 的 Context,對(duì)于 inlineDialplan 可忽略 -
<cid_name> <cid_num>是主叫名稱 和 主叫號(hào)碼(CallID Number),用于界面及 FROM 頭中顯示 -
<timeout_sec>是不回 100 Trying 的超時(shí)時(shí)間。 - originate 命令是阻塞的,可以在前方加上使用
bgapi轉(zhuǎn)為后臺(tái)執(zhí)行。若已經(jīng)發(fā)生阻塞:- 可以用 fs_cli 執(zhí)行
show channels查到 uuid,然后用uuid_kill <uuid>結(jié)束此呼叫。 - 或用
hupup掛斷所有電話。
- 可以用 fs_cli 執(zhí)行
- 命令中使用通道變量
originate {var1=1}{var2=2}user/1000 &echo,細(xì)節(jié)略。 - 忽略早期媒體的影響用
originate {ignore_early_media=true}sofia/gateway/gw/13800000000 &playback(/a.wav),因?yàn)?originate 命令是受到媒體指令就返回,如 183 或 200。由于軟電話會(huì)回復(fù) 180 而不是 183,183 相當(dāng)于攜帶媒體的 180,而在 PSTN 場景下一般都是回復(fù) 183 的。加入此參數(shù)后可以忽略 Early Media 對(duì)我們呼叫的影響。 -
originate user/1000 &bridge(user/1001)流程:建立 channel 然后呼叫 user/1000,1000 接聽后執(zhí)行 bridge,bridge 再建立一個(gè) channel 并呼叫 user/1001。此時(shí)雙方在信令上建立了橋接關(guān)系;在 1001 接聽后,媒體也會(huì)被橋接起來,進(jìn)入正常通話。
實(shí)際上,bridge 和 oiginate 底層用的同一個(gè)函數(shù)實(shí)現(xiàn),偽代碼是
originate(session, new_session, dial_str)差別在于 originate 調(diào)用函數(shù)是 session 字段為 null。
- 上方用 bridge 的邏輯中,是先撥通 a-leg 后再建立 b-leg 的,如果 b-leg 回的是 183 則媒體流正常轉(zhuǎn)發(fā)到 a-leg 中,若為 180 則由于無媒體流 a-leg 聽不到任何聲音,為了解決這個(gè)問題,可以讓 FS 回收一個(gè)假的回鈴音,方法:1)設(shè)置
{transfer_ringback=local_stream://moh}變量,此變量控制在 b-leg 回復(fù) 180 時(shí)開始播放聲音。2)在 1 的基礎(chǔ)上再加{instant_ringback=true}變量,可以讓 bridge 立即播放回鈴音,而不等待 180。
呼叫的完整邏輯
假設(shè) 1000 呼叫 1001
- 1000 發(fā)送 INVITE 到達(dá) mod_sofia 的 inernal Profile(
conf/sip_profiles/internal.xml,通過 5060 都是先到這里) - FS 收到后立即返回 100,由于 internal.xml 配置了
auth-calls=true所以會(huì)進(jìn)行鑒權(quán)(使用 Digest Auth),一般首次會(huì)鑒權(quán)失敗,所以回復(fù) 401 - UAC(即1000)重新發(fā)送帶鑒權(quán)信息的 INVITE 到 internal Profile(UAS)
- UAS 收到后,將鑒權(quán)信息提交到上層 FS 代碼,F(xiàn)S 通過 Directory(用戶目錄)找到相應(yīng)用戶信息,并根據(jù)配置的密碼鑒權(quán)(失敗 403)
- 鑒權(quán)通過,F(xiàn)S 通過 user_context 配置項(xiàng)找到應(yīng)該進(jìn)入哪個(gè)路由。如 1000.xml 中配的 user_context 為 default,則進(jìn)入
conf/dialplan/default.xml。(已經(jīng)進(jìn)入路由階段) - Dialplan 會(huì)查到 1001 用戶,找到匹配的 Extension 執(zhí)行里面的 action,action 有 bridge 命令及 data,所以執(zhí)行
bridge <data>,此時(shí)會(huì)再次查 Directory(用戶目錄)找到 1001 的配置信息 - 找到 1001 的 dial-string 配置項(xiàng),此項(xiàng)會(huì)配置在
conf/directory/default.xml中(由于此域下所有用戶的規(guī)則一樣,所以放在這里),其中 sofia_contact 這個(gè) API 會(huì)查找數(shù)據(jù)庫,找到 1001 的實(shí)際注冊(cè) Contact 地址,返回真正的呼叫字符串。(如通過sofia_contact 1000可快速查看sofia/internal/sip:1000@10.0.2.15:63757;ob) - 當(dāng)找到 dial-string 后,F(xiàn)S 會(huì)另外啟動(dòng)一個(gè)會(huì)話給 1001 發(fā)送 INVITE 請(qǐng)求
- 如果 1001 摘機(jī)(接聽),則 1001 向 FS 回送 200 OK,F(xiàn)S 再向 1000 回送 200 OK,通話開始。
總結(jié)主流程:1000 Invite -> sofia profile -> FS context -> dialplan -> action (bridge 1001) -> invite 1001。
external.xml 配置(5080 會(huì)走這里)
auth-calls 為 false,所以不進(jìn)行鑒權(quán)
context=public 其中也沒有每一個(gè) user 上配置的 user_context(internal 中也有 context=public 但走 user_context)
FS GUI
圖形化界面實(shí)現(xiàn)一般有兩種方式:
- 通過界面提供的操作方式修改 FS XML 配置文件,及 reloadxml 等操作使之生效
- 通過 http 服務(wù)器給 FS 提供 XML
如:
- FusionPBX
- blue.box
- FreeSWITCH Portal