模塊加載入口函數mod_sofia_load(),首先一系列switch_event_reserve_subclass()調用,註冊事件類型。然後調用switch_queue_create()建立三個消息隊列。
switch_queue_create(&mod_sofia_globals.presence_queue, SOFIA_QUEUE_SIZE, mod_sofia_globals.pool);
switch_queue_create(&mod_sofia_globals.general_event_queue, SOFIA_QUEUE_SIZE, mod_sofia_globals.pool);
mod_sofia_globals.cpu_count = switch_core_cpu_count();
mod_sofia_globals.max_msg_queues = (mod_sofia_globals.cpu_count / 2) + 1;
if (mod_sofia_globals.max_msg_queues < 2) {
mod_sofia_globals.max_msg_queues = 2;
}
if (mod_sofia_globals.max_msg_queues > SOFIA_MAX_MSG_QUEUE) {
mod_sofia_globals.max_msg_queues = SOFIA_MAX_MSG_QUEUE;
}
switch_queue_create(&mod_sofia_globals.msg_queue, SOFIA_MSG_QUEUE_SIZE * mod_sofia_globals.max_msg_queues, mod_sofia_globals.pool);
接下來調用sofia_init()函數初始化協議棧,並把協議棧的日誌重定向到FS的日誌系統。初始化完畢之後,調用config_sofia()對模塊進行配置。讀取配置文件進行設置,這裏關鍵是對每個profile初始化監聽線程,調用的是launch_sofia_profile_thread(),每個profile,初始化一個sofia庫事件處理線程,一個FS應用層消息隊列處理線程。在launch_sofia_profile_thread()中,初始化協議棧事件線程,線程入口函數sofia_profile_thread_run(),在這個線程裏,調用nua_create接口實例化NUA對象,同時綁定事件回調函數sofia_event_callback();調用switch_queue_create初始化應用層的消息隊列,然後調用launch_sofia_worker_thread()派生出應用層消息隊列處理線程。
if (profile->sipip) {
switch_event_t *s_event;
if (!profile->extsipport) profile->extsipport = profile->sip_port;
launch_sofia_profile_thread(profile);
if (profile->odbc_dsn) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Connecting ODBC Profile %s [%s]\n", profile->name, url);
switch_yield(1000000);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Started Profile %s [%s]\n", profile->name, url);
}
if ((switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_PROFILE_START) == SWITCH_STATUS_SUCCESS)) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_name", profile->name);
if (profile) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_uri", profile->url);
}
switch_event_fire(&s_event);
}
}
接下來,調用sofia_msg_thread_start(0);啓動消息處理線程,這是用於處理FS消息隊列事件的。
接下來,調用switch_event_bind()綁定一系列的事件回調函數。其中,有一些事件的回調函數是sofia_presence_event_handler(),這個回調函數會創建一個線程來處理presence事件。
最後,註冊模塊的APP和API實現。
上時序圖: