FreeSWITCH添加自定义endpoint
一、模块定义函数
#define SWITCH_MODULE_LOAD_ARGS (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool)
#define SWITCH_MODULE_RUNTIME_ARGS (void)
#define SWITCH_MODULE_SHUTDOWN_ARGS (void)
typedef switch_status_t (*switch_module_load_t) SWITCH_MODULE_LOAD_ARGS;
typedef switch_status_t (*switch_module_runtime_t) SWITCH_MODULE_RUNTIME_ARGS;
typedef switch_status_t (*switch_module_shutdown_t) SWITCH_MODULE_SHUTDOWN_ARGS;
#define SWITCH_MODULE_LOAD_FUNCTION(name) switch_status_t name SWITCH_MODULE_LOAD_ARGS
#define SWITCH_MODULE_RUNTIME_FUNCTION(name) switch_status_t name SWITCH_MODULE_RUNTIME_ARGS
#define SWITCH_MODULE_SHUTDOWN_FUNCTION(name) switch_status_t name SWITCH_MODULE_SHUTDOWN_ARGS
1、模块加载
2、模块卸载
3、模块运行时
4、模块定义
typedef struct switch_loadable_module_function_table {
int switch_api_version;
switch_module_load_t load;
switch_module_shutdown_t shutdown;
switch_module_runtime_t runtime;
switch_module_flag_t flags;
} switch_loadable_module_function_table_t; #define SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, flags) \
static const char modname[] = #name ; \
SWITCH_MOD_DECLARE_DATA switch_loadable_module_function_table_t name##_module_interface = { \
SWITCH_API_VERSION, \
load, \
shutdown, \
runtime, \
flags \
} #define SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime) \
SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, SMODF_NONE)
二、模块加载流程
1、模块加载函数
switch_loadable_module_load_module
=> switch_loadable_module_load_module_ex
=> switch_loadable_module_load_file
=> switch_loadable_module_process
=> switch_core_launch_thread => switch_loadable_module_exec
void *switch_dso_data_sym(switch_dso_lib_t lib, const char *sym, char **err)
{
void *addr = dlsym(lib, sym);
if (!addr) {
char *err_str = NULL;
dlerror(); if (!(addr = dlsym(lib, sym))) {
err_str = (char *)dlerror();
} if (err_str) {
*err = strdup(err_str);
}
}
return addr;
}
static void *SWITCH_THREAD_FUNC switch_loadable_module_exec(switch_thread_t *thread, void *obj)
{ switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_core_thread_session_t *ts = obj;
switch_loadable_module_t *module = ts->objs[0];
int restarts; switch_assert(thread != NULL);
switch_assert(module != NULL); for (restarts = 0; status != SWITCH_STATUS_TERM && !module->shutting_down; restarts++) {
status = module->switch_module_runtime();
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Thread ended for %s\n", module->module_interface->module_name); if (ts->pool) {
switch_memory_pool_t *pool = ts->pool;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Destroying Pool for %s\n", module->module_interface->module_name);
switch_core_destroy_memory_pool(&pool);
}
switch_thread_exit(thread, 0);
return NULL;
}
2、FreeSWITCH启动时加载模块
函数调用链如下:
main
=> switch_core_init_and_modload
=> switch_core_init
=> switch_loadable_module_init => switch_loadable_module_load_module
switch_loadable_module_load_module_ex("", "CORE_SOFTTIMER_MODULE", SWITCH_FALSE, SWITCH_FALSE, &err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, event_hash);
switch_loadable_module_load_module_ex("", "CORE_PCM_MODULE", SWITCH_FALSE, SWITCH_FALSE, &err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, event_hash);
switch_loadable_module_load_module_ex("", "CORE_SPEEX_MODULE", SWITCH_FALSE, SWITCH_FALSE, &err, SWITCH_LOADABLE_MODULE_TYPE_COMMON, event_hash);
main => switch_core_init_and_modload
=> switch_core_init
=> switch_xml_init
=> switch_xml_open_root => XML_OPEN_ROOT_FUNCTION
if (!SWITCH_GLOBAL_filenames.conf_name && (SWITCH_GLOBAL_filenames.conf_name = (char *) malloc(BUFSIZE))) {
switch_snprintf(SWITCH_GLOBAL_filenames.conf_name, BUFSIZE, "%s", "freeswitch.xml");
}
static switch_xml_open_root_function_t XML_OPEN_ROOT_FUNCTION = (switch_xml_open_root_function_t)__switch_xml_open_root; SWITCH_DECLARE_NONSTD(switch_xml_t) __switch_xml_open_root(uint8_t reload, const char **err, void *user_data)
{
char path_buf[1024];
uint8_t errcnt = 0;
switch_xml_t new_main, r = NULL; if (MAIN_XML_ROOT) {
if (!reload) {
r = switch_xml_root();
goto done;
}
} switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR, SWITCH_GLOBAL_filenames.conf_name);
if ((new_main = switch_xml_parse_file(path_buf))) {
*err = switch_xml_error(new_main);
switch_copy_string(not_so_threadsafe_error_buffer, *err, sizeof(not_so_threadsafe_error_buffer));
*err = not_so_threadsafe_error_buffer;
if (!zstr(*err)) {
switch_xml_free(new_main);
new_main = NULL;
errcnt++;
} else {
*err = "Success";
switch_xml_set_root(new_main); }
} else {
*err = "Cannot Open log directory or XML Root!";
errcnt++;
} if (errcnt == 0) {
r = switch_xml_root();
} done: return r;
}
<section name="configuration" description="Various Configuration">
<X-PRE-PROCESS cmd="include" data="autoload_configs/*.xml"/>
</section>
3、控制台动态加载
fs_cli => load ... => SWITCH_STANDARD_API(load_function) => switch_loadable_module_load_module fs_cli => reload ... => SWITCH_STANDARD_API(reload_function) => switch_loadable_module_unload_module
=> switch_loadable_module_load_module
三、关键数据结构
1、switch_loadable_module_t
struct switch_loadable_module {
char *key;
char *filename;
int perm;
switch_loadable_module_interface_t *module_interface;
switch_dso_lib_t lib;
switch_module_load_t switch_module_load;
switch_module_runtime_t switch_module_runtime;
switch_module_shutdown_t switch_module_shutdown;
switch_memory_pool_t *pool;
switch_status_t status;
switch_thread_t *thread;
switch_bool_t shutting_down;
switch_loadable_module_type_t type;
}; typedef struct switch_loadable_module switch_loadable_module_t;
2、switch_loadable_module_interface
struct switch_loadable_module_interface {
/*! the name of the module */
const char *module_name;
/*! the table of endpoints the module has implemented */
switch_endpoint_interface_t *endpoint_interface;
/*! the table of timers the module has implemented */
switch_timer_interface_t *timer_interface;
/*! the table of dialplans the module has implemented */
switch_dialplan_interface_t *dialplan_interface;
/*! the table of codecs the module has implemented */
switch_codec_interface_t *codec_interface;
/*! the table of applications the module has implemented */
switch_application_interface_t *application_interface;
/*! the table of chat applications the module has implemented */
switch_chat_application_interface_t *chat_application_interface;
/*! the table of api functions the module has implemented */
switch_api_interface_t *api_interface;
/*! the table of json api functions the module has implemented */
switch_json_api_interface_t *json_api_interface;
/*! the table of file formats the module has implemented */
switch_file_interface_t *file_interface;
/*! the table of speech interfaces the module has implemented */
switch_speech_interface_t *speech_interface;
/*! the table of directory interfaces the module has implemented */
switch_directory_interface_t *directory_interface;
/*! the table of chat interfaces the module has implemented */
switch_chat_interface_t *chat_interface;
/*! the table of say interfaces the module has implemented */
switch_say_interface_t *say_interface;
/*! the table of asr interfaces the module has implemented */
switch_asr_interface_t *asr_interface;
/*! the table of management interfaces the module has implemented */
switch_management_interface_t *management_interface;
/*! the table of limit interfaces the module has implemented */
switch_limit_interface_t *limit_interface;
/*! the table of database interfaces the module has implemented */
switch_database_interface_t *database_interface;
switch_thread_rwlock_t *rwlock;
int refs;
switch_memory_pool_t *pool;
}; typedef struct switch_loadable_module_interface switch_loadable_module_interface_t;
SWITCH_DECLARE(switch_loadable_module_interface_t *) switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name)
{
switch_loadable_module_interface_t *mod; mod = switch_core_alloc(pool, sizeof(switch_loadable_module_interface_t));
switch_assert(mod != NULL); mod->pool = pool; mod->module_name = switch_core_strdup(mod->pool, name);
switch_thread_rwlock_create(&mod->rwlock, mod->pool);
return mod;
}
*module_interface = switch_loadable_module_create_module_interface(pool, modname); rtc_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
rtc_endpoint_interface->interface_name = "rtc";
rtc_endpoint_interface->io_routines = &rtc_io_routines;
rtc_endpoint_interface->state_handler = &rtc_event_handlers;
rtc_endpoint_interface->recover_callback = rtc_recover_callback;
SWITCH_DECLARE(void *) switch_loadable_module_create_interface(switch_loadable_module_interface_t *mod, switch_module_interface_name_t iname)
{ switch (iname) {
case SWITCH_ENDPOINT_INTERFACE:
ALLOC_INTERFACE(endpoint) case SWITCH_TIMER_INTERFACE:
ALLOC_INTERFACE(timer) case SWITCH_DIALPLAN_INTERFACE:
ALLOC_INTERFACE(dialplan) case SWITCH_CODEC_INTERFACE:
ALLOC_INTERFACE(codec) case SWITCH_APPLICATION_INTERFACE:
ALLOC_INTERFACE(application) case SWITCH_CHAT_APPLICATION_INTERFACE:
ALLOC_INTERFACE(chat_application) case SWITCH_API_INTERFACE:
ALLOC_INTERFACE(api) case SWITCH_JSON_API_INTERFACE:
ALLOC_INTERFACE(json_api) case SWITCH_FILE_INTERFACE:
ALLOC_INTERFACE(file) case SWITCH_SPEECH_INTERFACE:
ALLOC_INTERFACE(speech) case SWITCH_DIRECTORY_INTERFACE:
ALLOC_INTERFACE(directory) case SWITCH_CHAT_INTERFACE:
ALLOC_INTERFACE(chat) case SWITCH_SAY_INTERFACE:
ALLOC_INTERFACE(say) case SWITCH_ASR_INTERFACE:
ALLOC_INTERFACE(asr) case SWITCH_MANAGEMENT_INTERFACE:
ALLOC_INTERFACE(management) case SWITCH_LIMIT_INTERFACE:
ALLOC_INTERFACE(limit) case SWITCH_DATABASE_INTERFACE:
ALLOC_INTERFACE(database) default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Module Type!\n");
return NULL;
}
}
3、switch_endpoint_interface_t
struct switch_endpoint_interface {
/*! the interface's name */
const char *interface_name; /*! channel abstraction methods */
switch_io_routines_t *io_routines; /*! state machine methods */
switch_state_handler_table_t *state_handler; /*! private information */
void *private_info; switch_thread_rwlock_t *rwlock;
int refs;
switch_mutex_t *reflock; /* parent */
switch_loadable_module_interface_t *parent; /* to facilitate linking */
struct switch_endpoint_interface *next; switch_core_recover_callback_t recover_callback; }; typedef struct switch_endpoint_interface switch_endpoint_interface_t;
4、switch_io_routines
struct switch_io_routines {
/*! creates an outgoing session from given session, caller profile */
switch_io_outgoing_channel_t outgoing_channel;
/*! read a frame from a session */
switch_io_read_frame_t read_frame;
/*! write a frame to a session */
switch_io_write_frame_t write_frame;
/*! send a kill signal to the session's channel */
switch_io_kill_channel_t kill_channel;
/*! send a string of DTMF digits to a session's channel */
switch_io_send_dtmf_t send_dtmf;
/*! receive a message from another session */
switch_io_receive_message_t receive_message;
/*! queue a message for another session */
switch_io_receive_event_t receive_event;
/*! change a sessions channel state */
switch_io_state_change_t state_change;
/*! read a video frame from a session */
switch_io_read_video_frame_t read_video_frame;
/*! write a video frame to a session */
switch_io_write_video_frame_t write_video_frame;
/*! read a video frame from a session */
switch_io_read_text_frame_t read_text_frame;
/*! write a video frame to a session */
switch_io_write_text_frame_t write_text_frame;
/*! change a sessions channel run state */
switch_io_state_run_t state_run;
/*! get sessions jitterbuffer */
switch_io_get_jb_t get_jb;
void *padding[10];
}; typedef struct switch_io_routines switch_io_routines_t;
5、switch_state_handler_table_t
struct switch_state_handler_table {
/*! executed when the state changes to init */
switch_state_handler_t on_init;
/*! executed when the state changes to routing */
switch_state_handler_t on_routing;
/*! executed when the state changes to execute */
switch_state_handler_t on_execute;
/*! executed when the state changes to hangup */
switch_state_handler_t on_hangup;
/*! executed when the state changes to exchange_media */
switch_state_handler_t on_exchange_media;
/*! executed when the state changes to soft_execute */
switch_state_handler_t on_soft_execute;
/*! executed when the state changes to consume_media */
switch_state_handler_t on_consume_media;
/*! executed when the state changes to hibernate */
switch_state_handler_t on_hibernate;
/*! executed when the state changes to reset */
switch_state_handler_t on_reset;
/*! executed when the state changes to park */
switch_state_handler_t on_park;
/*! executed when the state changes to reporting */
switch_state_handler_t on_reporting;
/*! executed when the state changes to destroy */
switch_state_handler_t on_destroy;
int flags;
void *padding[10];
}; typedef struct switch_state_handler_table switch_state_handler_table_t;
case CS_ROUTING: /* Look for a dialplan and find something to do */
STATE_MACRO(routing, "ROUTING");
break;
case CS_RESET: /* Reset */
STATE_MACRO(reset, "RESET");
break;
/* These other states are intended for prolonged durations so we do not signal lock for them */
case CS_EXECUTE: /* Execute an Operation */
STATE_MACRO(execute, "EXECUTE");
break;
case CS_EXCHANGE_MEDIA: /* loop all data back to source */
STATE_MACRO(exchange_media, "EXCHANGE_MEDIA");
break;
case CS_SOFT_EXECUTE: /* send/recieve data to/from another channel */
STATE_MACRO(soft_execute, "SOFT_EXECUTE");
break;
case CS_PARK: /* wait in limbo */
STATE_MACRO(park, "PARK");
break;
case CS_CONSUME_MEDIA: /* wait in limbo */
STATE_MACRO(consume_media, "CONSUME_MEDIA");
break;
case CS_HIBERNATE: /* sleep */
STATE_MACRO(hibernate, "HIBERNATE");
break;
四、模块编写示例
1、编写c风格的endpoint模块
2)修改文件名
4)修改编译选项
7)安装模块
8)加载模块
c风格endpoint模块编译及运行效果视频:
关注微信公众号(聊聊博文,文末可扫码)后回复 2023052801 获取。
2、编写c++风格的endpoint模块
c++风格endpoint模块编译及运行效果视频:
关注微信公众号(聊聊博文,文末可扫码)后回复 2023052802 获取。
五、资源下载
本文涉及源码和文件,可以从如下途径获取:
关注微信公众号(聊聊博文,文末可扫码)后回复 20230528 获取。
FreeSWITCH添加自定义endpoint的更多相关文章
- 《FreeSWITCH: VoIP实战》:SIP 模块 - mod_sofia
SIP 模块是 FreeSWITCH 的主要模块,所以,值得拿出专门一章来讲解. 在前几章时里,你肯定见过几次 sofia 这个词,只是或许还不知道是什么意思.是这样的,Sofia-SIP 是由诺基亚 ...
- Freeswitch配置之sofia
SIP模块 - mod_sofia SIP 模块是 FreeSWITCH的主要模块. 在 FreeSWITCH中,实现一些互联协议接口的模块称为 Endpoint.FreeSWITH支持很多的 End ...
- SpringCloud学习2-Springboot监控模块(actuator)
前言 学习一项新技术最大的困难是什么? 是资料.让人高兴的是找到了一本系统学习Spring Cloud的教程,<Spring Cloud微服务实战>, 接下来的学习目标将以此书顺序演进. ...
- springcloud添加自定义的endpoint来实现平滑发布
在我之前的文章 springcloud如何实现服务的平滑发布 里介绍了基于pause的发布方案. 平滑发布的核心思想就是:所有服务的调用者不再调用该服务了就表示安全的将服务kill掉. 另外actu ...
- freeswitch 拨号时添加自定义变量
Using Channel Variables in Dialplan Condition Statements Channel variables can be used in conditions ...
- FreeSWITCH的originate命令解析及示例
FreeSWITCH版本:1.10.9 操作系统:CentOS 7.6.1810 originate经常用于发起呼叫,在实际工作过程中用到的也比较多,今天总结下基本用法,也方便我以后查阅. 一.wik ...
- 生成freeswitch事件的几种方式
本文描述了生成freeswitch事件的几种方式,这里记录下,也方便我以后查阅. 操作系统:debian8.5_x64 freeswitch 版本 : 1.6.8 在freeswitch代码中加入事件 ...
- WCF之添加自定义用户名密码认证
1.创建WCF服务应用以及调用客户端(请自行google). 2.创建X509证书 cmd 进入 C:\Program Files\Microsoft SDKs\Windows\v6. ...
- FreeSwitch 终端命令详细介绍
FreeSwitch版本:1.6.9 以下为部分终端命令 alias 语法: alias [add|stickyadd] <alias> <command> | del [&l ...
- freeswitch编译安装,初探, 以及联合sipgateway, webrtc server的使用场景。
本文主要记录freeswitch学习过程. 一 安装freeswitch NOTE 以下两种安装方式,再安装的过程中遇到了不少问题,印象比较深刻的就是lua库找到不到这个问题.这个问题发生在make ...
随机推荐
- 【OGF生成函数板子题】牛客编程巅峰赛S2第11场 C 挑选方案问题
upd 2022-01-26 我找到了个题集 牛客竞赛数学专题班生成函数I(线性递推关系.生成函数概念与公式推导.暴力计算) 目录 题目链接 题面 解题思路 AC代码 题目链接 https://ac. ...
- IDEA集成Gitee
配置Git 在设置里面点击Git,点击选择git安装目录下的bin目录下的git.exe,点击Test,出现版本号,证明配置成功. 配置码云 在设置里面按照下图步骤,即可成功配置码云 安装Gitee插 ...
- eval有时候也可以用,而且有奇效
eval,一个我曾经避之不及的函数,最近我对它产生了一点新的感触:eval有时候也可以用,有奇效. 一般在使用js进行开发时,是不建议使用eval这类函数的.在JavaScript中,eval可以计算 ...
- 对一些常用RDD算子的总结
虽然目前逐渐sql化,但是掌握 RDD 常用算子是做好 Spark 应用开发的基础,而数据转换类算子则是基础中的基础,因此学习这些算子还是很有必要的. 这篇博客主要参考Spark官方文档中RDD编程一 ...
- 解密Prompt系列4. 升级Instruction Tuning:Flan/T0/InstructGPT/TKInstruct
这一章我们聊聊指令微调,指令微调和前3章介绍的prompt有什么关系呢?哈哈只要你细品,你就会发现大家对prompt和instruction的定义存在些出入,部分认为instruction是promp ...
- Logoist - 适用于设计师以及初次使用者的快速制作精美 logo 工具
>从简单的标识到设计开发.它只需要一点 ...
- mongodb导入数据,保创建新项目
1.回顾 2.导入数据 2.1 excel数据表格 2.2 设计导入数据的路由 routes/users.js router.get('/upload', function (req, res, ne ...
- 一些随笔No.3
1.开发应以业务为导向,技术只是手段 2.视觉上和程序上不一定是完全符合 比如,我所说的阻塞是视觉层面,或者是对用户而言的阻塞,而不是程序意义上的.我也许会传完参的同时销毁原组件,生成一个看起来一模一 ...
- [Java SE]Java8新特性——默认方法
1 简述 默认方法就是接口可以有实现方法,而且可以不需要实现类去实现其方法 默认方法(default void hello()) := 一个在接口里面有了一个(默认)实现的方法 1. 子类优先继承父类 ...
- 全网最详细中英文ChatGPT-GPT-4示例文档-智能聊天机器人从0到1快速入门——官网推荐的48种最佳应用场景(附python/node.js/curl命令源代码,小白也能学)
目录 Introduce 简介 setting 设置 Prompt 提示 Sample response 回复样本 API request 接口请求 python接口请求示例 node.js接口请求示 ...