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函式啟動:
分析啟動引數;
為全域性變數SWITCH_GLOBAL_dirs分配記憶體和賦值;
建立pid檔案;
呼叫switch_core.c中的switch_core_init_and_modload()函式,初始化並載入所有的module,內部實現邏輯如下:
a) switch_core_init_and_modload
i. 首先呼叫switch_core_init
初始化全域性變數runtime的相關引數;
對SWITCH_GLOBAL_dirs指定的目錄進行建立;
load_mime_types載入conf/mime.types載入所有的mime型別;
設定執行引數的預設值(注意:switch_find_local_ip獲取本地IP的時候會訪問外網);
依次呼叫:switch_core_session_init、switch_console_init、switch_event_init、switch_xml_init、switch_log_init進行相關的初始化,初始化的內容主要:hash、mutex。
載入”switch.conf”配置檔案;
switch_core_state_machine_init對state_machine進行初始化;
switch_core_sqldb_start,啟動資料庫相關執行緒;
switch_scheduler_task_thread_start,啟動任務排程模組
switch_rtp_init:初始化rtp/zrtp相關的
switch_scheduler_add_task( heartbeat_callback),將心跳任務加入任務排程模組;
ii. switch_loadable_module_init()[switch_loadable_module.c]載入各module,freeswitch為了後續高效的執行module中的各種介面,將所有的介面都存放到了hash表中,每種介面建立了一個hash桶:
初始化全域性變數:loadable_modules的各類hash。
載入整合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()
遍歷conf/modules.conf載入所有配置的module;
遍歷conf/post_load_modules.conf載入所有配置的module;
如果除整合module之外配置的模組為0,則從SWITCH_GLOBAL_dirs.mod_dir載入所有的mod;
switch_loadable_module_runtime,為每個module的runtime入口建立一個執行緒並執行runtime;