freeswitch系列5 channel

  1. 初始化

channel在switch_channel.c實現,在switch_channel.h定義相關數據結構。在第2章節初始化的時候,在覈心初始化裏會調用channel_global初始化。

 

  1. static struct {  
  2.     switch_memory_pool_t *pool;  
  3.     switch_hash_t *device_hash;  
  4.     switch_mutex_t *device_mutex;  
  5.     switch_device_state_binding_t *device_bindings;  
  6. } globals;  
  7.   
  8. SWITCH_DECLARE(void) switch_channel_global_init(switch_memory_pool_t *pool)  
  9. {  
  10.     memset(&globals, 0, sizeof(globals));  
  11.     globals.pool = pool;  
  12.   
  13.     switch_mutex_init(&globals.device_mutex, SWITCH_MUTEX_NESTED, pool);  
  14.     switch_core_hash_init(&globals.device_hash);  
  15. }

 

 

channel也有一個全局結構globals,其中比較重要的設備容器device_hash和設備狀態處理device_bindings,還不明白,初步猜測channel跟設備有關。

 

  1. 創建channel

channel和session是一一對應的,上一章講過,創建session的時候,會同時創建channel並初始化。

 

  1. SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_endpoint_interface_t  
  2.                                                                          *endpoint_interface,  
  3.                                                                          switch_call_direction_t direction,  
  4.                                                                          switch_originate_flag_t originate_flags,  
  5.                                                                          switch_memory_pool_t **pool, const char *use_uuid)  
  6. {  
  7.     switch_memory_pool_t *usepool;  
  8.     switch_core_session_t *session;  
  9.     switch_uuid_t uuid;  
  10.   
  11. ...  
  12.     //申請session的channel內存  
  13.     if (switch_channel_alloc(&session->channel, direction, session->pool) != SWITCH_STATUS_SUCCESS) {  
  14.         abort();  
  15.     }  
  16.   
  17.     //初始化channel  
  18.     switch_channel_init(session->channel, session, CS_NEW, 0);  
  19.   
  20.     if (direction == SWITCH_CALL_DIRECTION_OUTBOUND) {  
  21.         switch_channel_set_flag(session->channel, CF_OUTBOUND);  
  22.     }  
  23.   
  24.     //設置一些channel的變量  
  25.     switch_channel_set_variable(session->channel, "uuid", session->uuid_str);  
  26.     switch_channel_set_variable(session->channel, "call_uuid", session->uuid_str);  
  27.   
  28.     switch_channel_set_variable_printf(session->channel, "session_id""%u", session->id);  
  29.   
  30.     return session;  
  31. }

 

創建session的時候,同時對channel幹了三件事:申請channel內存、初始化channel、設置一些channel變量。下面分析下channel數據結構和這三個步驟。

    1. switch_channel

 

  1. struct switch_channel {  
  2.     char *name;  
  3.     switch_call_direction_t direction;  
  4.     switch_call_direction_t logical_direction;  
  5.     switch_queue_t *dtmf_queue;  
  6.     switch_queue_t *dtmf_log_queue;  
  7.     switch_mutex_t*dtmf_mutex;  
  8.     switch_mutex_t *flag_mutex;  
  9.     switch_mutex_t *state_mutex;  
  10.     switch_mutex_t *thread_mutex;  
  11.     switch_mutex_t *profile_mutex;  
  12.     switch_core_session_t *session;  
  13.     switch_channel_state_t state;//狀態  
  14.     switch_channel_state_t running_state;//運行狀態  
  15.     switch_channel_callstate_t callstate;//通話狀態  
  16.     uint32_t flags[CF_FLAG_MAX];  
  17.     uint32_t caps[CC_FLAG_MAX];  
  18.     uint8_t state_flags[CF_FLAG_MAX];  
  19.     uint32_t private_flags;  
  20.     switch_caller_profile_t *caller_profile;//  
  21.     const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];//狀態回調  
  22.     int state_handler_index;  
  23.     switch_event_t *variables;  
  24.     switch_event_t *scope_variables;  
  25.     switch_hash_t *private_hash;  
  26.     switch_hash_t *app_flag_hash;  
  27.     switch_call_cause_t hangup_cause;  
  28.     int vi;  
  29.     int event_count;  
  30.     int profile_index;  
  31.     opaque_channel_flag_t opaque_flags;  
  32.     switch_originator_type_t last_profile_type;  
  33.     switch_caller_extension_t *queued_extension;  
  34.     switch_event_t *app_list;  
  35.     switch_event_t *api_list;  
  36.     switch_event_t *var_list;  
  37.     switch_hold_record_t *hold_record;  
  38.     switch_device_node_t *device_node;  
  39.     char *device_id;  
  40. }; 

 

channel結構體全部列舉出來了,這裏只看一些比較重要的成員:

1、通道狀態state、running_state、狀態回調state_handlers。這個在上一章節session的時候就有講到狀態機。

 

  1. typedef enum {  
  2.     CS_NEW,  
  3.     CS_INIT,  
  4.     CS_ROUTING,  
  5.     CS_SOFT_EXECUTE,  
  6.     CS_EXECUTE,  
  7.     CS_EXCHANGE_MEDIA,  
  8.     CS_PARK,  
  9.     CS_CONSUME_MEDIA,  
  10.     CS_HIBERNATE,  
  11.     CS_RESET,  
  12.     CS_HANGUP,  
  13.     CS_REPORTING,  
  14.     CS_DESTROY,  
  15.     CS_NONE  
  16. } switch_channel_state_t;  

 

剛創建channel的時候是CS_NEW,然後進行初始化進入CS_INIT,有來電進入路由後,就是CS_ROUTING,路由解析完,進入執行action時變成CS_EXECUTE。什麼狀態執行什麼操作,看狀態機的實現函數,這裏就不展開。

2、跟通話call相關的有callstate、caller_profile。call的相關代碼還未跟蹤,這裏先列出call狀態。

  1. typedef enum {  
  2.     CCS_DOWN,  
  3.     CCS_DIALING,  
  4.     CCS_RINGING,  
  5.     CCS_EARLY,  
  6.     CCS_ACTIVE,  
  7.     CCS_HELD,  
  8.     CCS_RING_WAIT,  
  9.     CCS_HANGUP,  
  10.     CCS_UNHELD  
  11. } switch_channel_callstate_t;  

 

從這些狀態來看,也是比較清晰的,比如CSS_RINGING應該是本路通話在響鈴時候設置。

3、跟設備device相關的,預留後面補充。

    1. 申請channel內存

申請channel結構體內存使用switch_channel_alloc,該函數除了申請內存外,還初始化若干個默認值,除了創建通道變量channel->variables外,其它沒什麼重要的。

 

  1. SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel, switch_call_direction_t direction, switch_memory_pool_t *pool)  
  2. {  
  3.     switch_assert(pool != NULL);  
  4.   
  5.     if (((*channel) = switch_core_alloc(pool, sizeof(switch_channel_t))) == 0) {  
  6.         return SWITCH_STATUS_MEMERR;  
  7.     }  
  8.   
  9.     switch_event_create_plain(&(*channel)->variables, SWITCH_EVENT_CHANNEL_DATA);  
  10.   
  11.     switch_core_hash_init(&(*channel)->private_hash);  
  12.     switch_queue_create(&(*channel)->dtmf_queue, SWITCH_DTMF_LOG_LEN, pool);  
  13.     switch_queue_create(&(*channel)->dtmf_log_queue, SWITCH_DTMF_LOG_LEN, pool);  
  14.   
  15.     switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool);  
  16.     switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool);  
  17.     switch_mutex_init(&(*channel)->state_mutex, SWITCH_MUTEX_NESTED, pool);  
  18.     switch_mutex_init(&(*channel)->thread_mutex, SWITCH_MUTEX_NESTED, pool);  
  19.     switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool);  
  20.     (*channel)->hangup_cause = SWITCH_CAUSE_NONE;  
  21.     (*channel)->name = "";  
  22.     (*channel)->direction = (*channel)->logical_direction = direction;  
  23.     switch_channel_set_variable(*channel, "direction", switch_channel_direction(*channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");  
  24.   
  25.     return SWITCH_STATUS_SUCCESS;  
  26. }  

 

 

    1. channel初始化

channel初始化調用switch_channel_init,這裏很簡單,初始化狀態,保存channel對應的session,running_state設爲CS_NONE,state和running_state什麼區別,還不是很清晰。

 

  1. SWITCH_DECLARE(switch_status_t) switch_channel_init(switch_channel_t *channel, switch_core_session_t *session, switch_channel_state_t state,  
  2.                                                     switch_channel_flag_t flag)  
  3. {  
  4.     switch_assert(channel != NULL);  
  5.     channel->state = state;  
  6.     switch_channel_set_flag(channel, flag);  
  7.     channel->session = session;  
  8.     channel->running_state = CS_NONE;  
  9.     return SWITCH_STATUS_SUCCESS;  

 

channel相關的還不是看得很細,本文檔先編寫最基本的,後面瞭解更深入了再補充。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章