freeswitch Session dtmf callback的触发过程

本文详细介绍了Freeswitch中Session创建后,如何通过switch_core_session_thread_launch启动线程,以及在处理DTMF事件时的状态机流程。在CS_EXCHANGE_MEDIA状态下,音频桥接函数audio_bridge_on_exchange_media触发audio_bridge_thread,进而调用dtmf_callback,并最终在lua环境中运行run_dtmf_callback,实现DTMF事件的回调和处理。
摘要由CSDN通过智能技术生成

在创建一个Session后会调用switch_core_session_thread_launch()创建一个对应的线程

SWITCH_DECLARE(switch_status_t) switch_core_session_thread_launch(switch_core_session_t *session)
{
    switch_status_t status = SWITCH_STATUS_FALSE;
    switch_thread_t *thread;
    switch_threadattr_t *thd_attr;

    if (switch_test_flag(session, SSF_THREAD_RUNNING) || switch_test_flag(session, SSF_THREAD_STARTED)) {
        status = SWITCH_STATUS_INUSE;
        goto end;
    }


    if (switch_test_flag((&runtime), SCF_SESSION_THREAD_POOL)) {
        return switch_core_session_thread_pool_launch(session);
    }

    switch_mutex_lock(session->mutex);

    if (switch_test_flag(session, SSF_THREAD_RUNNING)) {
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot double-launch thread!\n");
    } else if (switch_test_flag(session, SSF_THREAD_STARTED)) {
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot launch thread again after it has already been run!\n");
    } else {
        switch_set_flag(session, SSF_THREAD_RUNNING);
        switch_set_flag(session, SSF_THREAD_STARTED);

        switch_threadattr_create(&thd_attr, session->pool);
        switch_threadattr_detach_set(thd_attr, 1);
        switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);

        if (switch_thread_create(&thread, thd_attr, switch_core_session_thread, session, session->pool) == SWITCH_STATUS_SUCCESS) {
            switch_set_flag(session, SSF_THREAD_STARTED);
            status = SWITCH_STATUS_SUCCESS;
        } else {
            switch_clear_flag(session, SSF_THREAD_RUNNING);
            switch_clear_flag(session, SSF_THREAD_STARTED); 
            switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot create thread!\n");
            thread_launch_failure();
        }
    }

    switch_mutex_unlock(session->mutex);

 end:

    return status;
}

在非使用线程池的情况下会调用switch_thread_create创建一个新线程,在这个新线程里面执行:switch_core_session_thread

static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thread, void *obj)
{
    switch_core_session_t *session = obj;
    switch_event_t *event;
    char *event_str = NULL;
    const char *val;

    session->thread = thread;
    session->thread_id = switch_thread_self();

    switch_core_session_run(session);
    switch_core_media_bug_remove_all(session);

    if (session->soft_lock) {
        uint32_t loops = session->soft_lock * 10;

        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session %" SWITCH_SIZE_T_FMT " (%s) Soft-Locked, "
                          "Waiting %u for external entities\n",
                          session->id, switch_channel_get_name(session->channel), session->soft_lock);

        while(--loops > 0) {
            if (!session->soft_lock) break;
            switch_yield(100000);
        }

    }

    switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session %" SWITCH_SIZE_T_FMT " (%s) Locked, Waiting on external entities\n",
                      session->id, switch_channel_get_name(session->channel));
    switch_core_session_write_lock(session);
    switch_set_flag(session, SSF_DESTROYED);

    if ((val = switch_channel_get_variable(session->channel, "memory_debug")) && switch_true(val)) {
        if (switch_event_create(&event, SWITCH_EVENT_GENERAL) == SWITCH_STATUS_SUCCESS) {
            switch_channel_event_set_data(session->channel, event);
            switch_event_serialize(event, &event_str, SWITCH_FALSE);
            switch_assert(event_str);
            switch_core_memory_pool_tag(switch_core_session_get_pool(session), switch_core_session_strdup(session, event_str));
            free(event
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值