• <strike id="fdgpu"><input id="fdgpu"></input></strike>
    <label id="fdgpu"></label>
    <s id="fdgpu"><code id="fdgpu"></code></s>

  • <label id="fdgpu"></label>
  • <span id="fdgpu"><u id="fdgpu"></u></span>

    <s id="fdgpu"><sub id="fdgpu"></sub></s>

    《FreeSWITCH: VoIP實(shí)戰》:FreeSWITCH 架構

    2012-08-14 14:02:18   作者:杜金房   來(lái)源:FreeSWITCH    評論:0  點(diǎn)擊:


      總體結構

      FreeSWITCH 由一個(gè)穩定的核心及外圍模塊組成。

      FreeSWITCH 使用線(xiàn)程模型來(lái)處理并發(fā)請求,每個(gè)連接都在單獨的線(xiàn)程中進(jìn)行處理。這不僅能提供最大強度的并發(fā),更重要的是,即使某路電話(huà)發(fā)生問(wèn)題,也只影響到它所在的線(xiàn)程,而不會(huì )影響到其它電話(huà)。FreeSWITCH 的核心非常短小精悍,這也是保持穩定的關(guān)鍵。所有其它功能都在外圍的模塊中。模塊是可以動(dòng)態(tài)加載(以及卸載)的,在實(shí)際應用中可以只加載用到的模塊。外圍模塊通過(guò)核心提供的 Public API 與核心進(jìn)行通信,而核心則通過(guò)回調機制執行外圍模塊中的代碼。

      核心

      FS Core 是 FreeSWITCH 的核心,它包含了關(guān)鍵的數據結構和復雜的代碼,但這些代碼只出現在核心中,并保持了最大限度的重用。外圍模塊只能通過(guò) API 調用核心的功能,因而核心運行在一個(gè)受保護的環(huán)境中,核心代碼都經(jīng)過(guò)精心的編碼和嚴格的測試,最大限度地保持了系統整體的穩定。

      核心代碼保持了最高度的抽象,因而它可以調用不同功能,不同協(xié)議的模塊。同時(shí),良好的 API 也使得編寫(xiě)不同的外圍模塊非常容易。

      數據庫

      FreeSWITCH 的核心除了使用內部的隊列、哈希表存儲數據外,也使用外部的 SQL 數據庫存儲數據。當前,系統的核心數據庫使用 SQLite,默認的存儲位置是 db/core.db 。 使用外部數據庫的好處是--查詢(xún)數據不用鎖定內存數據結構,這不僅能提供性能,而且降低了死鎖的風(fēng)險,保證了系統穩定。命令 show calls、show channels 等都是直接從數據庫中讀取內容并顯示的。由于 SQLite 會(huì )進(jìn)行讀鎖定,因此不建議直接讀取核心數據庫。

      系統對數據庫操作做了優(yōu)化,在高并發(fā)狀態(tài)時(shí),核心會(huì )盡量將幾百條 SQL 一齊執行,這大大提高了性能。但在低并發(fā)的狀態(tài)下執行顯得稍微有點(diǎn)慢,如一個(gè) channel 已經(jīng)建立了,但還不能在 show channels 中顯示;或者,一個(gè) channel 已經(jīng) destroy 了,還顯示在 show channels 中。但由于這些數據只用于查詢(xún),而不用于決策,所以一般沒(méi)什么問(wèn)題。

      除核心數據庫外,系統也支持使用 ODBC 方式連接其它數據庫,如 PostgreSQL、MySQL等。某些模塊,如 mod_sofia、mod_fifo等都有自己的數據庫(表)。如果在 *nix 類(lèi)系統上使用 ODBC,需要安裝 UnixODBC,并進(jìn)行正確的配置,如果編譯安裝的話(huà)還需要開(kāi)發(fā)包 unixodbc-devel(CentOS) 或 unixodbc-dev(Debian/Ubuntu)。由于 PostgreSQL、MySQL 等都是 Client-Server 的結構,因此,外部程序可以直接查詢(xún)數據(但需要清楚數據的準確性,可能會(huì )比 FreeSWITCH 核心中的數據有所滯后)。

      模塊

      FreeSWITCH 主要分為以下幾個(gè)部分:

      終點(diǎn)

      End Points 是終結 FreeSWITCH 的地方,也就是說(shuō)再往外走就超出 FreeSWITCH 的控制了。它主要包含了不同呼叫控制協(xié)議的接口,如 SIP, TDM 硬件,H323 以及 Google Talk 等。這使得 FreeSWITCH 可以與眾多不同的電話(huà)系統進(jìn)行通信。如,可以使用 mod_skypopen 與 Skype 網(wǎng)絡(luò )進(jìn)行通信。另外,前面也講過(guò),它還可以通過(guò) portaudio 驅動(dòng)本地聲卡,用作一個(gè)軟電話(huà)。

      撥號計劃

      Dialplan 主要是為了查找電話(huà)路由,主要的是 XML 描述的,但它也支持 Asterisk 格式的配置文件。另外它也持 ENUM 查詢(xún)。

      XML 接口

      XML Interface 支持多種獲取 XML 配置的方式,它可以是本地的配置文件,或從數據庫中讀取,甚至是一個(gè)能動(dòng)態(tài)返回 XML 的遠程 HTTP 服務(wù)器。

      編解碼器

      FreeSWITCH 支持最廣泛的 Codec,除了大多數 VoIP 系統支持的 G711、G722、G729、GSM 外,它還支持 iLBC,BV16/32、SILK、CELT等。它可以同時(shí)橋接不同采樣頻率的電話(huà),以及電話(huà)會(huì )議等。

      語(yǔ)音識別

      支持語(yǔ)音自動(dòng)識別(ASR)及文本-語(yǔ)音轉換(TTS)。

      文件格式

      支持不同的聲音文件格式,如 wav,mp3等。

      日志

      日志可以寫(xiě)到控制臺、日志文件、系統日志(syslog)以及遠程的日志服務(wù)器。

       嵌入式語(yǔ)言

       通過(guò) swig 包裝支持多種腳本語(yǔ)本語(yǔ)言控制呼叫流程,如 Lua、Javascript、Perl等。

      事件套接字

       使用 Event Socket 可以使用任何其它語(yǔ)言通過(guò) Socket 方式控制呼叫流程、擴展 FreeSWITCH 功能。

       目錄結構

       在 *nix 類(lèi)系統上,FreeSWITCH 默認的安裝位置是 /usr/local/freeswitch,在 Windows 上可能是 C:\freeswitch,目錄結構大致相同。

    bin         可執行程序
    db          系統數據庫(sqlite),FreeSWITCH 把呼叫信息存放到數據庫里以便在查詢(xún)時(shí)無(wú)需對核心數據結構加鎖
    htdocs      HTTP Web srver 根目錄
    lib         庫文件
    mod         可加載模塊
    run         運行目錄,存放 PID
    sounds      聲音文件,使用 playback() 時(shí)默認的尋找路徑
    grammar     語(yǔ)法
    include     頭文件
    log         日志,CDR 等
    recordings  錄音,使用 record() 時(shí)默認的存放路徑
    scripts     嵌入式語(yǔ)言寫(xiě)的腳本,如使用 lua()、luarun()、jsrun 等默認尋找的路徑
    storage     語(yǔ)言留言(Voicemail)的錄音
    conf        配置文件,詳見(jiàn)下節

       配置文件

       配置文件由許多 XML 文件組成。在系統裝載時(shí),XML解析器會(huì )將所有XML文件組織在一起,并讀入內存,稱(chēng)為XML注冊表。這種設計的好處在于其非常高的可擴展性。由于XML文檔本身非常適合描述復雜的數據結構,在 FreeSWITCH 中 就可以非常靈活的使用這些數據。并且,外部應用程序也可以很簡(jiǎn)單地生成XML,FreeSWITCH 在需要時(shí)可以動(dòng)態(tài)的裝載這些 XML。另外,系統還允許在某些 XML 節點(diǎn)上安裝回調程序(函數),當這些節點(diǎn)的數據變化時(shí),系統便自動(dòng)調用這些回調程序。

    使用 XML 唯一的不足就是手工編輯這些 XML 比較困難,但正如其作者所言,他絕對不是 XML 的粉絲,但這一缺點(diǎn)與它所帶來(lái)的好處相比是微不足道的。而且,將來(lái)也許會(huì )有圖形化的配置工具,到時(shí)候只所高級用戶(hù)會(huì )去看這些XML了。

       目錄結構

       配置文件的的目錄結構如下(其中結尾有 “/” 的為目錄):

    autoload_configs/
    dialplan/
    directory/
    extensions.conf
    freeswitch.xml
    fur_elise.ttml
    jingle_profiles/
    lang/
    mime.types
    notify-voicemail.tpl
    sip_profiles/
    tetris.ttml
    vars.xml
    voicemail.tpl
    web-vm.tpl

       其中最重要的是 freeswitch.xml,就是它將所有配置文件“粘”到一起。只要有一點(diǎn) XML 知識,這些配置是很容易看懂的。其中,X-PRE-PROCESS標簽稱(chēng)為預處理命令,它用來(lái)設置一些變量和裝入其它配置文件。在 XML 加載階段,FreeSWITCH 的 XML 解析器會(huì )先將預處理命令進(jìn)行展開(kāi),生成一個(gè)大的 XML 文件 log/freeswitch.xml.fsxml。該文件是一個(gè)內存鏡像,用戶(hù)不應該手工編輯它。但它對調試非常有用,假設你不慎弄錯了某個(gè)標簽,又不知道它在哪個(gè)地方,FreeSWITCH 在加載時(shí)就報 XML 的某一行出錯,在該文件中就行容易找到。

       整個(gè)XML文件分為幾個(gè)重要的部分:configuration (配置)、dialplan (撥號計劃)、directory(用戶(hù)目錄)及phrase(分詞)。每一部分又分別裝入不同的 XML。

        小知識:XML

    XML由標簽(Tag)和屬性構成。<tag> 和 </tag>組成一對標簽,如果該標簽有相關(guān)屬性,剛以
    <tag attr="value"></tag> 形式指定。有些標簽無(wú)須配對,則必須以 “/>”關(guān)閉該標簽定義,
    如<other\_tag attr="value"/>。

    freeswitch.xml
    <?xml version="1.0"?>
    <document type="freeswitch/xml">
        <!-- #comment 這是一個(gè)配置文件,本行是注釋 -->

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

        <section name="configuration" description="Various Configuration">
            <X-PRE-PROCESS cmd="include" data="autoload_configs/*.xml"/>
        </section>
    </document>

       上面是一個(gè)精減了的 freeswitch.xml。它的根是 document,在 document 中,有許多 section,每個(gè) section 都對應一部分功能。其中有兩個(gè) X-PRE-PROCESS 預處理指令,它們的作用是將 data 參數指定的文件包含(include)到本文件中來(lái)。由于它是一個(gè)預處理指令,FreeSWITCH 在加載階段只對其進(jìn)行簡(jiǎn)單替換,并不進(jìn)行語(yǔ)法分析,因此,對它進(jìn)行注釋是沒(méi)有效果的,這是一個(gè)新手常犯的錯誤。假設 vars.xml 的內容如下,它是一個(gè)合法的 XML:

    <!-- this is vars.xml -->
    <var>xxxxx</var>

    若你在調試階段想把一條 X-PRE-PROCESS 指令注釋掉:

    <!-- <X-PRE-PROCESS cmd="include" data="vars.xml"/> -->

       當 FreeSWITCH 預處理時(shí),還沒(méi)有到達 XML 解析階段,也就是說(shuō)它還不認識 XML 注釋語(yǔ)法,而僅會(huì )機械地將預處理指令替換為 vars.xml 里的內容:

    <!-- <!-- this is vars.xml -->
    <var>xxxxx</var> -->                                                 

       由于 XML 的注釋不能嵌套,因此便產(chǎn)生錯誤的XML。解決辦法是破壞掉 X-PRE-PROCESS 的定義,如我常用下面兩種方法:

    <xX-PRE-PROCESS cmd="include" data="vars.xml"/>
    <XPRE-PROCESS cmd="include" data="vars.xml"/>

       由于 FreeSWITCH 不認識 xX-PRE-PROCESS 及 XPRE-PROCESS,因此它會(huì )忽略掉該行,相當于注釋掉了。

       vars.xml

       vars.xml 主要通過(guò) X-PRE-PROCESS 指令定義了一些全局變量。全局變量以 $${var} 表示,臨時(shí)變量以 ${var} 表示。有些變量是系統在運行時(shí)自動(dòng)獲取的,如默認情況下 $${base_dir}=/usr/local/freeswitch, $${local_ip_v4}=你機器的IP地址等。

       autoload_configs 目錄

       autoload_configs目錄下面的各種配置文件會(huì )在系統啟動(dòng)時(shí)裝入。一般來(lái)說(shuō)都是模塊級的配置文件,每個(gè)模塊對應一個(gè)。文件名一般以 模塊名.conf.xxml 方式命名。其中 modules.conf.xml 決定了 FreeSWITCH 啟動(dòng)時(shí)自動(dòng)加載哪些模塊。

        dialplan 目錄

       定義 XML 撥號計劃,我們會(huì )有專(zhuān)門(mén)的章節講解撥號計劃。

       directory 目錄

       它里面的配置文本決定了 FreeSWITCH 作為注冊服務(wù)器時(shí)哪些用戶(hù)可以注冊上來(lái)。FreeSWITCH 支持多個(gè)域(Domain),每個(gè)域可以寫(xiě)到一個(gè) XML 文件里。默認的配置包括一個(gè) default.xml,里面定義了 1000 ~ 1019 一共 20 個(gè)用戶(hù)。

       sip_profiles

       它定義了 SIP 配置文件,實(shí)際上它是由 mod_sofia 模塊在 autoload_configs/sofia.conf.xml 中加載的。但由于它本身比較復雜又是核心的功能,因此單列了一個(gè)目錄。我們將會(huì )在后面加以詳細解釋。

       XML 用戶(hù)目錄

       XML 用戶(hù)目錄決定了哪些用戶(hù)可以注冊到 FreeSWITCH 上。當然,SIP 并不要求一定要注冊才可以打電話(huà),但是用戶(hù)認證仍需要在用戶(hù)目錄中配置。

       用戶(hù)目錄的默認配置文件在 conf/directory/,系統自帶的配置文件為 default.xml(其中 dial-string 一行由于排版要求人工換行,實(shí)際上不應該有換行):

    <domain name="$${domain}">
      <params>
        <param name="dial-string" value="{presence_id=${dialed_user}@${dialed_domain}}
            ${sofia_contact(${dialed_user}@${dialed_domain})}"/>
      </params>

      <variables>
        <variable name="record_stereo" value="true"/>
        <variable name="default_gateway" value="$${default_provider}"/>
        <variable name="default_areacode" value="$${default_areacode}"/>
        <variable name="transfer_fallback_extension" value="operator"/>
      </variables>

    </domain>

       該配置文件決定了哪些用戶(hù)能注冊到 FreeSWITCH 中。一般來(lái)說(shuō),所有用戶(hù)都應該屬于同一個(gè) domain(除非你想使用多 domain,后面我們會(huì )有例子)。這里的 $${domain} 全局變量是在 vars.xml 中設置的,它默認是主機的 IP 地址,但也可以修改,使用一個(gè)域名。params 中定義了該 domain 中所有用戶(hù)的公共參數。在這里只定義了一個(gè) dial-string,這是一個(gè)至關(guān)重要的參數。當你在使用 user/user_name 或 sofia/internal/user_name 這樣的呼叫字符串時(shí),它會(huì )擴展成實(shí)際的 SIP 地址。其中 sofia_contact 是一個(gè) API,它會(huì )根據用戶(hù)的注冊地址擴展成相應的呼叫字符串。

       variables 則定義了一些公共變量,在用戶(hù)做主叫或被叫時(shí),這些變量會(huì )綁定到相應的 Channel 上形成 Channel Variable。

        在 domain 中還定義了許多組(group),組里面包含很多用戶(hù)(user)。

    <groups>
      <group name="default">
        <users>
          <X-PRE-PROCESS cmd="include" data="default/*.xml"/>
        </users>
      </group>
    </groups>              

       在這里,組名 default 并沒(méi)有什么特殊的意義,它只是隨便起的,你可以修改成任何值。在用戶(hù)標簽里,又使用預處理指令裝入了 default/ 目錄中的所有 XML 文件。你可以看到,在 default/ 目錄中,每個(gè)用戶(hù)都對應一個(gè)文件。

       你也可以定義其它的用戶(hù)組,組中的用戶(hù)并不需要是完整的 XML 節點(diǎn),也可以是一個(gè)指向一個(gè)已存在用戶(hù)的“指針”,如下圖,使用 type="pointer" 可以定義指針。

      <group name="sales">
        <users>
          <user id="1000" type="pointer"/>
          <user id="1001" type="pointer"/>
          <user id="1002" type="pointer"/>
        </users>
      </group>

       雖然我們這里設置了組,但使用組并不是必需的。如果你不打算使用組,可以將用戶(hù)節點(diǎn)(users)直接放到 domain 的下一級。但使用組可以支持像群呼、代接等業(yè)務(wù)。使用 group_call 可以同時(shí)或順序的呼叫某個(gè)組的用戶(hù)。

       實(shí)際用戶(hù)相關(guān)的設置也很直觀(guān),下面顯示了 alice 這個(gè)用戶(hù)的設置:

    <user id="alice">
      <params>
        <param name="password" value="$${default_password}"/>
        <param name="vm-password" value="alice"/>
      </params>
      <variables>
        <variable name="toll_allow" value="domestic,international,local"/>
        <variable name="accountcode" value="alice"/>
        <variable name="user_context" value="default"/>
        <variable name="effective_caller_id_name" value="Extension 1000"/>
        <variable name="effective_caller_id_number" value="1000"/>
        <variable name="outbound_caller_id_name" value="$${outbound_caller_name}"/>
        <variable name="outbound_caller_id_number" value="$${outbound_caller_id}"/>
        <variable name="callgroup" value="techsupport"/>
      </variables>
    </user>

       由上面可以看到,實(shí)際上 params 和 variables 可以出現在 user 節點(diǎn)中,也可以出現在 group 或 domain 中。 當它們有重復時(shí),優(yōu)先級順序為 user,group,domain。

       當然,用戶(hù)目錄還有一些更復雜的設置,我們留待以后再做研究。

       呼叫流程及相關(guān)概念

       再復習一下,FreeSWITCH是一個(gè)B2BUA,我們還是以第四章中的圖為例: 

       主要呼叫流程有以下兩種:

       bob 向 FreeSWITCH 發(fā)起呼叫,FreeSWTICH 接著(zhù)啟動(dòng)另一個(gè) UA 呼叫 alice,兩者通話(huà);

       FreeSWITCH 同時(shí)呼叫 bob 和 alice,兩者接電話(huà)后 FreeSWITCH 將 a-leg 和 b-leg 橋接(bridge)到一起,兩者通話(huà)。

       其中第二種又有一種變種。如市場(chǎng)上有人利用上、下行通話(huà)的不對稱(chēng)性賣(mài)電話(huà)回撥卡獲取不正當利潤:bob 呼叫 FreeSWITCH,FreeSWITCH 不應答,而是在獲取 bob 的主叫號碼后直接掛機;然后 FreeSWITCH 回撥 bob;bob 接聽(tīng)后 FreeSWITCH 啟動(dòng)一個(gè) IVR 程序指示 bob 輸入 alice 的號碼;然后 FreeSWITCH 呼叫 Alice……

       在實(shí)際應用中,由于涉及回鈴音、呼叫失敗等,實(shí)際情況要復雜的多。

       Session 與 Channel

       對每一次呼叫,FreeSWITCH 都會(huì )啟動(dòng)一個(gè) Session(會(huì )話(huà),它包含SIP會(huì )話(huà),SIP會(huì )在每對UAC-UAS之間生成一個(gè) SIP Session),用于控制整個(gè)呼叫,它會(huì )一直持續到通話(huà)結束。其中,每個(gè) Session 都控制著(zhù)一個(gè) Channel(信道),Channel 是一對 UA 間通信的實(shí)體,相當于 FreeSWITCH 的一條腿(leg),每個(gè) Channel 都有一個(gè)唯一的 UUID。另外,Channel 上可以綁定一些呼叫參數,稱(chēng)為 Channel Variable(信道變量)。Channel 中可能包含媒體(音頻或視頻流),也可能不包含。通話(huà)時(shí),FreeSWITCH 的作用是將兩個(gè) Channel(a-leg 和 b-leg,通常先創(chuàng )建的或占主動(dòng)的叫 a-leg)橋接(bridge)到一起,使雙方可以通話(huà)。

       通話(huà)中,媒體(音頻或視頻)數據流在 RTP 包中傳送(不同于 SIP, RTP是另外的協(xié)議)。一般來(lái)說(shuō),Channel是雙向的,因此,媒體流會(huì )有發(fā)送(Send/Write)和接收(Receive/Read)兩個(gè)方向。

       回鈴音與 Early Media

    A  ------ |a 交換機 | ---X--- | 交換機 b| -------- B

       為了便于說(shuō)明,我們假定A與B不在同一臺服務(wù)器上(如在PSTN通話(huà)中可能不在同一座城市),中間需要經(jīng)過(guò)多級服務(wù)器的中轉。

       假設上圖是在 PSTN 網(wǎng)絡(luò )中,A 呼叫 B,B 話(huà)機開(kāi)始振鈴,A 端聽(tīng)回鈴音(Ring Back Tone)。在早期,B 端所在的交換機只給 A 端交換機送地址全(ACM)信號,證明呼叫是可以到達 B 的,A 端聽(tīng)到的回鈴音鈴流是由 A 端所在的交換機生成并發(fā)送的。但后來(lái),為了在 A 端能聽(tīng)到 B 端特殊的回鈴音(如“您撥打的電話(huà)正在通話(huà)中…” 或 “對方暫時(shí)不方便接聽(tīng)您的電話(huà)” 尤其是現代交換機支持各種個(gè)性化的彩鈴 - Ring Back Color Tone 等),回鈴音就只能由 B 端交換機發(fā)送。在 B 接聽(tīng)電話(huà)前,回鈴音和彩鈴是不收費的(不收取本次通話(huà)費。彩鈴費用一般是在 B 端以月租或套餐形式收取的)。這些回鈴音就稱(chēng)為 Early Media(早期媒體)。它是由 SIP 的183(帶有SDP)消息描述的。

       理論上講,B 接聽(tīng)電話(huà)后交換機 b 可以一直不向 a 交換機發(fā)送應答消息,而將真正的話(huà)音數據偽裝成 Early Media,以實(shí)現“免費通話(huà)”。

       Channel Variable

       在每一個(gè) Channel 上都可以設置好多 Variable,稱(chēng)為信道變量。FreeSWITCH 呼叫過(guò)程中,會(huì )根據這些變量控制 Channel 的行為。

       $${var} 與 ${var}

       ${var} 是在 dialplan、application 或 directory 中設置的變量,它會(huì )影響呼叫流程并且可以動(dòng)態(tài)的改變。而 $${var} 則是全局的變量,它僅在預處理階段(系統啟動(dòng)時(shí),或重新裝載 - reloadxml時(shí))被求值。后者一般用于設置一些系統一旦啟動(dòng)就不會(huì )輕易改變的量,如 $${domain} 或 $${local_ip_v4}等。所以,兩者最大的區別是,$${var} 只求值一次,而 ${var} 則在每次執行時(shí)求值(如一個(gè)新電話(huà)進(jìn)來(lái)時(shí))。

       $variable_xxxx

       你會(huì )發(fā)現,有些變量在顯示時(shí)(可以使用dp_tools 中的 info() 顯示,后面會(huì )講到)是以“variable_”開(kāi)頭的,但在實(shí)際引用時(shí)要去掉這開(kāi)頭的“variable_”。如“variable_user_name”,引用時(shí)要使用“${user_name}”。http://wiki.freeswitch.org/wiki/Channel_Variables#variable_xxxx 列舉了一些常見(jiàn)的變量顯示與引用時(shí)的對應關(guān)系。

       給 Variable 賦值

       在 dialplan 中,有兩個(gè)程序可以給 Variable 賦值:

    <action application="set" data="my_var=my_value"/>
    <action application="export" data="my_var=my_value"/>

    以上兩條命令都可以設置 my_var 變量的值為 my_value。不同的是 -- set 程序僅會(huì )作用于“當前”的 Channel (a-leg),而 export 程序則會(huì )將變量設置到兩個(gè) Channel (a-leg 和 b-leg)上,如果當時(shí) b-leg 還沒(méi)有創(chuàng )建,則會(huì )在創(chuàng )建時(shí)設置。另外,export 還可以只將變量設置到 b-leg 上:

    <action appliction="export" data="nolocal:my_var=my_value"/>

    在實(shí)際應用中,如果 a-leg 上已經(jīng)有一些變量的值(如 var1、var2、var3),而想同時(shí)把這些變量都復制到 b-leg 上,可以使用以下幾種辦法:

    <action application="export" data="var1=$var1"/>
    <action application="export" data="var2=$var2"/>
    <action application="export" data="var3=$var3"/>

    或者使用如下等價(jià)的方式:

    <action application="set" data="export_vars=var1,var2,var3">

    所以,其實(shí) set 也具有能往 b-leg 上賦值的能力,其實(shí),它和 export 一樣,都是操作 export_vars 這個(gè)特殊的變量。

    取消 Variable 定義
    取消 Variable 定義只需對它賦一個(gè)特殊的值_undef_”:

    <action application="set" data="var1=_undef_">

    截取 Variable 的一部分
    可以使用特殊的語(yǔ)法取一個(gè) Variable 的子串,格式是“${var:位置:長(cháng)度}”。其中 “位置” 從 0 開(kāi)始計烽,若為負數則從字符串尾部開(kāi)始計數;如果“長(cháng)度”為 0 或小于 0,則會(huì )從當前“位置”一直取到字符串結尾(或開(kāi)頭,若“位置”為負的話(huà))。例如 var 的值為 1234567890,那么:

    ${var}      = 1234567890
    ${var:0:1}  = 1
    ${var:1}    = 234567890
    ${var:-4}   = 7890
    ${var:-4:2} = 78
    ${var:4:2}  = 56

       小結

        本章描述了 FreeSWITCH 的架構。到這里,讀者應該對 FreeSWITCH 有了一個(gè)總體的了解。我們也提到了一些基本元素和概念,簡(jiǎn)單介紹了配置文件的基本結構,由于脫離了實(shí)際單講配置會(huì )比較抽象,因此,我們把具體的配置也寫(xiě)到后面的章節里,即,用到時(shí)再說(shuō)。


     

    分享到: 收藏

    專(zhuān)題

    亚洲精品网站在线观看不卡无广告,国产a不卡片精品免费观看,欧美亚洲一区二区三区在线,国产一区二区三区日韩 花莲县| 浏阳市| 济宁市| 丹阳市| 偃师市| 临沭县| 南康市| 灵石县| 曲水县| 越西县| 凤阳县| 平安县| 宜丰县| 那曲县| 武城县| 武宣县| 乌恰县| 大余县| 潮安县| 武宣县| 黔江区| 洛南县| 江城| 遂溪县| 定结县| 博客| 镇平县| 宁都县| 辽源市| 通化市| 宕昌县| 昭通市| 崇州市| 靖安县| 朔州市| 泽普县| 神农架林区| 仙居县| 静乐县| 和平县| 达日县| http://444 http://444 http://444 http://444 http://444 http://444