zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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,开发时注意这一点“收到事件的先后顺序”即可。

  • 相关阅读:
    axios的使用/
    jQuery好玩的双向控制轮播
    vue的路由跳转方式/两种
    vfor的某些注意事项
    vue使用插件时不能撑满页面?
    swiper中的双向控制器不生效问题
    sass的安装及使用
    .net必懂题
    软件架构初读01
    EJB
  • 原文地址:https://www.cnblogs.com/cqvoip/p/8079067.html
Copyright © 2011-2022 走看看