• <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í)戰》:執行長(cháng)期運行的嵌入式腳本Lua語(yǔ)言例子

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


      眾所周知,FreeSWITCH中可以使用嵌入式的腳本語(yǔ)言javascript、lua等來(lái)控制呼叫流程。而更復雜一點(diǎn)操作可能就需要使用Event Socket了。其實(shí)不然,嵌入式的腳本也可以一直運行,并可以監聽(tīng)所有的Event,就像使用Event Socket起一個(gè)單獨的Daemon一樣。

      這里我們以lua為例來(lái)講一下都有哪些限制以及如何解決。

      首先,在控制臺或fs_cli中執行一個(gè)Lua腳本有兩種方式,lua和luarun。二者的不同就是lua是在當前線(xiàn)程中運行的,所以,它會(huì )阻塞;而luarun會(huì )spawn一個(gè)新的線(xiàn)程,不會(huì )阻塞當前的線(xiàn)程執行。

      另外,你也可以寫(xiě)到lua.conf配置文件中,這樣它就能隨FreeSWITCH一起啟動(dòng)。

     <param name="startup-script" value="gateway_report.lua"/>

      腳本后面可以加參數,如 luarun test.lua arg1 arg2,在腳本中,就可以通過(guò)argv[1], argv[2]來(lái)獲得參數的值。而argv[0]是腳本的名字。

      如果要讓腳本一直運行,腳本中必須有一個(gè)無(wú)限循環(huán)。你可以這樣做:

    while true do
      -- Sleep for 500 milliseconds
      freeswitch.msleep(500);
      freeswitch.consoleLog("info", "blah...");
    end

      但這樣的腳本是無(wú)法終止的,由于FreeSWITCH使用swig支持這些嵌入式語(yǔ)言,而有些語(yǔ)言沒(méi)有退出機制,所以,所有語(yǔ)言的退出機制都沒(méi)有在FreeSWITCH中實(shí)現,即使unload相關(guān)的語(yǔ)言模塊也不行,也是因為如此,為了避免產(chǎn)生問(wèn)題,所有語(yǔ)言模塊也都不能unload。

      另外,使用freeswitch.msleep() 也不安全,Wiki上說(shuō): Do not use this on a session-based script or bad things will happen。

      既然是長(cháng)期運行的腳本,那,為什么為停止呢?是的,大部分時(shí)間你不需要,但,如果你想修改腳本,總不會(huì )每次都重啟FreeSWITCH吧?尤其是在調試的時(shí)候。

      那,還有別的辦法嗎?

      我們可以使用事件機制構造另一個(gè)循環(huán):

    con = freeswitch.EventConsumer("all");                                                                        
    for e in (function() return con:pop(1) end) do
      freeswitch.consoleLog("info", "event\n" .. e:serialize("xml"));
    end

      上面的代碼中,con被初始化成一個(gè)事件消費者。它會(huì )一直阻塞并等待FreeSWITCH發(fā)出一個(gè)事件,并打印該事件的XML表示。當然,事件總會(huì )有的。如每個(gè)電話(huà)初始化、掛機等都會(huì )有相應的事件。除此之外,FreeSWITCH內部也會(huì )毎20秒發(fā)出一個(gè)heartbeat事件,這樣你就可以定時(shí)執行一些任務(wù)。

      當然如果使用 con:pop(0)也可以變成無(wú)阻塞的,但你必須在循環(huán)內部執行一些sleep()以防止腳本占用太多的資源。

      通過(guò)這種方法,你應該就能想到辦法讓腳本退出了。那就是,另外執行一個(gè)腳本觸發(fā)一個(gè)custom的事件,當該腳本監測到特定的custom事件后退出。當然你也可以不退出,比方說(shuō),打印一些信息以用于調試。

      我寫(xiě)了一個(gè)gateway_report.lua腳本。就用了這種技術(shù)。思路是:監聽(tīng)所有事件。如果收到hangup,則判斷是通過(guò)哪個(gè)gateway出去的,并計算一些統計信息。如果需要保存這些信息,可以有以下幾種方式:

    1. fire_event,即觸發(fā)另一個(gè)事件,這樣,如果有其它程序監聽(tīng),就可以收到這個(gè)事件,從而可以進(jìn)行處理,如存入數據庫等。
    2. http_post,發(fā)一個(gè)HTTP post請求到一個(gè)HTTP server,HTTP server接收到請求后進(jìn)行下一步處理。其中,http_post是無(wú)阻塞的,以提高效率,即只發(fā)請求,而不等待處理結果。
    3. db,可以通過(guò)luasql直接寫(xiě)到數據庫,未完全實(shí)現
    4. 當然你也可以直接通過(guò)io.open寫(xiě)到一個(gè)本地文件,未實(shí)現...

      由于這種腳本會(huì )在FreeSWITCH內部執行,需要消耗FreeSWITCH的資源,因此,在大話(huà)務(wù)量(確切來(lái)說(shuō)是“大事件量”)的情況下還是應該用Event Socket。

    分享到: 收藏

    專(zhuān)題

    亚洲精品网站在线观看不卡无广告,国产a不卡片精品免费观看,欧美亚洲一区二区三区在线,国产一区二区三区日韩 乡宁县| 常州市| 天水市| 鄂尔多斯市| 扶沟县| 竹溪县| 清新县| 镇坪县| 静安区| 保靖县| 沿河| 通榆县| 阳原县| 屏山县| 若尔盖县| 东阳市| 嘉荫县| 河西区| 甘谷县| 垣曲县| 南康市| 林西县| 万全县| 红桥区| 镇原县| 辽阳市| 平阳县| 九龙坡区| 荥经县| 双柏县| 定陶县| 山阴县| 阳春市| 西充县| 大埔区| 涿州市| 改则县| 贵南县| 离岛区| 郓城县| 论坛| http://444 http://444 http://444 http://444 http://444 http://444