中文字幕无码久久精品,13—14同岁无码A片,99热门精品一区二区三区无码,菠萝菠萝蜜在线观看视频高清1

 首頁 > 新聞 > 專家觀點(diǎn) >

《FreeSWITCH: VoIP實(shí)戰(zhàn)》:撥號計(jì)劃- Dialplan

2012-08-17 15:51:59   作者:杜金房   來源:CTI論壇   評論:0  點(diǎn)擊:


hash 是內(nèi)存中的哈希表數(shù)據(jù)結(jié)構(gòu)。它可以設(shè)置一個鍵-值對(Key-Value pair)。如,上面最后一行上向 ${domain_name}-last_dial_ext 這個哈希表中插入 global 這么一個鍵,它的值是 ${uuid},就是本 Channel 的唯一標(biāo)志。

不管是上面的 set, 還是 hash,都是保存一些數(shù)據(jù)為后面做準(zhǔn)備的。

<action application="set" data="called_party_callgroup=${user_data(${dialed_extension}@${domain_name} var callgroup)}"/>
<!--<action application="export" data="nolocal:sip_secure_media=${user_data(${dialed_extension}@${domain_name} var sip_secure_media)}"/>-->

這一行默認(rèn)是注釋掉的,因此不起作用。 nolocal 的作用我們已前也講到過,它告訴 export 只將該變量設(shè)置到 b-leg 上,而不要設(shè)置到 a-leg 上。

<action application="hash" data="insert/${domain_name}-last_dial/${called_party_callgroup}/${uuid}"/>

還是 hash.

<action application="bridge" data="{sip_invite_domain=$${domain}}user/${dialed_extension}@${domain_name}"/>

bridge 是最關(guān)鍵的部分。其實(shí)上面除 bridge 以外的 action 都可以省略,只是會少一些功能。

  回憶一下第四章中的內(nèi)容。用戶 1000 其實(shí)是一個 SIP UA(UAC),它向 FreeSWITCH(作為UAS) 發(fā)送一個 INVITE 請求。然后 FreeSWITCH 建立一個 Channel,從 INVITE 請求中找到被叫號碼(destination_number=1001),然后在 Dialplan 中查找 1001 就一直走到這里。

  bridge 的作用就是把 FreeSWITCH 作為一個 SIP UAC,再向 1001 這個 SIP UA(UAS)發(fā)起一個 INVITE 請求,并建立一個 Channel。這就是我們的 b-leg。1001 開始振鈴,bridge 把回鈴音傳回到 1000,因此,1000 就能聽到回鈴音(如果 1001 有自己的回鈴音,則 1000 能聽到,否則,將會聽到默認(rèn)的回鈴音 ${us-ring})。

   當(dāng)然,實(shí)際的情況比我們所說的要復(fù)雜,因?yàn)樵诤艚兄。FreeSWITCH 首先要查找 1001 這個用戶是否已經(jīng)注冊,否則,會直接返回 USER_NOT_REGISTERED,而不會建立 b-leg。

  bridge 的參數(shù)是一個標(biāo)準(zhǔn)的呼叫字符串(Dial string),以前我們也講到過。domain 和 domain_name 都是預(yù)設(shè)的變量,默認(rèn)就是服務(wù)器的 IP 地址。user 是一個特殊的 endpoint,它指本地用戶。所以,呼叫字符串翻譯出來就是(假設(shè) IP 是 192.168.7.2):

{sip_invite_domain=192.168.7.2}user/1001@192.168.7.2

  其中,“{ }”里是設(shè)置變量,由于 bridge 在這里要建立 b-leg,因此,這些變量只會建立在 b-leg 上。與 set 是不一樣的。但它等價于下面的 export :

<action application="export" value="nolocal:sip_invite_domain=192.168.7.2"/>
<action application="bridge" value="user/1001@192.168.7.2"/>

  好了,到此為止電話路由基本上就完成了,我們已經(jīng)建立了 1000 到 1001 之間的呼叫,就等 1001 接電話了。接下來會有幾種情況:

  • 被叫應(yīng)答
  • 被叫忙
  • 被叫無應(yīng)答
  • 被叫拒絕
  • 其它情況 ...

  我們先來看一下被叫應(yīng)答的情況。1001 接電話,與 1000 暢聊。在這個時候 bridge 是阻塞的,也就是說,bridge 這個 APP 會一直等待兩者掛機(jī)(或者其它錯誤)后才返回,才有可能繼續(xù)執(zhí)行下面的 Action。好吧,讓我們休息一下,等他們兩個聊完吧。

  最后,無論哪一方掛機(jī),bridge 就算結(jié)束了。如果 1000 先掛機(jī),則 FreeSWITCH 會將掛機(jī)原因發(fā)送給 1001,一般是 NORMAL_RELEASE(正常釋放)。同時 Dialplan 就再也沒有往下執(zhí)行的必要的,因此會發(fā)送計(jì)費(fèi)信息,并銷售 a-leg 。

   如果 1001 先掛機(jī),b-leg 就這樣消失了。但 a-leg 依然存在,所以還有戲看。

   b-leg 會將掛機(jī)原因傳到 a-leg。在 a-leg 決定是否繼續(xù)往下執(zhí)行之前,會檢查一些變量。其中,我們在前面設(shè)置了 hangup_after_bridge=true。它的意思是,如果 bridge 正常完成后,就掛機(jī)。因此,a-leg 到這里就釋放了,它的掛機(jī)原因是參考 b-leg 得出的。

   但由于種種原因 1001 可能沒接電話。1001 可能會拒接(CAlL_REJECTED,但多數(shù) SIP UA都會在用戶拒接時返回 USER_BUSY)、忙(USER__BUSY)、無應(yīng)答(NO_ANSWER 或 NO_USER_RESPONSE)等。出現(xiàn)這些情況時,F(xiàn)reeSWITCH 認(rèn)為這是不成功的 bridge,因此 hangup_after_bridge 變量就不管用了。這時候它會檢查另一個變量 continue_on_fail。由于我們上面設(shè)置的 continue_on_fail=true,因此在 bridge 失敗(fail)后會繼續(xù)執(zhí)行下面的 Action。

  這里值得說明的是,通過給 continue_on_fail 不同的值,可以決定在什么情況下繼續(xù)。如:

  <action application="set" data="continue_on_fail=USER_BUSY,NO_ANSWER"/>

  將只在用戶忙和無應(yīng)答的情況下繼續(xù)。其它的值有:NORMAL_TEMPORARY_FAILURE(臨時故障)、TIMEOUT(超時,一般時SIP超時)、NO_ROUTE_DESTINATION(沒有路由)等。

   <action application="answer"/>

  最后,無論什么原因?qū)е?bridge 失。ㄎ覀儧]法聯(lián)系上 1001),我們都決定繼續(xù)執(zhí)行. 首先 FreeSWITCH 給 1000 回送應(yīng)答消息。這時非常重要的。

<action application="sleep" data="1000"/>
<action application="voicemail" data="default ${domain_name} ${dialed_extension}"/>

   接下來,暫停一秒,并轉(zhuǎn)到 1001 的語音信箱。語音信箱的知識等我們以后再講。另外,默認(rèn)配置中使用的是 loopback endpoint 轉(zhuǎn)到 voicemail,為了方便說明,我直接改成了 voicemail。

   回聲

  沒什么好解釋的,如果撥 9196,就能聽到自己的回聲

<extension name="echo">
    <condition field="destination_number" expression="^9196$">
        <action application="answer"/>
        <action application="echo"/>
    </condition>
</extension>

  延遲回聲

  與 echo 基本一樣,但回聲會有一定延遲,5000 是毫秒數(shù)。

<extension name="delay_echo">
    <condition field="destination_number" expression="^9195$">
        <action application="answer"/>
        <action application="delay_echo" data="5000"/>
    </condition>
</extension>

  內(nèi)連撥號計(jì)劃 - Inline Dialplan

  首先,Inline dialplan 與上面我們講的 Action 中的 inline 參數(shù)是不同的。

   XML Dialplan 支持非常豐富的功能,但在測試或編寫程序時,我們經(jīng)常用到一些臨時的,或者是很簡單的 Dialplan,如果每次都需要修改 XML,不僅麻煩,而且執(zhí)行效率也會有所折扣。所以,我們需要一種短小、輕便的 Dialplan 以便更高效地完成任務(wù)。而且,通過使用 Inline dialplan,也可以很方便的在腳本中生成動態(tài)的 Dialplan 而無需使用復(fù)雜的 reloadxml 以及 mod_xml_curl 技術(shù)等。

  與 XML Dialplan 不同,它沒有 Extension,也沒有復(fù)雜的 Condition。而只是象 XML Dialplan中那樣簡單的 Action 的疊加。它有一種很緊湊的語法格式:

  app1:arg1,app2:arg2,app3:arg3

   從語法可以看出,它只是多個 APP 以及參數(shù)組成的字符串,APP之間用逗號分隔,而APP與參數(shù)之間用冒號分隔。如果參數(shù)中有空格,則整個字符串都需要使用單引號引起來。在我們上面的例子中,你通過撥打 9196 來找到對應(yīng)的 XML dialplan,在這里,我們可以直接在命令行上寫出對應(yīng)的 inline 形式:

originate user/1000 echo inline
originate user/1000 answer,echo inline

   讀到這里,你可能要問,它與“originate user/1000 &echo” 有什么區(qū)別呢?在回答這個問題之前,我們需要先看一下 originate 的語法:

originate <call_url> <exten>|&<application_name>(<app_args>)
[<dialplan>] [<context>] [<cid_name>] [<cid_num>] [<timeout_sec>]

  首先,它的第一個參數(shù)是呼叫字符串, 第二個參數(shù)可以是 & 加上一個 APP,APP的參數(shù)要放到 ( ) 里,如:

originate user/1000 &echo
originate user/1000 &playback(/tmp/sound.wav)
originate user/1000 &record(/tmp/recording.wav)

  這是最簡單的形式,首先,originate 會產(chǎn)生一個 Channel,它會呼叫 user/1000 這個用戶。請注意,這是一個單腿的通話,因此只有一個 Channel。但一個 Channel 有兩端,一端是 1000 這個用戶,另一端是 FreeSWITCH。在 user/1000 接電話后(嚴(yán)格說是收到它的 earlymedia 后),F(xiàn)reeSWITCH 即開始在該 Channel 上執(zhí)行 & 后面的 APP。但這種形式只能執(zhí)行一個 APP,如果要執(zhí)行多個,就需要將電話轉(zhuǎn)入 Dialplan:

originate user/1000 9196
originate user/1000 9196 XML default

  上面兩個命令是一樣的。它的作用是,在 user/1000 接電話后,電話的另一端(也就是 FreeSWITCH)需要對電話進(jìn)行路由,在這里,它要將電話路由到 9196 這個 Extension 上,第一條命令由于沒有指定是哪個 Dialplan,因此它會在默認(rèn)的 XML Dialplan 中查找,同時,XML Dialplan 需要一個 Context, 它默認(rèn)就是 default。它的效果是跟你直接用軟電話撥打 9196 這個分機(jī)一樣的(所不同的是呼叫的方向問題,這種情況相當(dāng)于回?fù)埽?/p>

  當(dāng)然,除此之外,它還可以加一些可選的參數(shù),用于指定來電顯示(Caller ID)的名字(cid_name)和號碼(cid_number),以及超時的秒數(shù),如:

originate user/1000 9196 XML default 'Seven Du' 9196 30

   當(dāng)然,我們這里學(xué)了 Inline Dialplan,所以你也可以這樣用:

originate user/1000 echo inline

  請注意,在 XML Dialplan 中, 9196 是一個分機(jī)號,而 Inline 中的 echo 則是一個 APP,當(dāng)然你也可以順序執(zhí)行多個 APP:

originate user/1000 answer,playback:/tmp/pleace_leave_a_message.wav,record:/tmp/recording.wav inline
originate user/1000 playback:/tmp/beep.wav,bridge:user/1001 inline

  有時候,APP 的參數(shù)中可能會有逗號,因而會與默認(rèn)的 APP 間的逗號分隔符相沖突,以下的 m 語法形式將默認(rèn)的逗號改為 ^ 分隔(以下三行實(shí)際上為一行)。

originate user/1000
'm:^:playback/tmp/beep.wav^bridge:
{ignore_early_media=true,originate_caller_id_number=1000}user/1001'

當(dāng)然你也可以用在任何需要 Dialplan 的地方,如(以下兩行實(shí)為一行)

uuid_transfer 2bde6598-0f1a-48fe-80bc-a457a31b0055
'set:test_var=test_value,info,palyback:/tmp/beep.wav,record:/tmp/recording.wav'

  除此之外,還有其它的 Dialplan 形式,我們在這里就不再介紹了,要查看你的系統(tǒng)支持多少 Dialplan,使用如下命令:

freeswitch@seven-macpro.local> show dialplan

type,name,ikey
dialplan,LUA,mod_lua
dialplan,XML,mod_dialplan_xml
dialplan,asterisk,mod_dialplan_asterisk
dialplan,enum,mod_enum
dialplan,inline,mod_dptools

分享到: 收藏

專題