小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

《FreeSWITCH: VoIP實戰(zhàn)》:嵌入式腳本

 hginvent 2013-12-13

什么是嵌入式腳本?

  其實前面我們學到的 XML dialplan 已經(jīng)體現(xiàn)了其非凡的配置能力,它配合 FreeSWITCH 提供的各種 App 也可以認為是一種腳本。當然,畢竟 XML 是一種描述語言,功能還有限。FreeSWITCH 通過嵌入其它語言的解析器支持很多流行的編程語言。

  一般來說,編程語言分為兩種:編譯型語言(如C)和解釋型語言(如 javascript,perl 等)。使用解釋型語言編寫出來的腳本不需要編譯,因而非常靈活方便。典型地,F(xiàn)reeSWITCH 支持的語言有:

  • Lua
  • Javascript
  • Python
  • Perl
  • Java

  其它腳本語言如 Php, Ruby 以前是支持的,由于它們有內(nèi)存及性能問題,且沒有志愿者維護,現(xiàn)在已經(jīng)被列為 Unsupported 了。

  應用場景

  一般來說,這些嵌入式腳本主要用于寫 IVR,即主要用來控制一路通話的呼叫流程。雖然它們也可以控制多路通話(在后面我們也會講到這樣的例子,但這不是他們擅長的功能。

  當然,這里說的一路通話不是說它們只能控制唯一一路通話。以 Lua 為例,你可以把呼叫路由到一個 lua 腳本,當有電話進來時,F(xiàn)reeSWITCH 會為每一路通話啟動一個線程,控制每一路通話的 lua 腳本則在相應的線程內(nèi)執(zhí)行,互不干擾。Java 語言需要 Java 的虛擬機環(huán)境,比這個要復雜些。

  Lua

  這是一門小眾語言,聽起來,它可能不像其它語言(如 Java)那樣“如雷貫耳”,但由于其優(yōu)雅的語法及小巧的身段受到很多開發(fā)者的青睞,尤其是在游戲領域(我相信有很多人知道它是緣于2010年一則新聞中 說一個14歲的少年用它編出了 iPhone 上的名為 Bubble Ball 的游戲,該游戲下載量曾一度超過史上最流行的“憤怒的小鳥”)。

  在 FreeSWITCH 中,Lua 模塊是默認加載的。在所有嵌入式腳本語言中,它是最值得推薦的語言。首先它非常輕量級,mod_lua.so 經(jīng)過減肥(strip)后只有272K;另外,它的語法也是相的的簡單。有人做過對比說,在嵌入式的腳本語言里,如果 Python 得 2 分,Perl 拿 4,Javascript 得 5, 則 Lua 語言可得 10 分。可見一斑。

  另外, Lua 模塊的文檔也是最全的。寫其它語言的程序好多時候都需要參照 Lua 模塊的文檔。

  語法簡介

  Lua 語言的注釋為 “--” 開頭(單行),或 “--[[ ]]”(多行)。

  Lua 變量不需要類型聲明

  Lua 支持類似面向對象的編程,所有對象都是一個 Table(Lua 中獨有的概念)。

  Lua 支持尾遞歸、閉包。

  詳細的資料請參閱有關資料,底線是 -- 如果你會其它編程語言,在 30 分鐘內(nèi)就能學會它。

  將電話路由到 Lua 腳本

  在 dialplan XML 中,使用

   <action application="lua" data="test.lua"/>

  便可將進入 dialplan 的電話交給 lua 腳本接管。腳本的默認路徑是安裝路徑的 scripts/ 目錄下,當然你也可以指定絕對路徑,如 /tmp/test.lua。需要注意在 windows 下目錄分隔符是用 "\" ,所以有時候需要兩個,如“c:\test\test.lua”。

  Session 相關函數(shù)

  FreeSWITCH 會自動生成一個 session 對象(實際上是一個 table),因而可以使用 Lua 面象對象的特性編程,如以下腳本放播放歡迎聲音(來自 Hello Lua) 。

 -- answer the call
 session:answer();

 -- sleep a second
 session:sleep(1000);

 -- play a file
 session:streamFile("/tmp/hello-lua.wav");

 -- hangup
 session:hangup();

  大部分跟 session 有關的函數(shù)是跟 FreeSWITCH 中的 App 是一一對應的,如上面的 answer()、hangup() 等,特別的, streamFile() 對應 playback() App 。如果沒有對應的函數(shù),也可以通過 session:execute() 來執(zhí)行相關的 App,如 session:execute("playback", "/tmp/sound.wav") 等價于 session:streamFile("/tmp/sound.wav")。

  需要注意,lua 腳本執(zhí)行完畢后默認會掛斷電話,所以上面的 Hello Lua 例子中不需要明確的 session:hangup()。如果想在 lua 腳本執(zhí)行完畢后繼續(xù)執(zhí)行 dialplan 中的后續(xù)流程,則需要在腳本開始處執(zhí)行

  session:setAutoHangup(false)

  如下列場景,test.lua 執(zhí)行完畢后(假設沒有 session:hangup(),主叫也沒有掛機),如果沒有 setAutoHangup(false),則后續(xù)的 playback 動作得不到執(zhí)行。

 <extension name="eavesdrop">
      <condition field="destination_number" expression="^1234$">
           <action application="answer"/>
           <action application="lua" data="test.lua"/>
           <action application="playback" data="lua-script-complete.wav"/>
      </condition>
 </extension>

非 Session 函數(shù)

  Lua 腳本中也可以使用跟 sesion 不相關的函數(shù),最典型的是 freeswitch.consoleLog(),用于輸出日志,如:

 freeswitch.consoleLog("NOTICE", "Hello lua log!\n")

  另外一個是 freeswitch.API,它允許你執(zhí)行任意 API,如

 api = freeswitch.API();
 reply = api:executeString("sofia", "status");

  獨立的 Lua 腳本

  獨立的 Lua 腳本可以直接在控制臺終端上(使用 luarun)執(zhí)行,這種腳本大部分可用于執(zhí)行一些非 Session 相關的功能,后面我們會講到相關例子。

  數(shù)據(jù)庫

  在 Lua 中,可以使用 LuaSQL 連接各種關系型數(shù)據(jù)庫,但據(jù)說 LuaSQL 與某些版本的數(shù)據(jù)庫驅動結合有內(nèi)存泄漏問題,配置起來也比較復雜。

  另一種連接數(shù)據(jù)庫的方式是直接使用 freeswitch.Dbh。它可以直接通過 FreeSWITCH 內(nèi)部的數(shù)據(jù)庫連接句柄來連接 sqlite 數(shù)據(jù)庫或任何支持 ODBC 的數(shù)據(jù)庫。下面是一個來自 FreeSWITCH wiki 的例子。

 local dbh = freeswitch.Dbh("dsn","user","pass") -- when using ODBC
 -- OR --
 -- local dbh = freeswitch.Dbh("core:my_db") -- when using sqlite

 assert(dbh:connected()) -- exits the script if we didn't connect properly

 dbh:test_reactive("SELECT * FROM my_table",
                   "DROP TABLE my_table",
                   "CREATE TABLE my_table (id INTEGER(8), name VARCHAR(255))")

 dbh:query("INSERT INTO my_table VALUES(1, 'foo')") -- populate the table
 dbh:query("INSERT INTO my_table VALUES(2, 'bar')") -- with some test data

 dbh:query("SELECT id, name FROM my_table", function(row)
   stream:write(string.format("%5s : %s\n", row.id, row.name))
 end)

 dbh:query("UPDATE my_table SET name = 'changed'")
 stream:write("Affected rows: " .. dbh:affected_rows() .. "\n")

 dbh:release() -- optional

  Javascript

  相對于 Lua, 大家可能對 Javascript 更熟悉一些。Javascript 是 Web 瀏覽器上最主流的編程語言,它最早是設計出來用于配合 HTML 渲染頁面用的,近幾年由于 Node.js 的發(fā)展使它在服務器端的應用也已發(fā)揚光大。它遵循 EMCAScript 標準。

  通過加載 mod_spidermonkey 模塊可以使用 js 解析器,模塊 mod_spidermonkey_odbc 則支持在 Javascript 腳本中連接 ODBC 數(shù)據(jù)庫。

  除語法不同外,用法上與 Lua 類似,如使用 javascript (它是一個APP) 執(zhí)行一個 session 相關的腳本,或 jsrun (它是一個API)執(zhí)行一個非 session 相關的腳本。

  其它腳本語言

  其它腳本語言的使用也類似,讀者可參照使用。值得一提的是,F(xiàn)reeSWITCH 有一個 mod_managed 模塊支持 Windows .NET 架構下的語言(F#, VB.NET, C#, IronRuby, IronPython, JScript.NET),通過 mono 也可以支持其它平臺(如 Linux )。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多