mod_conference ESL控制三(程序)
第一篇描述了mod_conference控制原理,第二篇描述了conference相关事件,接下来对esl内联程序做简要说明。
由于event-socket采用TCP协议,因此需要一个线程与freeswitch保持长连接,轮询相关事件并上报应用层;另外一个线程接受应用层命令,并控制freeswitch。这两个线程需要共享一个重要参数esl连接"esl_handle_t *pHanndle";当然线程二也可以连接到fs,与线程一使用不同的esl_handle_t,不订阅事件即可。本人采用两个线程共享一个esl链接方式。
备注:以下代码未测试,仅作参考
线程一:
esl_handle_t handle = {{0}};
esl_status_t status;
while((status=esl_connect(&handle, "127.0.0.1", 8021, NULL, "ClueCon")) != ESL_SUCCESS)
{
printf("esl_connect error:%s:%d\n",handle.err,status);
sleep(5);
}
esl_events(&handle, ESL_EVENT_TYPE_PLAIN, "CHANNEL_CREATE CHANNEL_ANSWER CHANNEL_HANGUP_COMPLETE DTMF CUSTOM conference::maintenance");
esl_filter(&handle,"action","conference-create");
esl_filter(&handle,"action","conference-destroy");
esl_filter(&handle,"action","add-member");
esl_filter(&handle,"action","del-member");
esl_filter(&handle,"action","mute-member");
esl_filter(&handle,"action","unmute-member");
//esl_filter(&handle,"action","kick-member");
//esl_filter(&handle,"action","floor-change");
esl_filter(&handle,"Event-Name","DTMF");
esl_filter(&handle,"Event-Name","CHANNEL_CREATE");
esl_filter(&handle,"Event-Name","CHANNEL_ANSWER");
esl_filter(&handle,"Event-Name","CHANNEL_HANGUP_COMPLETE");
while((status = esl_recv_timed(&handle,1000)) != ESL_FAIL)
{
if(status != ESL_SUCCESS)
{
usleep(100);
continue;
}
const char *type = esl_event_get_header(handle.last_event, "content-type");
if(type==NULL || strcasecmp(type, "text/event-plain")!=0)
{
continue;
}
if(handle.last_event->body!=NULL)
{
proc_event(handle.last_event->body);
}
}
printf("diconnected:%d\n",status);//此处可作断线重连操作
esl_disconnect(&handle);
上述代码连接到fs event-socket,订阅事件、过滤事件、接收事件并处理。proc_event函数对订阅的事件进行解码、识别、处理。
线程二:业务线程,自行实现,以下说明如何向fs发命令。
char cmd[128]={0x00};
uuid_t uuid;char str[36];
uuid_generate(uuid);
uuid_unparse(uuid, str);
snprintf(cmd,256,"bgapi originate "
"{origination_uuid=%s,bridge_early_media=false,ignore_early_media=true,effective_caller_id_number=%s,dtmf_type=%s,execute_on_answer=start_dtmf}"
"sofia/gateway/%s/%s %s XML default"
,str,pFsm->ecp_phone,gw_dtmf_type,gw_name,phone,pFsm->confname);
//save_uuid_taskid(str,pFsm->taskid);
if(pFsm->fsnode->node_handle != NULL)
esl_send(pFsm->fsnode->node_handle,cmd);
当然,首先得取到esl连接的句柄handle,向fs发消息需要该handle,其次必须得校验该handle,防止esl断线了还调用esl_send进行发送导致出错。也可进一步对esl_send返回值校验,这里忽略了。
具体使用可以参考esl源代码获取相关API。
2015/2/14补充:
为了便于会场控制、计费,最终实现时取消了CHANNEL_HANGUP_COMPLETE事件的订阅,改为订阅CHANNEL_HANGUP事件。mod_conference对CHANNELS内事件作了“订阅”,当收到CHANNEL_HANGUP事件时会在会场中踢出对应的参会者,进而产生MEMBER-DEL事件,CHANNEL_HANGUP_COMPLETE在最后产生。即收到的事件顺序为:CHANNEL_CREATE->CHANNEL_ANSWER->MEMBER_ADD->CHANNEL_HANGUP->MEMBER-DEL->CHANNEL_HANGUP_COMPLETE,开发时注意这一点“收到事件的先后顺序”即可。
mod_conference ESL控制三(程序)的更多相关文章
- mod_conference ESL控制二(事件)
根据上篇所述功能需求,esl需要处理以下几类事件: ESL_EVENT_CHANNEL_* #channel相关事件,用户判断参会者是否应答.计费 DTMF事件 #识别参会者按键,根据按键进行操作( ...
- mod_conference ESL控制一(原理)
本文介绍通过freeswitch mod_conference 的配置和APP,以及如何通过这些事件实现会议控制. 需求 ESL内联,发起会议.加人.踢人.静音.恢复静音.申请发言.结束会议等基础功能 ...
- PIC12F629帮我用C语言写个程序,控制三个LED亮灭
http://power.baidu.com/question/240873584599025684.html?entry=browse_difficult PIC12F629帮我用C语言写个程序,控 ...
- 使用C#模拟键盘输入、鼠标移动和点击、设置光标位置及控制应用程序的显示
1.模拟键盘输入(SendKeys) 功能:将一个或多个按键消息发送到活动窗口,就如同在键盘上进行输入一样. 语法:SendKeys.Send(string keys);SendKeys.SendWa ...
- 控制 Android 程序使用的内存
如何控制应用程序使用的内存? 1. 记得关闭启动的服务 当服务中的任务完成后,要记得停止该服务.可以考虑使用 IntentService,因为 IntentService 在完成任务后会自动停止. 2 ...
- c#控制WPF程序自动登录(Automation方式实现)
说明:winForm窗体,可以通过win32接口dll的findWindow之类的函数来实现查找winform窗口,mfc窗口等. 但是wpf却是不实用这些,可以靠automation方式来进行操作. ...
- Linux及安全实践三——程序破解
Linux及安全实践三--程序破解 一.基本知识 常用指令机器码 指令 作用 机器码 nop 无作用(no operation) 90 call 调用子程序,子程序以ret结尾 e8 ret 返回程序 ...
- vscode 显示"没有活动的源代码控制提供程序“处理
不知为何我的 VS Code 在 1.25 版本开始就一直 ”没有活动的源代码控制提供程序“,找了好几天都没找到,今天终于找到怎么处理了, 切换到插件中找到下图对应的 Git (可以直接再上面搜索框输 ...
- VSCode Git 没有活动的源代码控制提供程序
主要原因:我以前安装的Git只允许在Git-Bash中运行,需要重新安装Git,选择允许三方软件的那个选项,然后安装Git插件,修改git.path即可. 以下是解决过程中的尝试,记录如下,实际上只需 ...
随机推荐
- 剑指offer(12)数值的整数次方
题目描述 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. 题目分析 这道题用传统的方法也可以做,只不过效率太低,这里我们用到快速幂的方法 ...
- HDU3033 I love sneakers!———分组背包
这题的动态转移方程真是妙啊,完美的解决了每一种衣服必须买一件的情况. if(a[x][i-c[x][j].x]!=-1) a[x][i]=max(a[x][i],a[x][i-c[x][j].x]+c ...
- flex外包团队—北京动点软件:推荐一本不错的Flex书籍
内容介绍:Ready to put your ActionScript 3 skills to work on mobile apps? This hands-on book walks you th ...
- Java GC机制
GC机制的基本算法是:分代收集,这个不用赘述.下面阐述每个分代的收集方法. 年轻代: 事实上,在上一节,已经介绍了新生代的主要垃圾回收方法,在新生代中,使用“停止-复制”算法进行清理,将新生代内存分为 ...
- robot framework学习二-----元素定位
文章摘自:https://www.cnblogs.com/fnng/p/3901391.html 不要误认为Robot framework 只是个web UI测试工具,更正确的理解Robot fram ...
- Android 开发版本统一
一.概述 对于 Android 开发版本的统一涉及到的东西就是 Gradle 中的全局设置,我们通过配置 gradle 也就是编写 Groovy 代码将开发中的版本号设置为全局参数.这样就能够在 mo ...
- Set集合中的treeSet问题:cannot be cast to java.lang.Comparable;
使用TreeSet保存自定义对象时, 必须让定义对象的类实现Comparable接口,并重写compareTo()方法 否则报 实体类User:cannot be cast to java.lang. ...
- [noip2017] 前三周总结
[noip2017] 前三周总结 10.20 Fri. Day -21 距离noip复赛还有3周了,进行最后的冲刺! 首先要说今天过得并不好,和我早上比赛打挂了有关系. 不过每一次比赛都能暴露出我的漏 ...
- Linux获取so/ko文件版本号教程
一.需要获取版本号的原因 从使用角度而言,有时只有特定版本的库才支持某些功能,所以我们需要确定库文件版本号. 从安全加固角度而言,有些版本存在漏洞有些版本不存在漏洞,所以我们需要获取版本号以确定当前使 ...
- 实践:搭建基于Load Balancer的MySql Cluster
服务器规划: 整套系统全部在rhel5u1 server 64位版本下,由基于xen的虚拟机搭建,其中集群管理节点*2.SQL节点*2.数据节点*4.Web服务节点*2组成,其中数据节点做成2个组,每 ...