freeswitch 內核模塊開發


 

我建了一個 Freeswitch 內核研究 交流群, 45211986, 歡迎加入, 另外,提供基於SIP的通信服務器及客戶端解決方案。

 

這里以模塊 helloworld 為例。

1. 創建模塊目錄  freeswitch/src/mod/applications/mod_helloworld

2. 把模塊名放在 freeswitch/modules.conf文件中,make時 根據此文件選擇編譯哪些模塊並生成相應模塊的makefile文件

3. 如果你的模塊以依賴第三方庫,則需要在makefile中指定頭文件以及庫的路徑,一個例子:

 

LOCAL_CFLAGS=-I$(switch_srcdir)/libs/libteletone/src
LOCAL_LDFLAGS=$(switch_srcdir)/libs/libteletone/libteletone.la

 

 

4.如果你的模塊包含多個文件則需要 指定文件列表:

 

LOCAL_OBJS=file.c file2.c file3.c 
local_depend: $(LOCAL_OBJS)

 

 

5.編寫模塊接口

 

freeswitch中 每個模塊從加載->運行->關閉 流程由三個宏實現,實際編寫模塊過程為幾個宏的填寫。具體業務邏輯在宏內部實現。

SWITCH_MODULE_LOAD_FUNCTION (mod_name)

 

實際展開即為函數,load function 負責系統啟動時或運行時加載模塊,模塊的全局數據結構,鈎子設置,事件handler 一般在此處實現。
 

SWITCH_MODULE_RUNTIME_FUNCTION

系統運行時loop, 這里可以啟動線程處理請求,監聽socket 等等。

SWITCH_MODULE_SHUTDOWN_FUNCTION

模塊卸載,這里負責清除全局數據結構,釋放資源。
  

 

SWITCH_MODULE_DEFINITION  模塊的定義

 

mod_helloworld.c 代碼:

 

 

[cpp]  view plain  copy
 
 print?
  1. #include <switch.h>  
  2.   
  3. /*  initialize any global structures, hook up any event or state handlers ,etc  */  
  4. SWITCH_MODULE_LOAD_FUNCTION(mod_helloworld_load);  
  5.   
  6.  /*  the runtime loop of the module, from here you can listen on sockets,  
  7.   *  spawn new threads to handle requests. etc. 
  8.   */  
  9. SWITCH_MODULE_RUNTIME_FUNCTION(mod_helloworld_runtime);  
  10.   
  11.  /* 
  12.   *   This is where you do any cleanup for unloading or reloading the module,  
  13.   *     you should release state handlers, event reservations, etc.  
  14.   *      You should also synchronize with shutting down the runtime thread (usually using something like a shared 'running' variable that the shutdown function  
  15.   *    sets to some value that the runtime function notices, sets to a third value and then exits). 
  16.   */  
  17. SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_helloworld_shutdown);  
  18.   
  19. SWITCH_MODULE_DEFINITION(mod_helloworld, mod_helloworld_load, mod_helloworld_shutdown, NULL);  
  20.   
  21.   
  22. SWITCH_STANDARD_API(helloworld_function)  
  23. {  
  24.     return SWITCH_STATUS_SUCCESS;  
  25. }  
  26. static switch_status_t parse_config(switch_bool_t reload)  
  27. {  
  28.     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "parse config\n");  
  29.   
  30.     return SWITCH_STATUS_SUCCESS;  
  31. }  
  32.   
  33. /* 
  34.     Macro expands to: switch_status_t  mod_helloworld_load(switch_loadable_module_interface_t **module_interface,  
  35.             switch_memory_pool_t *pool)  
  36. */  
  37. SWITCH_MODULE_LOAD_FUNCTION(mod_helloworld_load)  
  38. {  
  39.     switch_api_interface_t *api_interface;  
  40.     /* connect my internal structure to the blank pointer passed to me */  
  41.     *module_interface = switch_loadable_module_create_module_interface(pool, modname);  
  42.   
  43.     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");  
  44.   
  45.     parse_config(SWITCH_FALSE);  
  46.   
  47.     SWITCH_ADD_API(api_interface, "helloworld", "Hello World API", helloworld_function, "syntax");  
  48.   
  49.     /* indicate that the module should continue to be loaded */  
  50.     return SWITCH_STATUS_SUCCESS;  
  51.       
  52. }  
  53.   
  54. SWITCH_MODULE_RUNTIME_FUNCTION(mod_helloworld_runtime)  
  55. {  
  56.     while(1) {  
  57.         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");  
  58.         switch_yield(10000);  
  59.     }  
  60. }<pre class="cpp" name="code"></pre>  
  61. <pre></pre>  
  62. <pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"><pre class="cpp" name="code"></pre>  
  63. <p><br>  
  64. </p>  
  65. <pre style="border-bottom:rgb(60,120,181) 1px solid; border-left:rgb(60,120,181) 1px solid; padding-bottom:0.4em; background-color:rgb(240,240,240); padding-left:0.4em; padding-right:0.4em; border-top:rgb(60,120,181) 1px solid; border-right:rgb(60,120,181) 1px solid; padding-top:0.4em"><pre name="code" class="cpp">編譯: sudo make mod_helloworld  
  66. 安裝   sudo make mod_helloworld-install  
  67. dialplan里試一試 function  helloworld.  
  68. -----------------------------------  
  69. 高級:  
  70. 1.模塊加載函數內可以加載自定義xml配置文件.  
  71. 例子:  
  72. <configuration name="mymodule.conf" description="MyModule configuration">  
  73.    <settings>  
  74.     <param name="key" value="value"/>  
  75.     ...  
  76.    </settings>  
  77.  </configuration>  
  78. You could do the following:  
  79.   
  80.  switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;  
  81.  if ((xml = switch_xml_open_cfg("mymodule.conf", &cfg, NULL))) {  
  82.    if ((x_lists = switch_xml_child(cfg, "settings"))) {  
  83.      for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {  
  84.        const char *name = switch_xml_attr(x_list, "name"); // This needs to be const   
  85.        const char *value = switch_xml_attr(x_list, "value");  
  86.    
  87.        // Ignore empty/missing attributes  
  88.        if (switch_strlen_zero(name)) {  
  89.          continue;  
  90.        }  
  91.          
  92.        if (switch_strlen_zero(value)) {  
  93.          continue;  
  94.        }  
  95.    
  96.        if (!strcmp(name, "myattribute")) {  
  97.          // Do something with value  
  98.        } else if (!strcmp(name, "myotherattribute")) {  
  99.          // ...  
  100.        } else {  
  101.          switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown attribute %s\n", name);  
  102.        }  
  103.      }  
  104.    }  
  105.  } else {  
  106.    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load MyModule's config!\n");  
  107.  }  
  108.   
  109. 2. 訂閱事件  
  110. 模塊可以向系統訂閱自己感興趣的事件,只需一個函數,指定一個你自己的事件回調。  
  111. 例子:訂閱所有事件  
  112. if (switch_event_bind("mod_mymodule", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, mymodule_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {  
  113.    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot bind to event handler!\n");  
  114.  }  
  115.   
  116. 接下來就是編寫你的回調函數   
  117. void mymodule_event_handler(switch_event_t *event);  
  118. void mymodule_event_handler(switch_event_t *event)   
  119.  {  
  120.     switch_assert(event); // Just a sanity check  
  121.       
  122.     switch(event->event_id) {  
  123.         case SWITCH_EVENT_CHANNEL_CREATE:  
  124.             switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A new channel is born, its called \"%s\"\n",   
  125.                 switch_event_get_header_nil(event, "channel-name")); // This function isnt case-sensitive   
  126.             break;  
  127.         case SWITCH_EVENT_CHANNEL_DESTROY:  
  128.             switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A channel named \"%s\" has been destroyed\n"  
  129.                 switch_event_get_header_nil(event, "channel-name"));  
  130.             break;  
  131.     }  
  132.  }  
  133.   
  134. 3.在模塊內 發起呼叫,定義channle狀態回調。。。。  
  135. </pre><br><br></pre>  
  136. <p></p>  
  137. <pre></pre>  
  138. <pre></pre>  
  139. <pre></pre>  
  140. <pre></pre>  
  141. <pre></pre>  
  142. <pre></pre>  
  143. <pre></pre>  
  144. <pre></pre>  
  145. <pre></pre>  
  146.      
  147. </pre>  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM