freeswitch内核模块开发
2011-10-29 13:14
801 查看
转载地址:http://blog.csdn.net/perfectpdl/article/details/6692713
这里以模块 helloworld 为例。
1. 创建模块目录 freeswitch/src/mod/applications/mod_helloworld
2. 把模块名放在 freeswitch/modules.conf文件中,make时 根据此文件选择编译哪些模块并生成相应模块的makefile文件
3. 如果你的模块以依赖第三方库,则需要在makefile中指定头文件以及库的路径,一个例子:
4.如果你的模块包含多个文件则需要 指定文件列表:
5.编写模块接口
freeswitch中 每个模块从加载->运行->关闭 流程由三个宏实现,实际编写模块过程为几个宏的填写。具体业务逻辑在宏内部实现。
SWITCH_MODULE_LOAD_FUNCTION (mod_name)
实际展开即为函数,load function 负责系统启动时或运行时加载模块,模块的全局数据结构,钩子设置,事件handler 一般在此处实现。
SWITCH_MODULE_DEFINITION 模块的定义
mod_helloworld.c 代码:
view plainprint?
#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 plainprint?
<settings>
<param name="key" value="value"/>
...
</settings>
</configuration>
ou 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 plainprint?
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");
}
接下来就是编写你的回调函数
view plainprint?
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状态回调。。。。
这里以模块 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 plainprint?
#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);
}
}
#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 plainprint?
<settings>
<param name="key" value="value"/>
...
</settings>
</configuration>
ou 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");
}
<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 plainprint?
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");
}
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 plainprint?
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;
}
}
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状态回调。。。。
相关文章推荐
- freeswitch 内核模块开发
- 3-05 嵌入式Linux内核模块开发
- linux 内核模块的编译(用于驱动开发)
- freeswitch 内核之sip 模块
- 在ubuntu上开发编译内核模块,并查看printk打印的消息
- ARM学习笔记——内核模块开发
- Linux设备驱动开发详解-Note(8)---Linux 内核模块(2)
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程(转)
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程
- 有关 Linux 下内核模块的开发方式的记录
- Linux 下内核模块的开发方式的记录 及问题解决(入门的Helloworld)
- Linux设备驱动开发详解-Note(7)---Linux 内核模块(1)
- Ubuntu 14.04 Linux内核版本3.16.0内核模块开发Makefile文件样板
- Linux 驱动开发之内核模块开发 (三)—— 模块传参
- 内核模块开发中makefile的制作(多文件)
- 开发内核模块过程中的问题总结
- linux 学习- 编程基础之内核模块开发
- [zz]Ubuntu/Debian 之内核模块开发准备
- freeswitch 录音录像模块和内核
- 有关 Linux 下内核模块的开发方式的记录 .