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,开发时注意这一点“收到事件的先后顺序”即可。

posted on 2017-12-21 10:52  angry-baby  阅读(591)  评论(0编辑  收藏  举报

导航