代码基于FreeSWITCH-1.4.20版本讲解,阅读前提是你已经可以编译并安装FreeTDM模块,编译安装步骤。
使用场景为:一个语音卡上有4个FXS口,接上模拟话机,能摘机拨打电话。
第一步:修改配置配置文件。转到FreeSWITC的安装目录,当前目录下有: freetdm.conf和autoload_cofigs/freetdm.conf.xml文件。
1、修改freetdm.conf文件,找到如下文字:
[span wanpipe myWanpipe]
trunk_type => FXS
fxs-channel => 1:3-4
修改为:
[span wanpipe andywang]
trunk_type => FXS
fxs-channel => 1:1-4
2、修改freetdm.conf.xml文件,找到如下文字:
<span name="myAnalog">
修改为:
<span name="andywang">
注:“andywang”字符要和freetdm.conf完成一致,程序中会进行对比,通过此来寻找。
其他地方暂时不做修改。
第二步:查看源码加载
1、mod_freetdm是freeswitch的一个模块,加载过程和其他模块一致,入口函数在mod_freetdm.c文件中5567行,函数:
SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
函数中包含三个主要函数:1) ftdm_global_init():此函数主要是初始化一些全局数据结构,包括后面使用的哈希表,互斥锁,调度策略,目的是运行的基础环境进行初始化,和配置无关。
2) ftdm_global_configuration():此函数通过解析freetdm.conf文件来对程序进行配置,根据配置,malloc对应span结构体,malloc出1到4个通道的得通道结构体,并对通道进行初始化,创建通道句柄。此配置文件主要是配置不同类型的IO操作,可以认为不涉及信令部分。
3)load_config():此函数通过读取freetdm.conf.xml进行配置,根据不同的信令配置,组合相应的IO模块,进行信令配置。运行信令模块。
第三部:深入源码,具体的执行过程:
在整个配置加载完成后,一个analog得span会创建一个线程,线程的函数为(1181行,ftmod_analog.c):
static void *ftdm_analog_run(ftdm_thread_t *me, void *obj)
线程函数一直运行,会通过poll读取各个通道摘机、挂机和按键信号。
1、手动摘机,通道会上传一个FTDM_OOB_RING_START事件,具体的代码执行
( 1018 行) FTDM_OOB_RING_START:
会在此处创建一个通道的线程,具体创建代码如下: ftdm_thread_create_detached(ftdm_analog_channel_run, event->channel);
2、拨号时会有按键数字放置在队里面,通道的线程会读取对应的队列,判断是否有数字,具体的代码在:
(825行) if ((dlen = ftdm_channel_dequeue_dtmf(ftdmchan, dtmf + dtmf_offset, sizeof(dtmf) - strlen(dtmf))))
3、当你的拨号满足你设置的拨号方案,或者超时,拨号过程完成,进入正式呼叫过程,具体代码在:
848 if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) >= analog_data->max_dialstr))) {
849 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
850 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
851 last_digit = 0;
852 collecting = 0;
853 }
4、从FreeTDM转入到FreeSWITCH核心的呼叫,是从ftdm_analog.c文件中的代码:
698 case FTDM_CHANNEL_STATE_RING:
699 {
700 ftdm_channel_use(ftdmchan);
701 sig.event_id = FTDM_SIGEVENT_START;
702
703 if (ftdmchan->type == FTDM_CHAN_TYPE_FXO) {
704 ftdm_set_string(ftdmchan->caller_data.dnis.digits, ftdmchan->chan_number);
705 } else {
706 ftdm_set_string(ftdmchan->caller_data.dnis.digits, dtmf);
707 }
708
709 ftdm_span_send_signal(ftdmchan->span, &sig);
710 continue;
711 }
712 break;
转入到mod_freetdm.c文件代码中的:
2298 case FTDM_SIGEVENT_START:
2299 {
2300 status = ftdm_channel_from_event(sigmsg, &session);
2301 if (status != FTDM_SUCCESS) {
2302 ftdm_channel_call_hangup(sigmsg->channel);
2303 }
2304 }
2305 break;
这个函数ftdm_channel_from_event(sigmsg, &session)会执行具体的呼叫,转入到FreeSWITCH得CORE,然后调用mod_sofia模块进行SIP协议的组合,进行正式的SIP呼叫。