freeswitch内核模块开发

转载地址:http://blog.csdn.net/perfectpdl/article/details/6692713

这里以模块 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 代码:


view plain 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. }  
#include <switch.h>/* initialize any global structures, hook up any event or state handlers ,etc */SWITCH_MODULE_LOAD_FUNCTION(mod_helloworld_load); /* the runtime loop of the module, from here you can listen on sockets, * spawn new threads to handle requests. etc. */SWITCH_MODULE_RUNTIME_FUNCTION(mod_helloworld_runtime); /* * This is where you do any cleanup for unloading or reloading the module, * you should release state handlers, event reservations, etc. * You should also synchronize with shutting down the runtime thread (usually using something like a shared 'running' variable that the shutdown function * sets to some value that the runtime function notices, sets to a third value and then exits). */SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_helloworld_shutdown);SWITCH_MODULE_DEFINITION(mod_helloworld, mod_helloworld_load, mod_helloworld_shutdown, NULL);SWITCH_STANDARD_API(helloworld_function){ return SWITCH_STATUS_SUCCESS;}static switch_status_t parse_config(switch_bool_t reload){switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "parse config\n");return SWITCH_STATUS_SUCCESS;}/* Macro expands to: switch_status_t mod_helloworld_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */SWITCH_MODULE_LOAD_FUNCTION(mod_helloworld_load){switch_api_interface_t *api_interface;/* connect my internal structure to the blank pointer passed to me */*module_interface = switch_loadable_module_create_module_interface(pool, modname);switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");parse_config(SWITCH_FALSE);SWITCH_ADD_API(api_interface, "helloworld", "Hello World API", helloworld_function, "syntax");/* indicate that the module should continue to be loaded */return SWITCH_STATUS_SUCCESS;}SWITCH_MODULE_RUNTIME_FUNCTION(mod_helloworld_runtime){while(1) {switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");switch_yield(10000);}}

编译: sudo make mod_helloworld

安装   sudo make mod_helloworld-install

dialplan里试一试 function  helloworld.


-----------------------------------

高级:

1.模块加载函数内可以加载自定义xml配置文件.

例子:

<configuration name="mymodule.conf" description="MyModule configuration">

view plain print ?
  1.   <settings>  
  2.    <param name="key" value="value"/>  
  3.    ...  
  4.   </settings>  
  5. </configuration>  
  6. ou could do the following:  
  7.   
  8. switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;  
  9. if ((xml = switch_xml_open_cfg("mymodule.conf", &cfg, NULL))) {  
  10.   if ((x_lists = switch_xml_child(cfg, "settings"))) {  
  11.     for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {  
  12.       const char *name = switch_xml_attr(x_list, "name"); // This needs to be const   
  13.       const char *value = switch_xml_attr(x_list, "value");  
  14.   
  15.       // Ignore empty/missing attributes  
  16.       if (switch_strlen_zero(name)) {  
  17.         continue;  
  18.       }  
  19.         
  20.       if (switch_strlen_zero(value)) {  
  21.         continue;  
  22.       }  
  23.   
  24.       if (!strcmp(name, "myattribute")) {  
  25.         // Do something with value  
  26.       } else if (!strcmp(name, "myotherattribute")) {  
  27.         // ...  
  28.       } else {  
  29.         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown attribute %s\n", name);  
  30.       }  
  31.     }  
  32.   }  
  33. else {  
  34.   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load MyModule's config!\n");  
  35. }  
<settings> <param name="key" value="value"/> ... </settings> </configuration>You could do the following: switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL; if ((xml = switch_xml_open_cfg("mymodule.conf", &cfg, NULL))) { if ((x_lists = switch_xml_child(cfg, "settings"))) { for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) { const char *name = switch_xml_attr(x_list, "name"); // This needs to be const const char *value = switch_xml_attr(x_list, "value"); // Ignore empty/missing attributes if (switch_strlen_zero(name)) { continue; } if (switch_strlen_zero(value)) { continue; } if (!strcmp(name, "myattribute")) { // Do something with value } else if (!strcmp(name, "myotherattribute")) { // ... } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown attribute %s\n", name); } } } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load MyModule's config!\n"); }
2. 订阅事件

模块可以向系统订阅自己感兴趣的事件,只需一个函数,指定一个你自己的事件回调。

例子:订阅所有事件

view plain print ?
  1. if (switch_event_bind("mod_mymodule", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, mymodule_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {  
  2.    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot bind to event handler!\n");  
  3.  }  
if (switch_event_bind("mod_mymodule", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, mymodule_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot bind to event handler!\n"); }
接下来就是编写你的回调函数 

void mymodule_event_handler(switch_event_t *event);
view plain print ?
  1. void mymodule_event_handler(switch_event_t *event)   
  2.  {  
  3.     switch_assert(event); // Just a sanity check  
  4.       
  5.     switch(event->event_id) {  
  6.         case SWITCH_EVENT_CHANNEL_CREATE:  
  7.             switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A new channel is born, its called \"%s\"\n",   
  8.                 switch_event_get_header_nil(event, "channel-name")); // This function isnt case-sensitive   
  9.             break;  
  10.         case SWITCH_EVENT_CHANNEL_DESTROY:  
  11.             switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A channel named \"%s\" has been destroyed\n"  
  12.                 switch_event_get_header_nil(event, "channel-name"));  
  13.             break;  
  14.     }  
  15.  }  
void mymodule_event_handler(switch_event_t *event) { switch_assert(event); // Just a sanity check switch(event->event_id) { case SWITCH_EVENT_CHANNEL_CREATE: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A new channel is born, its called \"%s\"\n", switch_event_get_header_nil(event, "channel-name")); // This function isnt case-sensitive break; case SWITCH_EVENT_CHANNEL_DESTROY: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A channel named \"%s\" has been destroyed\n" switch_event_get_header_nil(event, "channel-name")); break; } }
3.在模块内 发起呼叫,定义channle状态回调。。。。

你可能感兴趣的:(xml,list,function,Module,null,interface)