




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、ubuntu安裝編譯運行可以使用 telnet 5038 登錄到y(tǒng)ate輸入?可以顯示支持的命令連按tab鍵可以補全命令先debug on 然后再debug level 10,可以打開log編譯步驟要先安裝apt-get install libqt4-dev在yate project的根目錄下./autogen./configuremake install然后在clients目錄下運行./run-qt4 腳本 ,會調(diào)用同樣目錄下的yate-qt4,這個是編譯生成的。wimdows安裝編譯運行yate client安裝qt-win-opensource-4.8.0-vs201
2、0.exe qt-vs-addin-1.1.9.exe安裝了這2個軟件后就可以使用vs2010 vs2005了,下面的不走可以不用做,但要設(shè)置環(huán)境變量。在環(huán)境變量中的系統(tǒng)環(huán)境變量增加:QTDIR= C:Qt4.8.0QMAKESPEC=win32-msvc2005Path = C:Qt4.8.0bin;用vs2005打開yate-4.2.0-2yatewindowsYATE.slnyate-4.2.0-2 的main-client.cpp文件有錯誤,需要改成class WinClientPlugin : public Pluginpublic: WinClientPlugin(): Plugi
3、n("winyateclient"),m_thread(0) virtual void initialize(void); virtual bool isBusy() const return true; private: WinClientThread* m_thread;Qt4相關(guān)的幾個工程和_customtable _customtable _customtext _clientarchive需要加上qt庫和頭文件的路徑。然后挨個編譯每個工程,然后把run-qt4.bat中的release改成debug,然后雙擊之,就會運行yate client了。Yate代碼學(xué)習(xí)筆
4、記Yate 開發(fā)向?qū)?.Yate 框架設(shè)計Yate 的設(shè)計是為了提供一個可擴展性的電話引擎,試圖以最簡簡潔的代碼,在擴展所需功能與性能、穩(wěn)定性之間達到最佳平衡。 Yate 設(shè)計分為三大部分:(1) 引擎( Engine )該引擎已 Yate C+ 類為基礎(chǔ),將把所有模塊組件連接在一起,上圖描述了各組件之間的交互過程。(2) 模塊( Modules )大部分功能由運行時加載的模塊來實現(xiàn)。這些模塊以動態(tài)鏈接庫為載體,作為插件被引擎或外部程序的特定模塊加載。被
5、外部程序特定模塊加載時,需能夠與引擎或其他模塊之間相互交互(通信)。(3) 消息( Messages )Yate 模塊(包括插件和外部模塊)之間的交互是依靠消息實現(xiàn)的。消息提供了一種可擴展,可定制,并且與具體技術(shù)無關(guān)的交互機制。每個模塊在需要得到信息或者需要通知其他模塊時只需要創(chuàng)建并向引擎提交消息,引擎負(fù)責(zé)會將消息傳遞給合適的目標(biāo)。Yate 以 Class Engine 為核心,構(gòu)建了插件式的管理體系,按照觀察者(發(fā)布 - 訂閱)的設(shè)計模式來處理數(shù)據(jù)流。Engine 類根據(jù)配置文件加載插件,缺省
6、參數(shù)的情況下,會加載指定目錄下所有的插件。然后運行插件的初始化函數(shù) initialize() 完成插件的初始化。 Class Yate 提供了一些 API (靜態(tài)函數(shù))用于加載分析配置參數(shù),加載特定模塊,和指定目錄下的所有模塊。/ 加載指定目錄下模塊 參數(shù) relPath 相對主模塊的路徑bool loadPluginDir(const String& relPath);/ 注冊插件,只有注冊過的插件才能被
7、初始化bool Register(const Plugin* plugin, bool reg = true);/ 加載指定模塊bool loadPlugin(const char* file, bool local,bool nounload); privatevoid loadPlugins();/ 從插件目錄中加載插件 privatevoid initPlugins();/ 初始化插件 private 基于列表的
8、發(fā)布 - 訂閱示例由客戶端、服務(wù)和數(shù)據(jù)源程序組成??梢杂卸鄠€客戶端和多個數(shù)據(jù)源程序同時運行??蛻舳擞嗛喎?wù)、接收通知,然后取消訂閱。數(shù)據(jù)源程序向服務(wù)發(fā)送將與所有當(dāng)前訂戶共享的信息。Class Engine:m_dispatcher:m_handles 維護著訂閱者列表,每個訂閱者都實現(xiàn)了以下接口用于接收通知。class MessageHandler virtual bool received(Message& msg) = 0;Class Engine 還提供了一些
9、列的 API (靜態(tài)成員函數(shù)) / 安裝注冊訂閱者的接口,參數(shù)指定訂閱的事件類型 static bool install(MessageHandler* handler);static bool uninstall(MessageHandler* handler); / 發(fā)送事件通知,所有注冊了該事件類型的都有機會得到事件內(nèi)容/enqueue 為非阻塞函數(shù),即將事件通知加入消息列表中,不關(guān)系事件處理的結(jié)果/dispatch 為阻塞函數(shù)
10、,即必須等到訂閱者處理完事件才能返回。static bool enqueue(Message* msg);static bool dispatch(Message* msg);一般調(diào)用 enqueue 把 message 放進了一個消息隊列里,再由一個 Dispatcher 類來對消息順序處理,相當(dāng)于向所有訂閱者發(fā)布消息。插件必須從 Module 類派生,并實現(xiàn) initialize() 這個虛函數(shù),另外,根據(jù)需要實現(xiàn) Message 的處理類MessageHandler
11、160;。在 initialize() 里,按照主題安裝 MessageHandler ,如下所示:Engine:install(new AuthHandler(s_cfg.getIntValue("general","auth_priority",70);上例的 AuthHandler 即是從 MessageHandler 中派生而來,它必須實現(xiàn) received() 虛函數(shù),以處理接收到的message 。如果處理成功,則 rece
12、ived() 應(yīng)該返回 true ,否則返回 false 。 如果某類 DrModule 需要處理多個事件,首先訂閱者必須從 MessageReceiver 派生, Module 就是從MessageReceiver 派生的,可以處理多了事件。另外消息處理類必須由 MessageRelay 派生,當(dāng)然MessageRelay ,也是從 MessageHandler 的。同樣在 Dr-Module:initi
13、alize 中,安裝如下TokenDict DrModule:s_messages = "engine.halt", DrModule:Halt , "gress",
14、0;DrModule:Progress , "call.route", DrModule:Route , "chan.text",
15、 DrModule:Text , "msg.route", DrModule:ImRoute , 0,0 &
16、#160; DrModule:installRelay(Halt); DrModule:installRelay(Progress); DrModule:installRelay(Route,200); DrModule:installRelay(Text); DrModule:installRelay(ImRoute); DrModule:installR
17、elay(ImExecute); YATE 的架構(gòu)是典型的發(fā)布 - 訂閱機制,很好的實現(xiàn)了平臺的可擴充性,減少了模塊與平臺、模塊與模塊之間的耦合,可以說架構(gòu)是非常清晰的。比如用戶認(rèn)證的功能, YATE 里有三個模塊提供三種方式對用戶進行認(rèn)證:文件方式( Regfile ), Radius 方式,數(shù)據(jù)庫方式。這三種方式都是接收并處理 "user.auth" 、"user.register" 等消息,其先后順序根據(jù) in
18、stall 時定的優(yōu)先級排序。處理的結(jié)果由 message 的 retValue() 帶回。這種處理機制雖然優(yōu)點很突出,但性能上的缺點也很明顯,因為在對消息隊列的處理是單線程而且要對所有訂閱者進行遍歷,效率比較低。 2 Yate 中的消息在 Yate 中,消息取代函數(shù)成為模塊間主要的交互方式。這樣的好處在于,當(dāng)一個模塊改變時,其他獨立的模塊不用做任何修改。另外,因為我們能夠輕松的跟蹤到消息的傳遞過程,所以調(diào)試起來相對容易。消息包括以下幾個組成部分:(1) 名字( name )
19、 消息類型的標(biāo)識,允許消息處理器通過名字進行匹配 (2) 返回值( return value ) 一個用字符串表示的處理消息之后的返回值 (3) 時間( time ) 消息被創(chuàng)建的時間;這對于排隊的消息檢查等待時長非常重要 (4) 參數(shù)( parameters ) 可能有多個或
20、 0 個參數(shù)組成,每個參數(shù)由名稱、值對構(gòu)成。每個處理器都能根據(jù)參數(shù)進行不同的動作,或者修改參數(shù)本身。未定義參數(shù)必須忽略。所有的消息在 YATE 內(nèi)部是二進制形式的。然而我們可以通過 rmanager 模塊提供一個對人可讀的形式。 YATE 內(nèi)部消息傳遞通過內(nèi)存共享( memory sharing )的方式,提高系統(tǒng)的性能。其他傳遞方式如管道或Sockets ,沒有內(nèi)存共享靈活和高效。當(dāng)被傳遞到外部模塊( external modules&
21、#160;)時,消息可被轉(zhuǎn)換成字符串編碼的形式,這樣所有能處理文本的外部模塊都可以處理消息了。 可參考文檔 external module ,獲取更多詳細(xì)信息。消息被消息處理器( MessageHandler )處理。消息處理器接收名字匹配的消息,可以對其中的組成部分進行修改,然后停止處理此消息(釋放),或讓此消息滑動到下一個操作者。消息處理器接收消息分發(fā)器通知的順序在其向引擎注冊時提供的優(yōu)先級決定。優(yōu)先級數(shù)字越小,優(yōu)先級越高。對于相同優(yōu)先級的消息處理器,調(diào)用順序是不確定的。調(diào)用順序按以下的規(guī)則: * 同名的消
22、息調(diào)用順序是不會改變的 * 為了避免不確定性,如果消息處理器被移除,并插入一個同等優(yōu)先級的消息處理器,則他們的順序由她的的內(nèi)存地址決定。 2.1 消息系統(tǒng)工作示例 以下是 “call.rotue” 在消息系統(tǒng)重的工作過程例子 當(dāng)某個電話打來時,消息是這樣產(chǎn)生的: 1. Message *m = new Message("call.route");
23、0; 2. m->addParam("driver","iax");
24、; 3. if (e->ies.c
25、alling_name)
26、 4. m->addParam("callername",e->ies.calling_name);
27、160;5. else
28、160;
29、160; 6. m->addParam("callername",e->session->callerid); 7. if (e->ies.called_number)
30、
31、 8. m->addParam("called",e->ies.called_number); 9. else
32、;
33、; 10.
34、160; m->addParam("called",e->session->dnid); 然后我們將消息發(fā)送給引擎,檢查是否有模塊(&
35、#160;module )接收并處理了,最后必須將消息銷毀。1. if (Engine:dispatch(m) 2. Output("Routing returned: %s",m->retValue().c_str(); 3. else
36、60;4. Output("Nobody routed the call!"); 5. m->destruct(); 上面的處理方式是阻塞式的,模塊發(fā)送消息之后需要等待該消息被發(fā)送之后才進行后續(xù)的處理。 Yate 中還有一種“發(fā)射后忘記”( fire-and-forget )的消息機制,非阻塞式
37、消息機制,這種消息被存儲在引擎中的一個隊列中,當(dāng)消息被分發(fā)后,由引擎負(fù)責(zé)釋放。這種消息一般都是事關(guān)系統(tǒng)全局的重要消息,例如錯誤報警,如下代碼所示:1. Message *m = new Message("alert"); 2. m->addParam("reason","Hardware malfunction");
38、160; 3. Engine:enqueue(m); 如果我們編寫的模塊需要處理一個路由請求(極有可能是其他模塊產(chǎn)生的),我們首先需要聲明一個名為RouteHandler 的類,并從MessageHandler 基類繼承。1. class RouteHandler : public MessageHandler 2.
39、160; 3. public: 4. RouteHandler(int prio) 5. : MessageHandler(
40、"call.route",prio) 6. virtual bool received(Message &msg); 7. 然后,由于在 received 方法中實現(xiàn),他是類 MessageHandler 中是純虛函數(shù),我
41、們必須重載。1. bool RouteHandler:received(Message &msg) 2. 3. const char *driver = msg.getValue("driver")
42、;4. Debug(DebugInfo,"Route for driver %s",driver); 5. / don't actually route anything, let message continue
43、6. return false; 7. 最后,在插件的 initialized 方法中,安裝此消息處理器1. void RegfilePlugin:initialize() 2.
44、0; 3. m_route = new RouteHandler(priority); 4. Engine:install(m_route); 5. 這樣,該插件就能處理“ call.route ”消息
45、了,這個例子中實際上只是接收了消息但沒有做任何動作,如果需要什么操作,在 received 方法里實現(xiàn)即可。 Yate 中的幾乎所有消息操作者都是按照這樣的框架實現(xiàn)的。2.2 消息流示例以呼叫進入為例: 路由當(dāng)一個通道模塊檢測到有呼叫進入 (1) ,它便發(fā)送 call.route(2) 消息來決定將此呼叫路由到哪個位置。Call.route 消息將被叫號碼映射到一個呼叫目標(biāo)。連接當(dāng)呼叫對象已知以后,呼入通道將其呼叫端點( CallEndPoint )附在
46、call.execute 消息上 (4) 。接收方應(yīng)該將它的呼叫端點連接到 call.execute 中攜帶的呼叫端點上。在等待對端接受呼叫期間應(yīng)該發(fā)送 call.ringing 消息(6) ,當(dāng)呼叫被接受時, call.ansered 被發(fā)送。會話期間在會話期間, chan.dtmf 消息 (8,9) 能在兩個方向上發(fā)送。掛機當(dāng)呼入通道檢測到掛機 (10) ,它將斷開其呼叫端點。斷開呼叫端點將引發(fā)兩個通道 chan.disc
47、onnected 消息和 chan.hangup 消息的(圖中未包括)發(fā)送。從消息流的示例我們可以看到, Yate 對呼叫的抽象很清晰,在邏輯上符合人們的思維習(xí)慣,比較容易理解。 2.3 消息類型1. 引擎消息( Engine messages ) engine.start
48、 由引擎發(fā)送給普通模塊,通知他們 Yate 準(zhǔn)備就緒,并已進入主循環(huán) engine.halt engine.init engine.busy engine.help mand
49、; engine.status engine.timer2. 通道消息( Channel messages ) chan.attach chan.connected chan.disconnected
50、0;chan.dtmf 雙音多頻信號( Dual-tone multi-frequency signaling ) chan.hangup chan.masquerade
51、0;chan.notify chan.record chan.rtp chan.startup chan.text chan.connect chan.locate
52、160; chan.control chan.replaced3. 呼叫消息( Call messages ) call.answered call.cdr call.drop
53、0;call.execute gress call.ringing call.route call.preroute call.update call.confer
54、ence4. 用戶消息( User messages ) user.account user.auth user.login user.notify user.register
55、0; user.unregister5. 資源描述 / 通知消息 (Resource subscribe/notify messages) resource.subscribe resource.notify6. SIP 消息 (SIP messages) sip.<methodname>
56、60; xsip.generate7. 編解碼特定協(xié)議消息 (Encode or decode protocol specific messages) isup.decode isup.encode? isup.mangle8. 網(wǎng)絡(luò)操作消息( Socket operation messag
57、es ) socket.stun socket.ssl socket.peel?9. 集群相關(guān)消息( Clustering related messages ) cluster.locate10. 即時信息相關(guān)消息( Instant messaging rel
58、ated messages ) msg.route? msg.execute?11. Jabber / XMPP messages xmpp.generate? xmpp.iq12. 其他消息( Miscellaneous messages )
59、 database monitor.query monitor.notify 3.Yate 模塊創(chuàng)建方法在實際應(yīng)用中,可能需要編寫自己的模塊插入到系統(tǒng)中或者替換掉自己的模塊,例如,使用商用的SIP 協(xié)議棧替代Yate 中開源的SIP 協(xié)議棧,所以,編寫在Yate 框架下編寫自己的模塊是使用Yate 平臺必備的技能。Yate可分為兩個部分
60、60; * Yate內(nèi)核 * Yate模塊 *Yate內(nèi)核提供基礎(chǔ),輔助API以及消息系統(tǒng) *Yate模塊使用Yate內(nèi)核實現(xiàn)特定的功能Yate模塊的類型Yate模塊可分為一下幾種 1.通道 2.路由器 3.電話歷史記錄(Call Detail Recorder) 4.計費程序 5.其他模塊如何指定
61、模塊的類型模塊類型在這里涉及許多概念性的東西。Yate的設(shè)計中并不區(qū)分模塊的種類,而是根據(jù)模塊處理的消息類型來區(qū)分模塊類型。例如一個通道模塊接受call.execute消息,并創(chuàng)建一個通道來接受處理它。有此特征的模塊我們稱之通道模塊。另一方面即使如果模塊可能接受call.execute消息并處理一個事情,但并不創(chuàng)建一個通道/終端,則它不是一個通道模塊。CDRBuilder就是這樣的模塊。如果你還不清楚,稍等,接下來的例子會說明清楚。 程序員眼里的消息 消息應(yīng)正確派發(fā)到注冊了并在監(jiān)聽該消息的模塊中。模塊可以指定接受消息的優(yōu)先級。如果一模塊監(jiān)聽的call.execute消息優(yōu)
62、先級為50,其他模塊也在監(jiān)聽call.execute消息,但優(yōu)先級值大于50,則該模塊應(yīng)該先于其他模塊獲取call.execute消息。一旦接收到該消息,模塊可向派發(fā)器返回true或fale,并附帶一些額外信息。如果返回true,則派發(fā)器停止向后續(xù)的模塊發(fā)送消息。返回false,則允許消息按照優(yōu)先級繼續(xù)派發(fā)到其他模塊中。 Yate消息不會同Windows消息相混淆,因為他只在Yate系統(tǒng)范圍內(nèi)發(fā)送而沒有使用操作系統(tǒng)機制發(fā)送消息。此外,Yate消息構(gòu)造是以字符串定義的,而OS消息使用的是數(shù)值。TelEngine命名空間 所有的Yate
63、API都什么在TelEngine命名空間中,命名空間是C+的一個概念,用于減少程序中變量名和函數(shù)名重名沖突。因此,要使用命名空間TelEngine,如不想寫TelEngine:blahblah,你可以使用:1. using namespace TelEngine; 我們的第一個模塊 我們現(xiàn)在開始寫我們的第一個模塊,可以接受call.execute消息,并將其呼叫和被叫的號碼輸出到控制臺中。我們設(shè)模塊名為mymodule1.ln。在這個模塊中我們需要討論以下幾個類。 *Module &
64、#160; *Message *MessageReceiver *String同樣還得介紹call.routeCPP文件準(zhǔn)備我們需在模塊目錄下創(chuàng)建一個名為mymodule1.cpp的文件包含telengine.h文件則可使用YATE的API第一步-模塊代碼和前面解釋的一樣,Yate模塊要申明他是一個Yate模塊都需從Module類派生。Module是從多個類派生的。在Yate API繼承關(guān)系如下:1. class YATE_API Module : public
65、;Plugin, public Mutex, public MessageReceiver, public DebugEnabler 2. . 注意Plugin類向Yate提供了加載模塊的功能在我們的模塊中聲明類如下: 1. class MyModule : public Module 2. 3. public: 4.
66、0;MyModule() 5. : Module("MyModule1","misc"), m_init(false) 6. virtual void initialize(); 7. virtual bool received(
67、Message &msg,int id); 8. private: 9. enum 10. 11. CallRoute = Private + 1 12. Privat
68、eRelayID; 13. bool m_init; 14. ; 第二步:創(chuàng)建Module類的靜態(tài)變量當(dāng)Yate模塊加載一個模塊是,他首先會在模塊中(Plugin)查找名為_plugin的靜態(tài)變量。在我們的例子中,我們需要定義類MyModule(派生于Plugin)的一個靜態(tài)變量。Yate提供了幫助做這個,僅需要這樣使用:1. INIT_PLUGIN(MyModule); 第三步:模塊initialize()的重要性你需特別注
69、意到我們在MyModule聲明定義的initialize方法。initialize函數(shù)在Plugin類是虛函數(shù),在Yate加載模塊時會被調(diào)用。MyModule需要重載它,做一些模塊初始化工作。通常在這里注冊模塊想監(jiān)聽的消息。我們可這樣寫代碼:1. void MyModule:initialize() 2. 3. Output("Initializing module mymodule1"); 4.
70、0; if(!m_init) 5. m_init = true; 6. 7. Yate提供的Output函數(shù)輸出信息到控制臺。它只在必要的時候使用。Yate同樣提供了一些其他API函數(shù)將調(diào)試信息輸出到控制臺。第四步:添加代碼接受消息模塊通常需要接受一個或多個消息。模塊接受到一個消息并執(zhí)行程序制度的工作。Module類派生與MessageReceiver,Message
71、Receiver通過虛函數(shù)received()提供了接受消息能力。我們可按自己愛好添加代碼接受消息,像這樣:1. void MyModule:initialize() 2. 3. Output("Initializing Module mymodule1"); 4. if(!m_init) 5. Eng
72、ine:install(new MessageRelay("call.route",this,CallRoute,55); 6. m_init = true; 7. 8. Yate中的類Engine。Yate創(chuàng)建了一個Engine的靜態(tài)對象作為他(Yate)的啟動(不是模塊的啟動)。這個類啟動真?zhèn)€Yate的服務(wù)器/服務(wù)。這個類全是靜態(tài)成員函數(shù)。In
73、stall()同樣是靜態(tài)函數(shù),這也就是我們?yōu)槭裁碋ngine:install這樣調(diào)用的原因。install向yate提供了我們的MessageRelay類對象,指定了我們想要監(jiān)聽消息的消息id、監(jiān)聽優(yōu)先級等。第三個參數(shù)CallRoute是枚舉值,它僅指定我們想關(guān)聯(lián)消息的消息ID。枚舉值CallRoute為Private+1,在類Module中定義,用于指定(說明)該消息在模塊中沒有任何RelayID??煽纯碮ate中Module類的枚舉值。當(dāng)你監(jiān)聽到多個消息,你需要識別監(jiān)聽到的消息,當(dāng)然這有多種方式實現(xiàn)。注意在MessageRelay的最好一個參數(shù)值為55,這說明我們想監(jiān)聽的消息優(yōu)先級別值為5
74、5。因此如果其他模塊也在監(jiān)聽同樣的消息且優(yōu)先級更高,將先接收到這個消息并且如果他返回非ture,我們的這個模塊才能接受到這個消息。MessageRelay被Yate用例發(fā)送消息,它的構(gòu)造函數(shù)擁有一個MessageReceiver類的對象用戶消息的通知。我們MyModule繼承于Module,而Module繼承于MessageReceiver,因此,我們在MyModule可提供這個對象(MessageReceiver)。第五步:重載received類MessageReceiver的received(Message &msg,int id)方法由Yate調(diào)用,用于派發(fā)注冊過監(jiān)聽的消息。re
75、ceived在MessageReceiver中聲明為虛函數(shù)。注意,返回值為bool,如果處理完這個消息,并不想后面的模塊接受處理該消息,返回true。希望后續(xù)的模塊繼續(xù)處理該消息返回false即可。這里(received)我們可以添加自己的邏輯代碼。在received中我們可寫一些代碼,在call.route消息來臨時,輸出呼叫者和被呼叫者名。1. bool MyModule:received(Message &msg,int id) 2. 3. String
76、160;called,caller; 4. called = msg.getValue("called"); 5. caller = msg.getValue("caller"); 6. Output("mymodule1: call.route called
77、0;7. caller %s, and called %s",caller.c_str(),called.c_str(); 8. return false; 9. 上述代碼使用了Yate API提供的String類。從名可知這個類提供了字符串的相關(guān)操作。Message繼承與NamedList,這是YATE提供的另一個類,用于更好管理字符串與字符串直接的映射鏈表。
78、類NamedList的函數(shù)getValue(),我們先獲取被叫號碼(熟知的DNID),然后獲取呼叫者的號碼,作為電信運營商的ANI/CLI(被叫者ID/呼叫者ID)。c_str為String的成員函數(shù),返回字符串存儲的數(shù)據(jù),類型為const char*.1. #include <yatengine.h> 2. #include <yatephone.h> 3. #include <stdio.h> 4. #include <stdlib.h>
79、 5. using namespace TelEngine; 6. class MyModule : public Module 7. 8. public: 9. MyModule() 10. : Module("MyModule1"
80、;,"misc"), m_init(false) 11. virtual void initialize(); 12. virtual bool received(Message &msg,int id); 13. private: 14. enum
81、0; 15. 16. CallRoute = Private + 1 17. PrivateRelayID; 18. bool m_init; 19. ; 20. bool
82、160;MyModule:received(Message &msg,int id) 21. 22. String called,caller; 23. called = msg.getValue("called"); 24. caller = msg.getValu
83、e("caller"); 25. Output("mymodule1: call.route called 26. caller %s, and called %s",caller.c_str(),called.c_str(); 27. return false;
84、160;28. 29. void MyModule:initialize() 30. 31. Output("Initializing Module mymodule1"); 32. if(!m_init) 33. Engine:i
85、nstall(new MessageRelay("call.route",this,CallRoute,55); 34. m_init = true; 35. 36. 37. INIT_PLUGIN(MyModule); 38. /* vi: set ts=8&
86、#160;sw=4 sts=4 noet: */ YATE消息機制消息是YATE的一個主要組成部分。所有的模塊間通信都使用消息而不使用函數(shù)調(diào)用,這主要是因為我們考慮當(dāng)一個模塊發(fā)生變化的時候不影響或不依賴于其他模塊,也因為我們知道模塊直接傳遞的參數(shù),使得我們的調(diào)試模塊可以更容易些。一個消息由以下幾個部分組成: * 名字(name)消息類型的標(biāo)識,允許消息處理器通過名字進行匹配 * 返回值(return value) 一個用字符串表示的處理消息之后的返回值
87、0; * 時間(time) 消息被創(chuàng)建的時間;這對于排隊的消息檢查等待時長非常重要 * 參數(shù)(parameters) 可能有多個或0個參數(shù)組成,每個參數(shù)由名稱、值對構(gòu)成。每個處理器都能根據(jù)參數(shù)進行不同的動作,或者修改參數(shù)本身。不知道的參數(shù)必須忽略。所有的消息在YATE內(nèi)部是二進制形式的。然而我們可以通過rmanager模塊提供一個對人可讀的形式。 YATE內(nèi)部消息傳遞通過內(nèi)存共享(memory sharing)。在這種方式下,可以提高系統(tǒng)的性能。其他可以考慮的形式如管道或Sockets,沒有內(nèi)存共享
88、靈活和高效。當(dāng)被傳遞到外部模塊(external modules)時,消息被轉(zhuǎn)換成字符串編碼的形式,這樣所有能處理文本的外部模塊都可以處理消息了。 可參考文檔external module,獲取更多詳細(xì)信息。 消息由消息處理器處理,每個消息處理器僅處理與它名字相同的消息。他們可以任意修改消息元素(參數(shù),返回值,甚至消息名稱),一個消息處理器處理完之后,可由下一個消息處理器處理。 消息處理器處理消息的順序,再插入派發(fā)器中就已經(jīng)決定。處理順序按照消息處理器的優(yōu)先級決定,優(yōu)先級值越低的預(yù)處理器優(yōu)先級越高,先與優(yōu)先級值高的接受到消息。 對于相同優(yōu)先級的消
89、息處理器,調(diào)用順序是不確定的。調(diào)用順序按以下的規(guī)則: *同名的消息調(diào)用順序是不會改變的 *為了避免不確定性,如果消息處理器被移除,并插入一個同等優(yōu)先級的消息處理器,則他們的順序由她的的內(nèi)存地址決定。 以下是“call.rotue”在消息系統(tǒng)重的工作過程例子 當(dāng)某個電話打來時,消息是這樣產(chǎn)生的:1. Message *m = new Message("call.route"); 2. m->addParam("driver&qu
90、ot;,"iax"); 3. if (e->ies.calling_name) 4. m->addParam("callername",e->ies.calling_name); 5. else 6. m->addParam("callername"
91、,e->session->callerid); 7. if (e->ies.called_number) 8. m->addParam("called",e->ies.called_number); 9. else 10. m->addParam("called",e->se
92、ssion->dnid); 然后我們將消息發(fā)送給引擎,檢查是否有模塊(module)接收并處理了,最后必須將消息銷毀。1. if (Engine:dispatch(m) 2. Output("Routing returned: %s",m->retValue().c_str(); 3. else 4. Output("Nobody routed the cal
93、l!"); 5. m->destruct(); 引擎在得到上述消息,將其發(fā)送到所有注冊名為“route”消息處理器模塊中。對于fire-and-forget類型消息,他們先存儲在引起的消息隊列中并由引擎內(nèi)部的線程池進行延后派發(fā)。一旦消息派發(fā)完成后則由引擎將其銷毀。1. Message *m = new Message("alert"); 2. m->addParam("reason","Hardware ma
94、lfunction"); 3. Engine:enqueue(m); 為了處理route消息請求(很有可能在另外一個模塊中),我們首先聲明一個從MessageHandler派生的類RouteHandler。1. class RouteHandler : public MessageHandler 2. 3. public: 4. RouteHandler(int p
95、rio) 5. : MessageHandler("call.route",prio) 6. virtual bool received(Message &msg); 7. ; 然后,由于方法received在類MessageHandler中是純虛函數(shù),我們必須重載。1. b
96、ool RouteHandler:received(Message &msg) 2. 3. const char *driver = msg.getValue("driver") 4. Debug(DebugInfo,"Route for driver %s",driver); 5. / don't actually route anything, let message continue 6. return false; 7. 最后,在插件的initia
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 土地使用權(quán)轉(zhuǎn)讓合同
- 油罐清洗施工方案
- 裝飾頂帽施工方案
- 公司員工聘用合同書
- 橋梁施工方案對比
- 纜索吊拱橋施工方案
- 2025年防雷防爆及弱電工程設(shè)備項目建議書
- 拆除溫感煙感探頭施工方案
- 酒店弱電養(yǎng)護方案
- 滁州商場指示牌施工方案
- 道路工程規(guī)劃選址論證報告(共85頁)
- 完整版專家信息登記表
- 5米以上深基礎(chǔ)專項施工方案
- 醫(yī)院安全巡查制度醫(yī)院安全巡查制度
- 骨化膿性骨髓炎的影像學(xué)診斷
- 臺灣姓氏拼音對照
- 套管柱及其強度設(shè)計ppt課件
- 三年級語文家長會(課堂PPT)
- 新老加油加氣站設(shè)計與施工規(guī)范要點對比解讀
- 醫(yī)藥企業(yè)價格和營銷行為信用承諾書
- 三體系程序文件(參考)
評論
0/150
提交評論