zoukankan      html  css  js  c++  java
  • 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 ");  
    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! ");  
    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! ");  
    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 ", name);  
    102.        }  
    103.      }  
    104.    }  
    105.  } else {  
    106.    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load MyModule's config! ");  
    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! ");  
    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" ",   
    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 "  
    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>  
  • 相关阅读:
    Codeforces Round #710 (Div. 3)
    Codeforces Round #708(Unrated on Div. 2)
    [JSOI2014]学生选课(二分+2-SAT)
    Educational Codeforces Round 103 (Rated for Div. 2)爆炸记
    AtCoder Beginner Contest 190
    GPU服务器centos7.4下安装jupyter后调用py文件以及调用失败的解决办法
    关于在centos7.4原来python2.7.5更新到python3.6或更高版本时注意事项
    Selenium初步应用
    CentOS利用docker安装MySQL5.7
    CentOS 常用命令
  • 原文地址:https://www.cnblogs.com/fire909090/p/6862189.html
Copyright © 2011-2022 走看看