1. 程式人生 > >FreeSWITCH程式碼分析(一)

FreeSWITCH程式碼分析(一)

什麼是FreeSWITCH

FreeSWITCH 是一個可擴充套件的開源跨平臺的電話平臺,支援音訊、視訊、文字或任何其他形式的媒體使用的協議的路由與互動。它於2006年成立。FreeSWITCH也提供一個穩定的技術平臺,可供許多電話應用開發利用的免費工具。

FreeSWITCH 最初由Anthony Minessale在Brian West和Michael Jerris的協助下設計和開發。這三人原先都是asterisk的開發者。這個專案的設計目標包括模組化、跨平臺的支援,可擴充套件性和穩定性。今天,許多更多的開發者和使用者都為FreeSWITCH在貢獻力量。

FreeSWITCH支援各種通訊技術,如Skype,SIP、H.323、GoogleTalk,因此它容易與其他的開源PBX進行對接,如:sipXecs、Call Weaver、Bayonne、YATE 和Asterisk。

FreeSWITCH支援許多高階的SIP特性,如presence、BLF、SLA以及TCP TLS和 sRTP。它也可以作為一個透明代理(有媒體或無媒體),扮演SBC和T.38代理的角色。

FreeSWITCH既支援寬頻、窄帶編碼。Voice channel和conference bridge模組可以支援8k、16k、24k、32k和48k不同的位元速率,而且這些不同位元速率的通道可以進行bridge。如果G.729編解碼經過授權,FreeSWITCH也是支援的。

FreeSWITCH支援Windows,Mac OS X ,Linux,BSD和Solaris的32與64位平臺。

FreeSWITCH支援傳真,無論是音訊,還是T.38,而且可以微微音訊和T.38的閘道器。

FreeSWITCH的很多開發者,都是非常有經驗的開發人員。他們同時也參與其他開源軟交換產品的開發,如:openSER, sipXecs, Asterisk和Call Weaver.

目錄結構

├── configure

├── configure.in

├── Makefile.am

├── Makefile.in

├── modules.conf :需要編譯的module列表

├── patches/ :補丁包

│ ├── MODAPP-293.diff

│ ├── mod_portaudio_snow_leopard.diff

│ ├── sofia.diff

│ └── zrtp_bnlib_pic.diff

├── src/

│ ├── CMakeLists.txt

│ ├── g711.c

│ ├── include/

│ ├── inet_pton.c

│ ├── Makefile.am

│ ├── Makefile.in

│ ├── mod/

│ ├── switch_apr.c

│ ├── switch_buffer.c

│ ├── switch.c :main入口

│ ├── switch_caller.c

│ ├── switch_channel.c

│ ├── switch_config.c

│ ├── switch_console.c

│ ├── switch_core_asr.c

│ ├── switch_core.c

│ ├── switch_core_codec.c

│ ├── switch_core_db.c

│ ├── switch_core_directory.c

│ ├── switch_core_event_hook.c

│ ├── switch_core_file.c

│ ├── switch_core_hash.c

│ ├── switch_core_io.c

│ ├── switch_core_media_bug.c

│ ├── switch_core_memory.c

│ ├── switch_core_port_allocator.c

│ ├── switch_core_rwlock.c

│ ├── switch_core_session.c

│ ├── switch_core_speech.c

│ ├── switch_core_sqldb.c

│ ├── switch_core_state_machine.c

│ ├── switch_core_timer.c

│ ├── switch_cpp.cpp

│ ├── switch_dso.c

│ ├── switch_event.c

│ ├── switch_ivr_async.c

│ ├── switch_ivr_bridge.c

│ ├── switch_ivr.c

│ ├── switch_ivr_menu.c

│ ├── switch_ivr_originate.c

│ ├── switch_ivr_play_say.c

│ ├── switch_ivr_say.c

│ ├── switch_loadable_module.c

│ ├── switch_log.c

│ ├── switch_mprintf.c

│ ├── switch_nat.c

│ ├── switch_odbc.c

│ ├── switch_pcm.c

│ ├── switch_profile.c

│ ├── switch_regex.c

│ ├── switch_resample.c

│ ├── switch_rtp.c

│ ├── switch_scheduler.c

│ ├── switch_stun.c

│ ├── switch_swig.c

│ ├── switch_swig.i

│ ├── switch_time.c

│ ├── switch_utils.c

│ ├── switch_xml.c

│ └── switch_xml_config.c

├── libs/

啟動邏輯

FreeSwitch主程式的入庫函式在src/switch.c檔案中。Main函式啟動:

  1. 分析啟動引數;

  2. 為全域性變數SWITCH_GLOBAL_dirs分配記憶體和賦值;

  3. 建立pid檔案;

  4. 呼叫switch_core.c中的switch_core_init_and_modload()函式,初始化並載入所有的module,內部實現邏輯如下:

a) switch_core_init_and_modload

i. 首先呼叫switch_core_init

  1. 初始化全域性變數runtime的相關引數;

  2. 對SWITCH_GLOBAL_dirs指定的目錄進行建立;

  3. load_mime_types載入conf/mime.types載入所有的mime型別;

  4. 設定執行引數的預設值(注意:switch_find_local_ip獲取本地IP的時候會訪問外網);

  5. 依次呼叫:switch_core_session_init、switch_console_init、switch_event_init、switch_xml_init、switch_log_init進行相關的初始化,初始化的內容主要:hash、mutex。

  6. 載入”switch.conf”配置檔案;

  7. switch_core_state_machine_init對state_machine進行初始化;

  8. switch_core_sqldb_start,啟動資料庫相關執行緒;

  9. switch_scheduler_task_thread_start,啟動任務排程模組

  10. switch_rtp_init:初始化rtp/zrtp相關的

  11. switch_scheduler_add_task( heartbeat_callback),將心跳任務加入任務排程模組;

ii. switch_loadable_module_init()[switch_loadable_module.c]載入各module,freeswitch為了後續高效的執行module中的各種介面,將所有的介面都存放到了hash表中,每種介面建立了一個hash桶:

  1. 初始化全域性變數:loadable_modules的各類hash。

  2. 載入整合module:CORE_SOFTTIMER_MODULE、CORE_PCM_MODULE;

a) switch_loadable_module_load_file進行module載入

i. 找到name##_module_interface的全域性變數進行載入(module中巨集SWITCH_MODULE_DEFINITION定義的);

ii. 執行module->load(會初始化引數module_interface,是SWITCH_MODULE_LOAD_FUNCTION定義的函式的一個引數),load中會增加各類介面:API、CHAT、APP、DIALPLAN、CODEC

b) switch_loadable_module_process

i. 遍歷每個節點的endpoint_interface、codec_interface、dialplan_interface、timer_interface、application_interface、api_interface、file_interface、speech_interface、asr_interface、directory_interface、chat_interface、say_interface、management_interface,載入並存儲到hash。

c) 建立執行緒,執行module->runtime()

  1. 遍歷conf/modules.conf載入所有配置的module;

  2. 遍歷conf/post_load_modules.conf載入所有配置的module;

  3. 如果除整合module之外配置的模組為0,則從SWITCH_GLOBAL_dirs.mod_dir載入所有的mod;

  4. switch_loadable_module_runtime,為每個module的runtime入口建立一個執行緒並執行runtime;