近期又开始了我的FreeSWITCH研究之路, 因为项目中需要, 使用sip_profile中的internal端点来处理sipUA的注册及在线保持做被叫, 打开了登录及呼叫认证的开关, 我们都知道FreeSWITCH默认的directory中有1000-1019这20个默认用户, 如果新增用户也有一个批处理脚本能快速的生成出来新的用户, 但是我们做为一个统一平台的操作, 有一个分布式的FS集群, 如果所有的用户都以文档的方式存在每一台有FS的机器上, 管理起来非常不方便, 并且也不便于查询等操作, 所以就有了mod_xml_curl这个模块, 这个模块主要是来集中远程RPC的方式来管理用户目录, 拨号计划, 端点配置等相关的xml配置, 本文主要是从源码的级别来阐述它到底是如何工作的。
一、总体结构
正如其它模块一样, 每一个FS模块都要存在几个通用方法, 如下:
SWITCH_MODULE_LOAD_FUNCTION(mod_xml_curl_load); // 模块装载
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_curl_shutdown); // 模块缷载
SWITCH_MODULE_DEFINITION(mod_xml_curl, mod_xml_curl_load, mod_xml_curl_shutdown, NULL); // 导出外部对本模块的操作入口
switch_status_t mod_xml_curl_load (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool)
SWITCH_MODULE_LOAD_FUNCTION(mod_xml_curl_load)
{
switch_api_interface_t *xml_curl_api_interface; // 这里定义了一个api的使用实例指针
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname); // 这里使用core方法来创建一个模块实例
// 其中的参数, pool为FS共用的内存池, 这里都统一使用core中的内存池, 如果处理不好会导致所有的模块都会有问题, 这点感觉设计的不太好, 第二个
// 参数是modname: 这个是模块的名称
memset(&globals, 0, sizeof(globals)); // 对struct的一个初始化过程
globals.pool = pool; // 保存core内存池句柄到本模块全局变量中去, 以便以后引用
globals.hash_root = NULL;
globals.hash_tail = NULL;
// 这里是对模块的配置文件进行了一个解析的过程, 主要操作xml_curl.conf文件, 以节点xml_binding_t保存
// 这个方法很重要,除了上面说的对配置文件的解析,还对xml_url_fetch回调rpc业务处理方法做了bind,并在switch_xml_bind_search_function方法中
// 将binding保存到了全局的BINDINGS的一个搜索链表中去, 以便core在查找用户时直接回调本方法来拿到用户数据并使用
if (do_config() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
// 这里对这个api进行了初始化, 把xml_curl加入到module_interface模块实例中去, 其中xml_curl_function这个模块回调指针
// 主要设置了控制台api操作时对模块变量keep_file_around参数的赋值, 调试器打开或关闭, 并响应控制台结果.
SWITCH_ADD_API(xml_curl_api_interface, "xml_curl", "XML Curl", xml_curl_function, XML_CURL_SYNTAX);
// 这里是控制台指令调用方法入口,组装sql语句,并通过switch_core_sql_exec(mystream.data)方法将本条指令放入db中去
switch_console_set_complete("add xml_curl debug_on");
switch_console_set_complete("add xml_curl debug_off");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_curl_shutdown)
{
hash_node_t *ptr = NULL;
// 这里对模块产生的内存进行释放
while (globals.hash_root) {
ptr = globals.hash_root;
switch_core_hash_destroy(&ptr->hash);
globals.hash_root = ptr->next;
switch_safe_free(ptr);
}
// 并且取消已解析绑定的xml配置资源
switch_xml_unbind_search_function_ptr(xml_url_fetch);
return SWITCH_STATUS_SUCCESS;
}