- 初始化
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相關的還不是看得很細,本文檔先編寫最基本的,後面瞭解更深入了再補充。