freeswitch esl的同步与异步

文章目录

  • 前言
  • 同步
    • 事件锁
      • 自己构造事件
      • 直接设置连接的属性
      • 主要解决的问题
  • 使用esl_oop

前言

使用 esl 的c++ 来进行拨号计划的控制,有几个细节,困扰了我好几天。这些都是使用lua脚本所没有碰到的。

同步

这里有说明。
主要是这句


 


async 表示异步执行
full 表示所有的内置程序都可用。必须要要这个
举例

1,	t_pEslConn->execute("playback", "/usr/local/freeswitch/sounds/tone_callout/CallOut1.wav");
2,	t_pEslConn->execute("hangup");
3,	t_pEslConn->execute("playback", "/usr/local/freeswitch/sounds/tone_callout/CallOut2.wav");

如果是async模式,这3句都会走。
如果是在正常运行的模式下,根本听不到声音,就挂断了。
如果在第二行第三行打上断点,当走到第二行的时候(第二行还没运行),可以听到第一行运行的音乐;再走一步,音乐中断电话挂断;再走一步,没效果了(因为电话已经挂断了)。

如果是 同步模式。playback是阻塞运行的,只能在第一行运行完之后才能走到第二行。

事件锁

自己构造事件

(这种方式有点麻烦,可以直接看下一条)
生成freeswitch事件的几种方式
c++ esl 创建ESLevent sendMSG

	ESLconnection* t_pEslConn = 、、、;
	
	ESLevent *t_willSendEvent = new ESLevent("CUSTOM","calltest1::calltest1_sub");
	t_willSendEvent->addHeader("call-command","execute");
	t_willSendEvent->addHeader("execute-app-name","playback");
	t_willSendEvent->addHeader("execute-app-arg","/usr/local/freeswitch/sounds/tone_callout/CallOut1.wav");
	t_willSendEvent->addHeader("event-lock", "true");
	const char* t_cWillSendSerial = t_willSendEvent->serialize();//这一步是为了看构造的对不对
	int t_iMsgRtn = t_pEslConn->sendMSG(t_willSendEvent); 

直接设置连接的属性

t_pEslConn->setEventLock("1");  //这一句保证那些异步运行的程序能按顺序执行 

里面调用了一个函数

int ESLconnection::setEventLock(const char *val)
{
	if (val) {
		handle.event_lock = esl_true(val);
	}
	return handle.event_lock;
}
//下面这个函数看起来很有道理
static __inline__ int esl_true(const char *expr) {
	return (expr && (!strcasecmp(expr, "yes")
					 || !strcasecmp(expr, "on")
					 || !strcasecmp(expr, "true")
					 || !strcasecmp(expr, "enabled")
					 || !strcasecmp(expr, "active")
					 || !strcasecmp(expr, "allow")
					 || atoi(expr)));
}

再拿这三行来说

1,	t_pEslConn->execute("playback", "/usr/local/freeswitch/sounds/tone_callout/CallOut1.wav");
2,	t_pEslConn->execute("hangup");
3,	t_pEslConn->execute("playback", "/usr/local/freeswitch/sounds/tone_callout/CallOut2.wav");

设置 async full 之后。
正常运行的时候,三行会直接走下去,但是实际运行的时候,会先播放完第一行的音乐,然后再走第二行挂断。
这样就达到了lua脚本的效果。

主要解决的问题

	string t_args;
	t_args += t_pALegUuid;
	t_args += " ";
	t_args += t_pBLegUuid;
	const char * t_cArgs = t_args.c_str();
	ESLevent* t_call_event2 = t_pEslConn->bgapi("uuid_bridge", t_cArgs);

uuid_bridge 这个api属相有点特别,如果是在同步模式下,根本对接不起来。但是esl程序杀死后,a腿与b腿却又连起来了。貌似是里面有个程序在运行。
因此只能使用异步模式。

使用esl_oop

也就是使用esl的c++接口,通过底层代码可知,里面实际上封装的是esl的c接口。
但是这个面向对象使用起来很操蛋。

ESLconnection 这个对象的接口的返回值是ESLevent,你要自己去管理它的内存释放。
我一般写成下面这个样子

auto t_rtn =  make_shared(t_pESLConn->execute("playback", audioPath.c_str()));
//或者
ESLevent* t_pEslInfo = t_pEslConn->getInfo();
shared_ptr t_spEslInfo(t_pEslInfo);//为了能自动释放内存

我翻看了源码,确实要我们自己手动管理这个返回值的释放。

你可能感兴趣的:(freeswitch)