freeSwitch入門

閱讀《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)完成。

image.png

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)。

image.png

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

image.png

啟動(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
  • 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>
image.png
  • 注意執(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 掛斷所有電話。
  • 命令中使用通道變量 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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容