- 初始化
channel在switch_channel.c实现,在switch_channel.h定义相关数据结构。在第2章节初始化的时候,在核心初始化里会调用channel_global初始化。
- static struct {
- switch_memory_pool_t *pool;
- switch_hash_t *device_hash;
- switch_mutex_t *device_mutex;
- switch_device_state_binding_t *device_bindings;
- } globals;
- SWITCH_DECLARE(void) switch_channel_global_init(switch_memory_pool_t *pool)
- {
- memset(&globals, 0, sizeof(globals));
- globals.pool = pool;
- switch_mutex_init(&globals.device_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_core_hash_init(&globals.device_hash);
- }
channel也有一个全局结构globals,其中比较重要的设备容器device_hash和设备状态处理device_bindings,还不明白,初步猜测channel跟设备有关。
- 创建channel
channel和session是一一对应的,上一章讲过,创建session的时候,会同时创建channel并初始化。
。
- SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_endpoint_interface_t
- *endpoint_interface,
- switch_call_direction_t direction,
- switch_originate_flag_t originate_flags,
- switch_memory_pool_t **pool, const char *use_uuid)
- {
- switch_memory_pool_t *usepool;
- switch_core_session_t *session;
- switch_uuid_t uuid;
- ...
- //申请session的channel内存
- if (switch_channel_alloc(&session->channel, direction, session->pool) != SWITCH_STATUS_SUCCESS) {
- abort();
- }
- //初始化channel
- switch_channel_init(session->channel, session, CS_NEW, 0);
- if (direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
- switch_channel_set_flag(session->channel, CF_OUTBOUND);
- }
- //设置一些channel的变量值
- switch_channel_set_variable(session->channel, "uuid", session->uuid_str);
- switch_channel_set_variable(session->channel, "call_uuid", session->uuid_str);
- switch_channel_set_variable_printf(session->channel, "session_id", "%u", session->id);
- return session;
- }
创建session的时候,同时对channel干了三件事:申请channel内存、初始化channel、设置一些channel变量。下面分析下channel数据结构和这三个步骤。
-
- switch_channel
- struct switch_channel {
- char *name;
- switch_call_direction_t direction;
- switch_call_direction_t logical_direction;
- switch_queue_t *dtmf_queue;
- switch_queue_t *dtmf_log_queue;
- switch_mutex_t*dtmf_mutex;
- switch_mutex_t *flag_mutex;
- switch_mutex_t *state_mutex;
- switch_mutex_t *thread_mutex;
- switch_mutex_t *profile_mutex;
- switch_core_session_t *session;
- switch_channel_state_t state;//状态
- switch_channel_state_t running_state;//运行状态
- switch_channel_callstate_t callstate;//通话状态
- uint32_t flags[CF_FLAG_MAX];
- uint32_t caps[CC_FLAG_MAX];
- uint8_t state_flags[CF_FLAG_MAX];
- uint32_t private_flags;
- switch_caller_profile_t *caller_profile;//
- const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];//状态回调
- int state_handler_index;
- switch_event_t *variables;
- switch_event_t *scope_variables;
- switch_hash_t *private_hash;
- switch_hash_t *app_flag_hash;
- switch_call_cause_t hangup_cause;
- int vi;
- int event_count;
- int profile_index;
- opaque_channel_flag_t opaque_flags;
- switch_originator_type_t last_profile_type;
- switch_caller_extension_t *queued_extension;
- switch_event_t *app_list;
- switch_event_t *api_list;
- switch_event_t *var_list;
- switch_hold_record_t *hold_record;
- switch_device_node_t *device_node;
- char *device_id;
- };
channel结构体全部列举出来了,这里只看一些比较重要的成员:
1、通道状态state、running_state、状态回调state_handlers。这个在上一章节session的时候就有讲到状态机。
- typedef enum {
- CS_NEW,
- CS_INIT,
- CS_ROUTING,
- CS_SOFT_EXECUTE,
- CS_EXECUTE,
- CS_EXCHANGE_MEDIA,
- CS_PARK,
- CS_CONSUME_MEDIA,
- CS_HIBERNATE,
- CS_RESET,
- CS_HANGUP,
- CS_REPORTING,
- CS_DESTROY,
- CS_NONE
- } switch_channel_state_t;
刚创建channel的时候是CS_NEW,然后进行初始化进入CS_INIT,有来电进入路由后,就是CS_ROUTING,路由解析完,进入执行action时变成CS_EXECUTE。什么状态执行什么操作,看状态机的实现函数,这里就不展开。
2、跟通话call相关的有callstate、caller_profile。call的相关代码还未跟踪,这里先列出call状态。
- typedef enum {
- CCS_DOWN,
- CCS_DIALING,
- CCS_RINGING,
- CCS_EARLY,
- CCS_ACTIVE,
- CCS_HELD,
- CCS_RING_WAIT,
- CCS_HANGUP,
- CCS_UNHELD
- } switch_channel_callstate_t;
从这些状态来看,也是比较清晰的,比如CSS_RINGING应该是本路通话在响铃时候设置。
3、跟设备device相关的,预留后面补充。
-
- 申请channel内存
申请channel结构体内存使用switch_channel_alloc,该函数除了申请内存外,还初始化若干个默认值,除了创建通道变量channel->variables外,其它没什么重要的。
- SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel, switch_call_direction_t direction, switch_memory_pool_t *pool)
- {
- switch_assert(pool != NULL);
- if (((*channel) = switch_core_alloc(pool, sizeof(switch_channel_t))) == 0) {
- return SWITCH_STATUS_MEMERR;
- }
- switch_event_create_plain(&(*channel)->variables, SWITCH_EVENT_CHANNEL_DATA);
- switch_core_hash_init(&(*channel)->private_hash);
- switch_queue_create(&(*channel)->dtmf_queue, SWITCH_DTMF_LOG_LEN, pool);
- switch_queue_create(&(*channel)->dtmf_log_queue, SWITCH_DTMF_LOG_LEN, pool);
- switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_mutex_init(&(*channel)->state_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_mutex_init(&(*channel)->thread_mutex, SWITCH_MUTEX_NESTED, pool);
- switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool);
- (*channel)->hangup_cause = SWITCH_CAUSE_NONE;
- (*channel)->name = "";
- (*channel)->direction = (*channel)->logical_direction = direction;
- switch_channel_set_variable(*channel, "direction", switch_channel_direction(*channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
- return SWITCH_STATUS_SUCCESS;
- }
-
- channel初始化
channel初始化调用switch_channel_init,这里很简单,初始化状态,保存channel对应的session,running_state设为CS_NONE,state和running_state什么区别,还不是很清晰。
- SWITCH_DECLARE(switch_status_t) switch_channel_init(switch_channel_t *channel, switch_core_session_t *session, switch_channel_state_t state,
- switch_channel_flag_t flag)
- {
- switch_assert(channel != NULL);
- channel->state = state;
- switch_channel_set_flag(channel, flag);
- channel->session = session;
- channel->running_state = CS_NONE;
- return SWITCH_STATUS_SUCCESS;
- }
channel相关的还不是看得很细,本文档先编写最基本的,后面了解更深入了再补充。