Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
004cc9d7
提交
004cc9d7
authored
12月 06, 2010
作者:
Moises Silva
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'moy.iodump'
上级
e85ef4ce
e37ce444
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
672 行增加
和
217 行删除
+672
-217
Makefile.am
libs/freetdm/Makefile.am
+0
-4
freetdm.conf
libs/freetdm/conf/freetdm.conf
+26
-0
freetdm.conf.xml
libs/freetdm/conf/freetdm.conf.xml
+215
-47
configure.ac
libs/freetdm/configure.ac
+0
-11
mod_freetdm.c
libs/freetdm/mod_freetdm/mod_freetdm.c
+23
-20
ftdm_io.c
libs/freetdm/src/ftdm_io.c
+278
-93
ftmod_r2.c
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
+84
-30
freetdm.h
libs/freetdm/src/include/freetdm.h
+30
-0
ftdm_core.h
libs/freetdm/src/include/private/ftdm_core.h
+15
-12
ftdm_types.h
libs/freetdm/src/include/private/ftdm_types.h
+1
-0
没有找到文件。
libs/freetdm/Makefile.am
浏览文件 @
004cc9d7
...
@@ -55,10 +55,6 @@ COMPILE = $(CC) $(FTDM_CFLAGS)
...
@@ -55,10 +55,6 @@ COMPILE = $(CC) $(FTDM_CFLAGS)
LTCOMPILE
=
$(LIBTOOL)
--mode
=
compile
--tag
=
CC
$(COMPILE)
LTCOMPILE
=
$(LIBTOOL)
--mode
=
compile
--tag
=
CC
$(COMPILE)
LINK
=
$(LIBTOOL)
--mode
=
link
--tag
=
CC
$(CC)
$(FTDM_CFLAGS)
$(LDFLAGS)
-o
$@
LINK
=
$(LIBTOOL)
--mode
=
link
--tag
=
CC
$(CC)
$(FTDM_CFLAGS)
$(LDFLAGS)
-o
$@
if
WANT_DEBUGDTMF
FTDM_CFLAGS
+=
-DFTDM_DEBUG_DTMF
endif
#
#
# GNU pkgconfig file
# GNU pkgconfig file
...
...
libs/freetdm/conf/freetdm.conf
浏览文件 @
004cc9d7
...
@@ -45,3 +45,29 @@ fxs-channel => 1
...
@@ -45,3 +45,29 @@ fxs-channel => 1
number
=>
2
number
=>
2
fxo
-
channel
=>
3
fxo
-
channel
=>
3
;
MFC
-
R2
typical
span
configuration
;
MFC
-
R2
with
wanpipe
(
Sangoma
)
[
span
wanpipe
myWanpipeSpan
]
trunk_type
=>
E1
cas
-
channel
=>
1
-
15
:
1101
cas
-
channel
=>
17
-
31
:
1101
;
MFC
-
R2
with
Zaptel
/
DAHDI
[
span
zt
myWanpipeSpan
]
trunk_type
=>
E1
cas
-
channel
=>
1
-
15
:
1101
cas
-
channel
=>
17
-
31
:
1101
;
generic
channel
parameters
;
this
parameters
are
accepted
by
any
type
of
span
/
channel
;
remember
that
for
generic
channel
parameters
only
channels
;
below
the
parameter
within
the
span
will
be
affected
;
Channel
audio
gain
;
rxgain
=>
0
.
0
;
txgain
=>
0
.
0
;
Whether
to
perform
media
dumps
for
DTMF
debugging
;
debugdtmf
=>
yes
libs/freetdm/conf/freetdm.conf.xml
浏览文件 @
004cc9d7
<!-- Please refer to http://wiki.freeswitch.org/wiki/FreeTDM for further documentation -->
<!-- Please refer to http://wiki.freeswitch.org/wiki/FreeTDM for further documentation -->
<!--
This is a sample FreeSWITCH XML configuration for FreeTDM
Remember you still need to configure freetdm.conf (no XML extension) in $prefix/conf/
directory of FreeSWITCH. The freetdm.conf (no XML extension) is a simple text file
definining the I/O interfaces (Sangoma, DAHDI etc). This file (freetdm.conf.xml) deals
with the signaling protocols that you can run on top of your I/O interfaces.
-->
<configuration
name=
"freetdm.conf"
description=
"FreeTDM Configuration"
>
<configuration
name=
"freetdm.conf"
description=
"FreeTDM Configuration"
>
<settings>
<param
name=
"debug"
value=
"0"
/>
<settings>
<!--<param name="hold-music" value="$${moh_uri}"/>-->
<param
name=
"debug"
value=
"0"
/>
<!--<param name="enable-analog-option" value="call-swap"/>-->
<!--<param name="hold-music" value="$${moh_uri}"/>-->
<!--<param name="enable-analog-option" value="3-way"/>-->
<!--<param name="enable-analog-option" value="call-swap"/>-->
</settings>
<!--<param name="enable-analog-option" value="3-way"/>-->
</settings>
<!-- use the <pri_spans> tag for native ISDN support (most likely broken at this point, check sangoma_pri_spans or libpri_spans for alternatives) -->
<pri_spans>
<span
name=
"PRI_1"
>
<!-- Log Levels: none, alert, crit, err, warning, notice, info, debug -->
<param
name=
"q921loglevel"
value=
"alert"
/>
<param
name=
"q931loglevel"
value=
"alert"
/>
<param
name=
"mode"
value=
"user"
/>
<param
name=
"dialect"
value=
"5ess"
/>
<param
name=
"dialplan"
value=
"XML"
/>
<param
name=
"context"
value=
"default"
/>
</span>
<span
name=
"PRI_2"
>
<param
name=
"q921loglevel"
value=
"alert"
/>
<param
name=
"q931loglevel"
value=
"alert"
/>
<param
name=
"mode"
value=
"user"
/>
<param
name=
"dialect"
value=
"5ess"
/>
<param
name=
"dialplan"
value=
"XML"
/>
<param
name=
"context"
value=
"default"
/>
</span>
</pri_spans>
<!-- Analog spans go here -->
<analog_spans>
<span
name=
"myAnalog"
>
<!--<param name="hold-music" value="$${moh_uri}"/>-->
<!--<param name="enable-analog-option" value="call-swap"/>-->
<!--<param name="enable-analog-option" value="3-way"/>-->
<param
name=
"tonegroup"
value=
"us"
/>
<param
name=
"digit-timeout"
value=
"2000"
/>
<param
name=
"max-digits"
value=
"11"
/>
<param
name=
"dialplan"
value=
"XML"
/>
<param
name=
"context"
value=
"default"
/>
<param
name=
"enable-callerid"
value=
"true"
/>
<!-- regex to stop dialing when it matches -->
<!--<param name="dial-regex" value="5555"/>-->
<!-- regex to stop dialing when it does not match -->
<!--<param name="fail-dial-regex" value="^5"/>-->
</span>
</analog_spans>
<!-- Sample analog configuration -->
<analog_spans>
<!-- The span name must match the name in your freetdm.conf -->
<span
name=
"myAnalog"
>
<!--<param name="hold-music" value="$${moh_uri}"/>-->
<!--<param name="enable-analog-option" value="call-swap"/>-->
<!--<param name="enable-analog-option" value="3-way"/>-->
<param
name=
"tonegroup"
value=
"us"
/>
<param
name=
"digit-timeout"
value=
"2000"
/>
<param
name=
"max-digits"
value=
"11"
/>
<param
name=
"dialplan"
value=
"XML"
/>
<param
name=
"context"
value=
"default"
/>
<param
name=
"enable-callerid"
value=
"true"
/>
<!-- regex to stop dialing when it matches -->
<!--<param name="dial-regex" value="5555"/>-->
<!-- regex to stop dialing when it does not match -->
<!--<param name="fail-dial-regex" value="^5"/>-->
</span>
</analog_spans>
<!-- openr2 (MFC-R2 signaling) spans
MFC-R2 signaling has lots of variants from country to country and even sometimes
minor variants inside the same country. The only mandatory parameters here are:
variant, but typically you also want to set max_ani and max_dnis.
IT IS RECOMMENDED that you leave the default values (leaving them commented) for the
other parameters unless you have problems or you have been instructed to change some
parameter. OpenR2 library uses the 'variant' parameter to try to determine the
best defaults for your country. If you want to contribute your configs for a particular
country send them to the e-mail of the primary OpenR2 developer that you can find in the
AUTHORS file of the OpenR2 package, they will be added to the samples directory of openr2.
-->
<r2_spans>
<span
name=
"wp1"
cfgprofile=
"testr2"
>
<!--
MFC/R2 variant. This depends on the OpenR2 supported variants
A list of values can be found by executing the openr2 command r2test -l
some valid values are:
mx (Mexico)
ar (Argentina)
br (Brazil)
ph (Philippines)
itu (per ITU spec)
-->
<param
name=
"variant"
value=
"mx"
/>
<!-- switch parameters (required), where to send calls to -->
<param
name=
"dialplan"
value=
"XML"
/>
<param
name=
"context"
value=
"default"
/>
<!--
Max amount of ANI (caller id digits) to ask for
<param name="max_ani" value="4"/>
-->
<!--
Max amount of DNIS to ask for
<param name="max_dnis" value="4"/>
-->
<!-- Do not set parameters below this line unless you desire to tweak it because is not working -->
<!--
Whether or not to get the ANI before getting DNIS (only affects incoming calls)
Some telcos require ANI first some others do not care, if default go wrong on
incoming calls, change this value
<param name="get_ani_first" value="yes"/>
-->
<!--
Caller Category to send. Accepted values:
- national_subscriber
- national_priority_subscriber
- international_subscriber
- international_priority_subscriber
- collect_call
Usually national_subscriber (the default) works just fine
<param name="category" value="national_subscriber"/>
-->
<!--
Brazil uses a special calling party category for collect calls (llamadas por cobrar)
instead of using the operator (as in Mexico). The R2 spec in Brazil says a special GB tone
should be used to reject collect calls. If you want to ALLOW collect calls specify 'yes',
if you want to BLOCK collect calls then say 'no'. Default is to block collect calls.
(see also 'double_answer')
<param name="allow_collect_calls" value="yes"/>
-->
<!--
This feature is related but independent of allow_collect_calls
Some PBX's require a double-answer process to block collect calls, if
you ever have problems blocking collect calls using Group B signals (allow_collect_calls=no)
then you may want to try with double_answer=yes, this will cause that every answer signal
is changed to perform 'answer -> clear back -> answer' (sort of a flash)
(see also 'allow_collect_calls')
<param name="double_answer" value="yes"/>
-->
<!--
This feature allows to skip the use of Group B/II signals and go directly
to the accepted state for incoming calls
<param name="immediate_accept" value="yes"/>
-->
<!--
Skip request of calling party category and ANI
<param name="skip_category" value="yes"/>
-->
<!--
Brazil use a special signal to force the release of the line (hangup) from the
backward perspective. When forced_release=no, the normal clear back signal
will be sent on hangup, which is OK for all mfcr2 variants I know of, except for
Brazilian variant, where the central will leave the line up for several seconds (30, 60)
which sometimes is not what people really want. When forced_release=yes, a different
signal will be sent to hangup the call indicating that the line should be released immediately
<param name="forced_release" value="yes"/>
-->
<!--
Whether or not report to the other end 'accept call with charge'
This setting has no effect with most telecos, usually is safe
leave the default (yes), but once in a while when interconnecting with
old PBXs this may be useful.
Concretely this affects the Group B signal used to accept calls
<param name="charge_calls" value="yes"/>
-->
<!--
MFC/R2 value in milliseconds for the MF timeout. Any negative value
means 'default', smaller values than 500ms are not recommended
and can cause malfunctioning. If you experience protocol error
due to MF timeout try incrementing this value in 500ms steps
<param name="mfback_timeout" value="1500"/>
-->
<!--
MFC/R2 value in milliseconds for the metering pulse timeout.
Metering pulses are sent by some telcos for some R2 variants
during a call presumably for billing purposes to indicate costs,
however this pulses use the same signal that is used to indicate
call hangup, therefore a timeout is sometimes required to distinguish
between a *real* hangup and a billing pulse that should not
last more than 500ms, If you experience call drops after some
minutes of being stablished try setting a value of some ms here,
values greater than 500ms are not recommended.
BE AWARE that choosing the proper protocol variant parameter
implicitly sets a good recommended value for this timer, use this
parameter only when you *really* want to override the default, otherwise
just comment out this value.
<param name="metering_pulse_timeout" value="1000"/>
-->
<!--
WARNING: advanced users only! I really mean it
this parameter is commented by default because
YOU DON'T NEED IT UNLESS YOU REALLY GROK MFC/R2
READ COMMENTS on doc/r2proto.conf in openr2 package
for more info
<param name="advanced_protocol_file" value="/usr/local/freeswitch/conf/r2proto.conf"/>
-->
<!-- USE THIS FOR DEBUGGING MFC-R2 PROTOCOL -->
<!--
Where to dump advanced call file protocol logs
<param name="logdir" value="$${base_dir}/log/mfcr2"/>
-->
<!--
MFC/R2 valid logging values are: all,error,warning,debug,notice,cas,mf,nothing
error,warning,debug and notice are self-descriptive
'cas' is for logging ABCD CAS tx and rx
'mf' is for logging of the Multi Frequency tones
You can mix up values, like: loglevel=error,debug,mf to log just error, debug and
multi frequency messages
'all' is a special value to log all the activity
'nothing' is a clean-up value, in case you want to not log any activity for
a channel or group of channels
BE AWARE that the level of output logged will ALSO depend on
the value you have in FreeSWITCH logging configurations, if you disable output FreeSWITCH
then it does not matter if you specify 'all' here, nothing will be logged
so FreeSWITCH has the last word on what is going to be logged
<param name="logging" value="debug,notice,warning,error,mf,cas"/>
-->
<!--
whether or not to drop protocol call files into 'logdir'
<param name="call_files" value="yes"/>
-->
<!--
Use only for very technical debugging
This is the size (if 0, dumps are disabled) of MF dump files. MF dump files
are audio files that are dumped when a protocol error occurs.
The files are dumped in whatever you set in the logdir parameter.
Value -1 uses a default recommended size (which stores 5 seconds of audio)
<param name="mf_dump_size" value="-1"/>
-->
</span>
</r2_spans>
</configuration>
</configuration>
libs/freetdm/configure.ac
浏览文件 @
004cc9d7
...
@@ -167,17 +167,6 @@ AC_ARG_WITH([pritap],
...
@@ -167,17 +167,6 @@ AC_ARG_WITH([pritap],
HAVE_PRITAP="${enable_pritap}"
HAVE_PRITAP="${enable_pritap}"
AM_CONDITIONAL([HAVE_PRITAP],[test "${enable_pritap}" = "yes"])
AM_CONDITIONAL([HAVE_PRITAP],[test "${enable_pritap}" = "yes"])
# debug dtmf?
AC_ARG_WITH([debugdtmf],
[AS_HELP_STRING([--with-debugdtmf], [Debug DTMF])],
[case "${withval}" in
no) enable_debugdtmf="no" ;;
*) enable_debugdtmf="yes" ;;
esac],
[enable_debugdtmf="no"]
)
AM_CONDITIONAL([WANT_DEBUGDTMF], [test "${enable_debugdtmf}" = "yes"])
##
##
# OpenR2 stack
# OpenR2 stack
#
#
...
...
libs/freetdm/mod_freetdm/mod_freetdm.c
浏览文件 @
004cc9d7
...
@@ -1417,6 +1417,24 @@ fail:
...
@@ -1417,6 +1417,24 @@ fail:
}
}
static
void
ftdm_enable_channel_dtmf
(
ftdm_channel_t
*
fchan
,
switch_channel_t
*
channel
)
{
if
(
channel
)
{
const
char
*
var
;
if
((
var
=
switch_channel_get_variable
(
channel
,
"freetdm_disable_dtmf"
)))
{
if
(
switch_true
(
var
))
{
ftdm_channel_command
(
fchan
,
FTDM_COMMAND_DISABLE_DTMF_DETECT
,
NULL
);
ftdm_log
(
FTDM_LOG_INFO
,
"DTMF detection disabled in channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
fchan
),
ftdm_channel_get_id
(
fchan
));
return
;
}
}
/* the variable is not present or has a negative value then proceed to enable DTMF ... */
}
if
(
ftdm_channel_command
(
fchan
,
FTDM_COMMAND_ENABLE_DTMF_DETECT
,
NULL
)
!=
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Failed to enable DTMF detection in channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
fchan
),
ftdm_channel_get_id
(
fchan
));
}
}
ftdm_status_t
ftdm_channel_from_event
(
ftdm_sigmsg_t
*
sigmsg
,
switch_core_session_t
**
sp
)
ftdm_status_t
ftdm_channel_from_event
(
ftdm_sigmsg_t
*
sigmsg
,
switch_core_session_t
**
sp
)
{
{
switch_core_session_t
*
session
=
NULL
;
switch_core_session_t
*
session
=
NULL
;
...
@@ -1440,6 +1458,9 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
...
@@ -1440,6 +1458,9 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
return
FTDM_FAIL
;
return
FTDM_FAIL
;
}
}
/* I guess we always want DTMF detection */
ftdm_enable_channel_dtmf
(
sigmsg
->
channel
,
NULL
);
switch_core_session_add_stream
(
session
,
NULL
);
switch_core_session_add_stream
(
session
,
NULL
);
tech_pvt
=
(
private_t
*
)
switch_core_session_alloc
(
session
,
sizeof
(
private_t
));
tech_pvt
=
(
private_t
*
)
switch_core_session_alloc
(
session
,
sizeof
(
private_t
));
...
@@ -1633,24 +1654,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
...
@@ -1633,24 +1654,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
return
FTDM_BREAK
;
return
FTDM_BREAK
;
}
}
static
void
ftdm_enable_channel_dtmf
(
ftdm_channel_t
*
fchan
,
switch_channel_t
*
channel
)
{
if
(
channel
)
{
const
char
*
var
;
if
((
var
=
switch_channel_get_variable
(
channel
,
"freetdm_disable_dtmf"
)))
{
if
(
switch_true
(
var
))
{
ftdm_channel_command
(
fchan
,
FTDM_COMMAND_DISABLE_DTMF_DETECT
,
NULL
);
ftdm_log
(
FTDM_LOG_INFO
,
"DTMF detection disabled in channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
fchan
),
ftdm_channel_get_id
(
fchan
));
return
;
}
}
/* the variable is not present or has a negative value then proceed to enable DTMF ... */
}
if
(
ftdm_channel_command
(
fchan
,
FTDM_COMMAND_ENABLE_DTMF_DETECT
,
NULL
)
!=
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Failed to enable DTMF detection in channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
fchan
),
ftdm_channel_get_id
(
fchan
));
}
}
static
FIO_SIGNAL_CB_FUNCTION
(
on_fxo_signal
)
static
FIO_SIGNAL_CB_FUNCTION
(
on_fxo_signal
)
{
{
switch_core_session_t
*
session
=
NULL
;
switch_core_session_t
*
session
=
NULL
;
...
@@ -2059,6 +2062,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
...
@@ -2059,6 +2062,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
}
}
break
;
break
;
case
FTDM_SIGEVENT_PROCEED
:{}
break
;
default:
default:
{
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_WARNING
,
"Unhandled event %d from R2 for channel %d:%d
\n
"
,
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_WARNING
,
"Unhandled event %d from R2 for channel %d:%d
\n
"
,
...
@@ -2092,8 +2097,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
...
@@ -2092,8 +2097,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
{
{
ftdm_channel_add_var
(
sigmsg
->
channel
,
"screening_ind"
,
ftdm_screening2str
(
caller_data
->
screen
));
ftdm_channel_add_var
(
sigmsg
->
channel
,
"screening_ind"
,
ftdm_screening2str
(
caller_data
->
screen
));
ftdm_channel_add_var
(
sigmsg
->
channel
,
"presentation_ind"
,
ftdm_presentation2str
(
caller_data
->
pres
));
ftdm_channel_add_var
(
sigmsg
->
channel
,
"presentation_ind"
,
ftdm_presentation2str
(
caller_data
->
pres
));
ftdm_enable_channel_dtmf
(
sigmsg
->
channel
,
NULL
);
return
ftdm_channel_from_event
(
sigmsg
,
&
session
);
return
ftdm_channel_from_event
(
sigmsg
,
&
session
);
}
}
break
;
break
;
...
...
libs/freetdm/src/ftdm_io.c
浏览文件 @
004cc9d7
...
@@ -86,6 +86,114 @@ FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void)
...
@@ -86,6 +86,114 @@ FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void)
#endif
#endif
}
}
static
void
write_chan_io_dump
(
ftdm_channel_t
*
fchan
,
ftdm_io_dump_t
*
dump
,
char
*
dataptr
,
int
dlen
)
{
int
windex
=
dump
->
windex
;
int
avail
=
dump
->
size
-
windex
;
if
(
!
dump
->
buffer
)
{
return
;
}
if
(
dlen
>
avail
)
{
int
diff
=
dlen
-
avail
;
ftdm_assert
(
diff
<
dump
->
size
,
"Very small buffer or very big IO chunk!
\n
"
);
/* write only what we can and the rest at the beginning of the buffer */
memcpy
(
&
dump
->
buffer
[
windex
],
dataptr
,
avail
);
memcpy
(
&
dump
->
buffer
[
0
],
&
dataptr
[
avail
],
diff
);
windex
=
diff
;
/*ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "wrapping around dump buffer %p up to index %d\n\n", dump, windex);*/
dump
->
wrapped
=
1
;
}
else
{
memcpy
(
&
dump
->
buffer
[
windex
],
dataptr
,
dlen
);
windex
+=
dlen
;
}
if
(
windex
==
dump
->
size
)
{
/*ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "wrapping around dump buffer %p\n", dump);*/
windex
=
0
;
dump
->
wrapped
=
1
;
}
dump
->
windex
=
windex
;
}
static
void
dump_chan_io_to_file
(
ftdm_channel_t
*
fchan
,
ftdm_io_dump_t
*
dump
,
FILE
*
file
)
{
/* write the saved audio buffer */
int
rc
=
0
;
int
towrite
=
dump
->
size
-
dump
->
windex
;
if
(
dump
->
wrapped
)
{
rc
=
fwrite
(
&
dump
->
buffer
[
dump
->
windex
],
1
,
towrite
,
file
);
if
(
rc
!=
towrite
)
{
ftdm_log_chan
(
fchan
,
FTDM_LOG_ERROR
,
"only wrote %d out of %d bytes in DTMF debug buffer
\n
"
,
rc
,
towrite
);
}
}
if
(
dump
->
windex
)
{
towrite
=
dump
->
windex
;
rc
=
fwrite
(
&
dump
->
buffer
[
0
],
1
,
towrite
,
file
);
if
(
rc
!=
towrite
)
{
ftdm_log_chan
(
fchan
,
FTDM_LOG_ERROR
,
"only wrote %d out of %d bytes in DTMF debug buffer
\n
"
,
rc
,
towrite
);
}
}
dump
->
windex
=
0
;
dump
->
wrapped
=
0
;
}
static
void
stop_chan_io_dump
(
ftdm_io_dump_t
*
dump
)
{
if
(
!
dump
->
buffer
)
{
return
;
}
ftdm_safe_free
(
dump
->
buffer
);
memset
(
dump
,
0
,
sizeof
(
dump
));
}
static
ftdm_status_t
start_chan_io_dump
(
ftdm_channel_t
*
chan
,
ftdm_io_dump_t
*
dump
,
ftdm_size_t
size
)
{
if
(
dump
->
buffer
)
{
ftdm_log_chan_msg
(
chan
,
FTDM_LOG_ERROR
,
"IO dump is already started
\n
"
);
return
FTDM_FAIL
;
}
memset
(
dump
,
0
,
sizeof
(
*
dump
));
dump
->
buffer
=
ftdm_malloc
(
size
);
if
(
!
dump
->
buffer
)
{
return
FTDM_FAIL
;
}
dump
->
size
=
size
;
return
FTDM_SUCCESS
;
}
static
void
close_dtmf_debug_file
(
ftdm_channel_t
*
ftdmchan
)
{
if
(
ftdmchan
->
dtmfdbg
.
file
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"closing debug dtmf file
\n
"
);
fclose
(
ftdmchan
->
dtmfdbg
.
file
);
ftdmchan
->
dtmfdbg
.
file
=
NULL
;
}
}
static
ftdm_status_t
disable_dtmf_debug
(
ftdm_channel_t
*
ftdmchan
)
{
if
(
!
ftdmchan
->
dtmfdbg
.
enabled
)
{
return
FTDM_SUCCESS
;
}
if
(
!
ftdmchan
->
rxdump
.
buffer
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"DTMF debug enabled but no rx dump?
\n
"
);
return
FTDM_FAIL
;
}
close_dtmf_debug_file
(
ftdmchan
);
stop_chan_io_dump
(
&
ftdmchan
->
rxdump
);
ftdmchan
->
dtmfdbg
.
enabled
=
0
;
return
FTDM_SUCCESS
;
}
typedef
struct
{
typedef
struct
{
uint8_t
enabled
;
uint8_t
enabled
;
uint8_t
running
;
uint8_t
running
;
...
@@ -448,10 +556,6 @@ static ftdm_status_t ftdm_channel_destroy(ftdm_channel_t *ftdmchan)
...
@@ -448,10 +556,6 @@ static ftdm_status_t ftdm_channel_destroy(ftdm_channel_t *ftdmchan)
ftdm_sleep
(
500
);
ftdm_sleep
(
500
);
}
}
#ifdef FTDM_DEBUG_DTMF
ftdm_mutex_destroy
(
&
ftdmchan
->
dtmfdbg
.
mutex
);
#endif
ftdm_mutex_lock
(
ftdmchan
->
pre_buffer_mutex
);
ftdm_mutex_lock
(
ftdmchan
->
pre_buffer_mutex
);
ftdm_buffer_destroy
(
&
ftdmchan
->
pre_buffer
);
ftdm_buffer_destroy
(
&
ftdmchan
->
pre_buffer
);
ftdm_mutex_unlock
(
ftdmchan
->
pre_buffer_mutex
);
ftdm_mutex_unlock
(
ftdmchan
->
pre_buffer_mutex
);
...
@@ -870,9 +974,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t
...
@@ -870,9 +974,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t
ftdm_mutex_create
(
&
new_chan
->
mutex
);
ftdm_mutex_create
(
&
new_chan
->
mutex
);
ftdm_mutex_create
(
&
new_chan
->
pre_buffer_mutex
);
ftdm_mutex_create
(
&
new_chan
->
pre_buffer_mutex
);
#ifdef FTDM_DEBUG_DTMF
ftdm_mutex_create
(
&
new_chan
->
dtmfdbg
.
mutex
);
#endif
ftdm_buffer_create
(
&
new_chan
->
digit_buffer
,
128
,
128
,
0
);
ftdm_buffer_create
(
&
new_chan
->
digit_buffer
,
128
,
128
,
0
);
ftdm_buffer_create
(
&
new_chan
->
gen_dtmf_buffer
,
128
,
128
,
0
);
ftdm_buffer_create
(
&
new_chan
->
gen_dtmf_buffer
,
128
,
128
,
0
);
...
@@ -2400,23 +2501,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signa
...
@@ -2400,23 +2501,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signa
}
}
}
}
#ifdef FTDM_DEBUG_DTMF
static
void
close_dtmf_debug
(
ftdm_channel_t
*
ftdmchan
)
{
ftdm_mutex_lock
(
ftdmchan
->
dtmfdbg
.
mutex
);
if
(
ftdmchan
->
dtmfdbg
.
file
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"closing debug dtmf file
\n
"
);
fclose
(
ftdmchan
->
dtmfdbg
.
file
);
ftdmchan
->
dtmfdbg
.
file
=
NULL
;
}
ftdmchan
->
dtmfdbg
.
windex
=
0
;
ftdmchan
->
dtmfdbg
.
wrapped
=
0
;
ftdm_mutex_unlock
(
ftdmchan
->
dtmfdbg
.
mutex
);
}
#endif
static
ftdm_status_t
ftdm_channel_clear_vars
(
ftdm_channel_t
*
ftdmchan
);
static
ftdm_status_t
ftdm_channel_clear_vars
(
ftdm_channel_t
*
ftdmchan
);
FT_DECLARE
(
ftdm_status_t
)
ftdm_channel_done
(
ftdm_channel_t
*
ftdmchan
)
FT_DECLARE
(
ftdm_status_t
)
ftdm_channel_done
(
ftdm_channel_t
*
ftdmchan
)
{
{
...
@@ -2445,9 +2529,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
...
@@ -2445,9 +2529,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdm_buffer_destroy
(
&
ftdmchan
->
pre_buffer
);
ftdm_buffer_destroy
(
&
ftdmchan
->
pre_buffer
);
ftdmchan
->
pre_buffer_size
=
0
;
ftdmchan
->
pre_buffer_size
=
0
;
ftdm_mutex_unlock
(
ftdmchan
->
pre_buffer_mutex
);
ftdm_mutex_unlock
(
ftdmchan
->
pre_buffer_mutex
);
#ifdef FTDM_DEBUG_DTMF
close_dtmf_debug
(
ftdmchan
);
#endif
ftdm_channel_clear_vars
(
ftdmchan
);
ftdm_channel_clear_vars
(
ftdmchan
);
if
(
ftdmchan
->
hangup_timer
)
{
if
(
ftdmchan
->
hangup_timer
)
{
ftdm_sched_cancel_timer
(
globals
.
timingsched
,
ftdmchan
->
hangup_timer
);
ftdm_sched_cancel_timer
(
globals
.
timingsched
,
ftdmchan
->
hangup_timer
);
...
@@ -2456,7 +2537,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
...
@@ -2456,7 +2537,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdmchan
->
init_state
=
FTDM_CHANNEL_STATE_DOWN
;
ftdmchan
->
init_state
=
FTDM_CHANNEL_STATE_DOWN
;
ftdmchan
->
state
=
FTDM_CHANNEL_STATE_DOWN
;
ftdmchan
->
state
=
FTDM_CHANNEL_STATE_DOWN
;
ftdm_log
(
FTDM_LOG_DEBUG
,
"channel done %u:%u
\n
"
,
ftdmchan
->
span_id
,
ftdmchan
->
chan_id
);
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_DISABLE_DEBUG_DTMF
,
NULL
);
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_DISABLE_INPUT_DUMP
,
NULL
);
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_DISABLE_OUTPUT_DUMP
,
NULL
);
if
(
FTDM_IS_VOICE_CHANNEL
(
ftdmchan
))
{
if
(
FTDM_IS_VOICE_CHANNEL
(
ftdmchan
))
{
ftdm_sigmsg_t
sigmsg
;
ftdm_sigmsg_t
sigmsg
;
...
@@ -2468,6 +2551,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
...
@@ -2468,6 +2551,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdm_span_send_signal
(
ftdmchan
->
span
,
&
sigmsg
);
ftdm_span_send_signal
(
ftdmchan
->
span
,
&
sigmsg
);
}
}
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"channel done
\n
"
);
ftdm_mutex_unlock
(
ftdmchan
->
mutex
);
ftdm_mutex_unlock
(
ftdmchan
->
mutex
);
return
FTDM_SUCCESS
;
return
FTDM_SUCCESS
;
...
@@ -2476,7 +2561,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
...
@@ -2476,7 +2561,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
FT_DECLARE
(
ftdm_status_t
)
ftdm_channel_use
(
ftdm_channel_t
*
ftdmchan
)
FT_DECLARE
(
ftdm_status_t
)
ftdm_channel_use
(
ftdm_channel_t
*
ftdmchan
)
{
{
assert
(
ftdmchan
!=
NULL
);
ftdm_assert
(
ftdmchan
!=
NULL
,
"Null channel
\n
"
);
ftdm_set_flag_locked
(
ftdmchan
,
FTDM_CHANNEL_INUSE
);
ftdm_set_flag_locked
(
ftdmchan
,
FTDM_CHANNEL_INUSE
);
...
@@ -2550,8 +2635,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
...
@@ -2550,8 +2635,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
{
{
ftdm_status_t
status
=
FTDM_FAIL
;
ftdm_status_t
status
=
FTDM_FAIL
;
assert
(
ftdmchan
!=
NULL
);
ftdm_assert_return
(
ftdmchan
!=
NULL
,
FTDM_FAIL
,
"No channel
\n
"
);
assert
(
ftdmchan
->
fio
!=
NULL
);
ftdm_assert_return
(
ftdmchan
->
fio
!=
NULL
,
FTDM_FAIL
,
"No IO attached to channel
\n
"
);
ftdm_mutex_lock
(
ftdmchan
->
mutex
);
ftdm_mutex_lock
(
ftdmchan
->
mutex
);
...
@@ -2578,7 +2663,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
...
@@ -2578,7 +2663,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
break
;
break
;
case
FTDM_COMMAND_TRACE_INPUT
:
case
FTDM_COMMAND_TRACE_INPUT
:
{
{
char
*
path
=
(
char
*
)
obj
;
char
*
path
=
FTDM_COMMAND_OBJ_CHAR_P
;
if
(
ftdmchan
->
fds
[
FTDM_READ_TRACE_INDEX
]
>
0
)
{
if
(
ftdmchan
->
fds
[
FTDM_READ_TRACE_INDEX
]
>
0
)
{
close
(
ftdmchan
->
fds
[
FTDM_READ_TRACE_INDEX
]);
close
(
ftdmchan
->
fds
[
FTDM_READ_TRACE_INDEX
]);
ftdmchan
->
fds
[
FTDM_READ_TRACE_INDEX
]
=
-
1
;
ftdmchan
->
fds
[
FTDM_READ_TRACE_INDEX
]
=
-
1
;
...
@@ -2621,6 +2706,128 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
...
@@ -2621,6 +2706,128 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
}
break
;
break
;
/*!< Enable DTMF debugging */
case
FTDM_COMMAND_ENABLE_DEBUG_DTMF
:
{
if
(
ftdmchan
->
dtmfdbg
.
enabled
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Cannot enable debug DTMF again
\n
"
);
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
if
(
ftdmchan
->
rxdump
.
buffer
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Cannot debug DTMF if Rx dumping is already enabled
\n
"
);
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
if
(
start_chan_io_dump
(
ftdmchan
,
&
ftdmchan
->
rxdump
,
FTDM_IO_DUMP_DEFAULT_BUFF_SIZE
)
!=
FTDM_SUCCESS
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Failed to enable rx dump for DTMF debugging
\n
"
);
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
ftdmchan
->
dtmfdbg
.
enabled
=
1
;
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Enabled DTMF debugging
\n
"
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
break
;
/*!< Disable DTMF debugging (if not disabled explicitly, it is disabled automatically when calls hangup) */
case
FTDM_COMMAND_DISABLE_DEBUG_DTMF
:
{
if
(
!
ftdmchan
->
dtmfdbg
.
enabled
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"DTMF debug is already disabled
\n
"
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
if
(
disable_dtmf_debug
(
ftdmchan
)
!=
FTDM_SUCCESS
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Failed to disable DTMF debug
\n
"
);
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Disabled DTMF debugging
\n
"
);
}
break
;
/*!< Start dumping all input to a circular buffer. The size of the circular buffer can be specified, default used otherwise */
case
FTDM_COMMAND_ENABLE_INPUT_DUMP
:
{
ftdm_size_t
size
=
obj
?
FTDM_COMMAND_OBJ_SIZE
:
FTDM_IO_DUMP_DEFAULT_BUFF_SIZE
;
if
(
ftdmchan
->
rxdump
.
buffer
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Input dump is already enabled
\n
"
);
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
if
(
start_chan_io_dump
(
ftdmchan
,
&
ftdmchan
->
rxdump
,
size
)
!=
FTDM_SUCCESS
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Failed to enable input dump
\n
"
);
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Enabled input dump with size %zd
\n
"
,
size
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
break
;
/*!< Stop dumping all input to a circular buffer. */
case
FTDM_COMMAND_DISABLE_INPUT_DUMP
:
{
if
(
!
ftdmchan
->
rxdump
.
buffer
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"No need to disable input dump
\n
"
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Disabled input dump of size %zd
\n
"
,
ftdmchan
->
rxdump
.
size
);
stop_chan_io_dump
(
&
ftdmchan
->
rxdump
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
break
;
/*!< Start dumping all output to a circular buffer. The size of the circular buffer can be specified, default used otherwise */
case
FTDM_COMMAND_ENABLE_OUTPUT_DUMP
:
{
ftdm_size_t
size
=
obj
?
FTDM_COMMAND_OBJ_SIZE
:
FTDM_IO_DUMP_DEFAULT_BUFF_SIZE
;
if
(
ftdmchan
->
txdump
.
buffer
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Output dump is already enabled
\n
"
);
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
if
(
start_chan_io_dump
(
ftdmchan
,
&
ftdmchan
->
txdump
,
size
)
!=
FTDM_SUCCESS
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Failed to enable output dump
\n
"
);
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Enabled output dump with size %zd
\n
"
,
size
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
break
;
/*!< Stop dumping all output to a circular buffer. */
case
FTDM_COMMAND_DISABLE_OUTPUT_DUMP
:
{
if
(
!
ftdmchan
->
txdump
.
buffer
)
{
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"No need to disable output dump
\n
"
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Disabled output dump of size %zd
\n
"
,
ftdmchan
->
rxdump
.
size
);
stop_chan_io_dump
(
&
ftdmchan
->
txdump
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
break
;
/*!< Dump the current input circular buffer to the specified FILE* structure */
case
FTDM_COMMAND_DUMP_INPUT
:
{
if
(
!
obj
)
{
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
dump_chan_io_to_file
(
ftdmchan
,
&
ftdmchan
->
rxdump
,
obj
);
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Dumped input of size %zd to file %p
\n
"
,
ftdmchan
->
rxdump
.
size
,
obj
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
break
;
/*!< Dump the current output circular buffer to the specified FILE* structure */
case
FTDM_COMMAND_DUMP_OUTPUT
:
{
if
(
!
obj
)
{
GOTO_STATUS
(
done
,
FTDM_FAIL
);
}
dump_chan_io_to_file
(
ftdmchan
,
&
ftdmchan
->
txdump
,
obj
);
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Dumped input of size %zd to file %p
\n
"
,
ftdmchan
->
txdump
.
size
,
obj
);
GOTO_STATUS
(
done
,
FTDM_SUCCESS
);
}
break
;
case
FTDM_COMMAND_SET_INTERVAL
:
case
FTDM_COMMAND_SET_INTERVAL
:
{
{
if
(
!
ftdm_channel_test_feature
(
ftdmchan
,
FTDM_CHANNEL_FEATURE_INTERVAL
))
{
if
(
!
ftdm_channel_test_feature
(
ftdmchan
,
FTDM_CHANNEL_FEATURE_INTERVAL
))
{
...
@@ -3089,12 +3296,14 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
...
@@ -3089,12 +3296,14 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
ftdm_size_t
wr
=
0
;
ftdm_size_t
wr
=
0
;
const
char
*
p
;
const
char
*
p
;
assert
(
ftdmchan
!=
NULL
);
ftdm_assert_return
(
ftdmchan
!=
NULL
,
FTDM_FAIL
,
"No channel
\n
"
);
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Queuing DTMF %s (debug = %d)
\n
"
,
dtmf
,
ftdmchan
->
dtmfdbg
.
enabled
);
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Queuing DTMF %s
\n
"
,
dtmf
);
if
(
!
ftdmchan
->
dtmfdbg
.
enabled
)
{
goto
skipdebug
;
}
#ifdef FTDM_DEBUG_DTMF
ftdm_mutex_lock
(
ftdmchan
->
dtmfdbg
.
mutex
);
if
(
!
ftdmchan
->
dtmfdbg
.
file
)
{
if
(
!
ftdmchan
->
dtmfdbg
.
file
)
{
struct
tm
currtime
;
struct
tm
currtime
;
time_t
currsec
;
time_t
currsec
;
...
@@ -3107,37 +3316,19 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
...
@@ -3107,37 +3316,19 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
ftdmchan
->
span_id
,
ftdmchan
->
chan_id
,
ftdmchan
->
span_id
,
ftdmchan
->
chan_id
,
currtime
.
tm_year
-
100
,
currtime
.
tm_mon
+
1
,
currtime
.
tm_mday
,
currtime
.
tm_year
-
100
,
currtime
.
tm_mon
+
1
,
currtime
.
tm_mday
,
currtime
.
tm_hour
,
currtime
.
tm_min
,
currtime
.
tm_sec
,
ftdmchan
->
native_codec
==
FTDM_CODEC_ULAW
?
"ulaw"
:
ftdmchan
->
native_codec
==
FTDM_CODEC_ALAW
?
"alaw"
:
"sln"
);
currtime
.
tm_hour
,
currtime
.
tm_min
,
currtime
.
tm_sec
,
ftdmchan
->
native_codec
==
FTDM_CODEC_ULAW
?
"ulaw"
:
ftdmchan
->
native_codec
==
FTDM_CODEC_ALAW
?
"alaw"
:
"sln"
);
ftdmchan
->
dtmfdbg
.
file
=
fopen
(
dfile
,
"w"
);
ftdmchan
->
dtmfdbg
.
file
=
fopen
(
dfile
,
"w"
);
if
(
!
ftdmchan
->
dtmfdbg
.
file
)
{
if
(
!
ftdmchan
->
dtmfdbg
.
file
)
{
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_ERROR
,
"failed to open debug dtmf file %s
\n
"
,
dfile
);
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_ERROR
,
"failed to open debug dtmf file %s
\n
"
,
dfile
);
}
else
{
}
else
{
/* write the saved audio buffer */
int
rc
=
0
;
int
towrite
=
sizeof
(
ftdmchan
->
dtmfdbg
.
buffer
)
-
ftdmchan
->
dtmfdbg
.
windex
;
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"created debug DTMF file %s
\n
"
,
dfile
);
ftdmchan
->
dtmfdbg
.
closetimeout
=
DTMF_DEBUG_TIMEOUT
;
ftdmchan
->
dtmfdbg
.
closetimeout
=
DTMF_DEBUG_TIMEOUT
;
if
(
ftdmchan
->
dtmfdbg
.
wrapped
)
{
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_DUMP_INPUT
,
ftdmchan
->
dtmfdbg
.
file
);
rc
=
fwrite
(
&
ftdmchan
->
dtmfdbg
.
buffer
[
ftdmchan
->
dtmfdbg
.
windex
],
1
,
towrite
,
ftdmchan
->
dtmfdbg
.
file
);
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_DEBUG
,
"Dumped initial DTMF output to %s
\n
"
,
dfile
);
if
(
rc
!=
towrite
)
{
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_ERROR
,
"only wrote %d out of %d bytes in DTMF debug buffer
\n
"
,
rc
,
towrite
);
}
}
if
(
ftdmchan
->
dtmfdbg
.
windex
)
{
towrite
=
ftdmchan
->
dtmfdbg
.
windex
;
rc
=
fwrite
(
&
ftdmchan
->
dtmfdbg
.
buffer
[
0
],
1
,
towrite
,
ftdmchan
->
dtmfdbg
.
file
);
if
(
rc
!=
towrite
)
{
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_ERROR
,
"only wrote %d out of %d bytes in DTMF debug buffer
\n
"
,
rc
,
towrite
);
}
}
ftdmchan
->
dtmfdbg
.
windex
=
0
;
ftdmchan
->
dtmfdbg
.
wrapped
=
0
;
}
}
}
else
{
}
else
{
ftdmchan
->
dtmfdbg
.
closetimeout
=
DTMF_DEBUG_TIMEOUT
;
ftdmchan
->
dtmfdbg
.
closetimeout
=
DTMF_DEBUG_TIMEOUT
;
}
}
ftdm_mutex_unlock
(
ftdmchan
->
dtmfdbg
.
mutex
);
#endif
skipdebug
:
if
(
ftdmchan
->
pre_buffer
)
{
if
(
ftdmchan
->
pre_buffer
)
{
ftdm_buffer_zero
(
ftdmchan
->
pre_buffer
);
ftdm_buffer_zero
(
ftdmchan
->
pre_buffer
);
...
@@ -3182,16 +3373,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
...
@@ -3182,16 +3373,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
static
FIO_WRITE_FUNCTION
(
ftdm_raw_write
)
static
FIO_WRITE_FUNCTION
(
ftdm_raw_write
)
{
{
int
dlen
=
(
int
)
*
datalen
;
if
(
ftdmchan
->
fds
[
FTDM_WRITE_TRACE_INDEX
]
>
-
1
)
{
if
(
ftdmchan
->
fds
[
FTDM_WRITE_TRACE_INDEX
]
>
-
1
)
{
int
dlen
=
(
int
)
*
datalen
;
if
((
write
(
ftdmchan
->
fds
[
FTDM_WRITE_TRACE_INDEX
],
data
,
dlen
))
!=
dlen
)
{
if
((
write
(
ftdmchan
->
fds
[
FTDM_WRITE_TRACE_INDEX
],
data
,
dlen
))
!=
dlen
)
{
ftdm_log
(
FTDM_LOG_WARNING
,
"Raw output trace failed to write all of the %zd bytes
\n
"
,
dlen
);
ftdm_log
(
FTDM_LOG_WARNING
,
"Raw output trace failed to write all of the %zd bytes
\n
"
,
dlen
);
}
}
}
}
write_chan_io_dump
(
ftdmchan
,
&
ftdmchan
->
txdump
,
data
,
dlen
);
return
ftdmchan
->
fio
->
write
(
ftdmchan
,
data
,
datalen
);
return
ftdmchan
->
fio
->
write
(
ftdmchan
,
data
,
datalen
);
}
}
static
FIO_READ_FUNCTION
(
ftdm_raw_read
)
static
FIO_READ_FUNCTION
(
ftdm_raw_read
)
{
{
ftdm_status_t
status
=
ftdmchan
->
fio
->
read
(
ftdmchan
,
data
,
datalen
);
ftdm_status_t
status
=
ftdmchan
->
fio
->
read
(
ftdmchan
,
data
,
datalen
);
...
@@ -3206,48 +3397,24 @@ static FIO_READ_FUNCTION(ftdm_raw_read)
...
@@ -3206,48 +3397,24 @@ static FIO_READ_FUNCTION(ftdm_raw_read)
ftdmchan
->
span
->
sig_read
(
ftdmchan
,
data
,
*
datalen
);
ftdmchan
->
span
->
sig_read
(
ftdmchan
,
data
,
*
datalen
);
}
}
#ifdef FTDM_DEBUG_DTMF
if
(
status
==
FTDM_SUCCESS
)
{
if
(
status
==
FTDM_SUCCESS
)
{
int
dlen
=
(
int
)
*
datalen
;
int
dlen
=
(
int
)
*
datalen
;
int
rc
=
0
;
int
rc
=
0
;
ftdm_mutex_lock
(
ftdmchan
->
dtmfdbg
.
mutex
);
if
(
!
ftdmchan
->
dtmfdbg
.
file
)
{
write_chan_io_dump
(
ftdmchan
,
&
ftdmchan
->
rxdump
,
data
,
dlen
);
/* no file yet, write to our circular buffer */
int
windex
=
ftdmchan
->
dtmfdbg
.
windex
;
/* if dtmf debug is enabled and initialized, write there too */
int
avail
=
sizeof
(
ftdmchan
->
dtmfdbg
.
buffer
)
-
windex
;
if
(
ftdmchan
->
dtmfdbg
.
file
)
{
char
*
dataptr
=
data
;
if
(
dlen
>
avail
)
{
int
diff
=
dlen
-
avail
;
/* write only what we can and the rest at the beginning of the buffer */
memcpy
(
&
ftdmchan
->
dtmfdbg
.
buffer
[
windex
],
dataptr
,
avail
);
memcpy
(
&
ftdmchan
->
dtmfdbg
.
buffer
[
0
],
&
dataptr
[
avail
],
diff
);
windex
=
diff
;
/*ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "wrapping around dtmf read buffer up to index %d\n\n", windex);*/
ftdmchan
->
dtmfdbg
.
wrapped
=
1
;
}
else
{
memcpy
(
&
ftdmchan
->
dtmfdbg
.
buffer
[
windex
],
dataptr
,
dlen
);
windex
+=
dlen
;
}
if
(
windex
==
sizeof
(
ftdmchan
->
dtmfdbg
.
buffer
))
{
/*ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "wrapping around dtmf read buffer\n");*/
windex
=
0
;
ftdmchan
->
dtmfdbg
.
wrapped
=
1
;
}
ftdmchan
->
dtmfdbg
.
windex
=
windex
;
}
else
{
rc
=
fwrite
(
data
,
1
,
dlen
,
ftdmchan
->
dtmfdbg
.
file
);
rc
=
fwrite
(
data
,
1
,
dlen
,
ftdmchan
->
dtmfdbg
.
file
);
if
(
rc
!=
dlen
)
{
if
(
rc
!=
dlen
)
{
ftdm_log
(
FTDM_LOG_WARNING
,
"DTMF debugger wrote only %d out of %d bytes: %s
\n
"
,
rc
,
datalen
,
strerror
(
errno
));
ftdm_log
(
FTDM_LOG_WARNING
,
"DTMF debugger wrote only %d out of %d bytes: %s
\n
"
,
rc
,
datalen
,
strerror
(
errno
));
}
}
ftdmchan
->
dtmfdbg
.
closetimeout
--
;
ftdmchan
->
dtmfdbg
.
closetimeout
--
;
if
(
!
ftdmchan
->
dtmfdbg
.
closetimeout
)
{
if
(
!
ftdmchan
->
dtmfdbg
.
closetimeout
)
{
close_dtmf_debug
(
ftdmchan
);
close_dtmf_debug
_file
(
ftdmchan
);
}
}
}
}
ftdm_mutex_unlock
(
ftdmchan
->
dtmfdbg
.
mutex
);
}
}
#endif
return
status
;
return
status
;
}
}
...
@@ -4043,6 +4210,7 @@ static ftdm_status_t ftdm_set_channels_alarms(ftdm_span_t *span, int currindex)
...
@@ -4043,6 +4210,7 @@ static ftdm_status_t ftdm_set_channels_alarms(ftdm_span_t *span, int currindex)
FT_DECLARE
(
ftdm_status_t
)
ftdm_configure_span_channels
(
ftdm_span_t
*
span
,
const
char
*
str
,
ftdm_channel_config_t
*
chan_config
,
unsigned
*
configured
)
FT_DECLARE
(
ftdm_status_t
)
ftdm_configure_span_channels
(
ftdm_span_t
*
span
,
const
char
*
str
,
ftdm_channel_config_t
*
chan_config
,
unsigned
*
configured
)
{
{
int
currindex
;
int
currindex
;
unsigned
chan_index
=
0
;
ftdm_assert_return
(
span
!=
NULL
,
FTDM_EINVAL
,
"span is null
\n
"
);
ftdm_assert_return
(
span
!=
NULL
,
FTDM_EINVAL
,
"span is null
\n
"
);
ftdm_assert_return
(
chan_config
!=
NULL
,
FTDM_EINVAL
,
"config is null
\n
"
);
ftdm_assert_return
(
chan_config
!=
NULL
,
FTDM_EINVAL
,
"config is null
\n
"
);
...
@@ -4076,6 +4244,14 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
...
@@ -4076,6 +4244,14 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
return
FTDM_FAIL
;
return
FTDM_FAIL
;
}
}
if
(
chan_config
->
debugdtmf
)
{
for
(
chan_index
=
currindex
+
1
;
chan_index
<=
span
->
chan_count
;
chan_index
++
)
{
if
(
!
FTDM_IS_VOICE_CHANNEL
(
span
->
channels
[
chan_index
]))
{
continue
;
}
span
->
channels
[
chan_index
]
->
dtmfdbg
.
requested
=
1
;
}
}
return
FTDM_SUCCESS
;
return
FTDM_SUCCESS
;
}
}
...
@@ -4094,7 +4270,7 @@ static ftdm_status_t load_config(void)
...
@@ -4094,7 +4270,7 @@ static ftdm_status_t load_config(void)
ftdm_channel_config_t
chan_config
;
ftdm_channel_config_t
chan_config
;
memset
(
&
chan_config
,
0
,
sizeof
(
chan_config
));
memset
(
&
chan_config
,
0
,
sizeof
(
chan_config
));
sprintf
(
chan_config
.
group_name
,
"
default"
);
sprintf
(
chan_config
.
group_name
,
"__
default"
);
if
(
!
ftdm_config_open_file
(
&
cfg
,
cfg_name
))
{
if
(
!
ftdm_config_open_file
(
&
cfg
,
cfg_name
))
{
return
FTDM_FAIL
;
return
FTDM_FAIL
;
...
@@ -4131,6 +4307,9 @@ static ftdm_status_t load_config(void)
...
@@ -4131,6 +4307,9 @@ static ftdm_status_t load_config(void)
if
(
ftdm_span_create
(
type
,
name
,
&
span
)
==
FTDM_SUCCESS
)
{
if
(
ftdm_span_create
(
type
,
name
,
&
span
)
==
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_DEBUG
,
"created span %d (%s) of type %s
\n
"
,
span
->
span_id
,
span
->
name
,
type
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"created span %d (%s) of type %s
\n
"
,
span
->
span_id
,
span
->
name
,
type
);
d
=
0
;
d
=
0
;
/* it is confusing that parameters from one span affect others, so let's clear them */
memset
(
&
chan_config
,
0
,
sizeof
(
chan_config
));
sprintf
(
chan_config
.
group_name
,
"__default"
);
}
else
{
}
else
{
ftdm_log
(
FTDM_LOG_CRIT
,
"failure creating span of type %s
\n
"
,
type
);
ftdm_log
(
FTDM_LOG_CRIT
,
"failure creating span of type %s
\n
"
,
type
);
span
=
NULL
;
span
=
NULL
;
...
@@ -4254,6 +4433,9 @@ static ftdm_status_t load_config(void)
...
@@ -4254,6 +4433,9 @@ static ftdm_status_t load_config(void)
if
(
sscanf
(
val
,
"%f"
,
&
(
chan_config
.
rxgain
))
!=
1
)
{
if
(
sscanf
(
val
,
"%f"
,
&
(
chan_config
.
rxgain
))
!=
1
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"invalid rxgain: '%s'
\n
"
,
val
);
ftdm_log
(
FTDM_LOG_ERROR
,
"invalid rxgain: '%s'
\n
"
,
val
);
}
}
}
else
if
(
!
strcasecmp
(
var
,
"debugdtmf"
))
{
chan_config
.
debugdtmf
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Setting debugdtmf to '%s'
\n
"
,
chan_config
.
debugdtmf
?
"yes"
:
"no"
);
}
else
if
(
!
strcasecmp
(
var
,
"group"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"group"
))
{
len
=
strlen
(
val
);
len
=
strlen
(
val
);
if
(
len
>=
FTDM_MAX_NAME_STR_SZ
)
{
if
(
len
>=
FTDM_MAX_NAME_STR_SZ
)
{
...
@@ -4905,6 +5087,9 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
...
@@ -4905,6 +5087,9 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
case
FTDM_SIGEVENT_START
:
case
FTDM_SIGEVENT_START
:
{
{
ftdm_set_echocancel_call_begin
(
sigmsg
->
channel
);
ftdm_set_echocancel_call_begin
(
sigmsg
->
channel
);
if
(
sigmsg
->
channel
->
dtmfdbg
.
requested
)
{
ftdm_channel_command
(
sigmsg
->
channel
,
FTDM_COMMAND_ENABLE_DEBUG_DTMF
,
NULL
);
}
/* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was
/* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was
* doing it during SIGEVENT_START, but now that flags are private they can't, wonder if
* doing it during SIGEVENT_START, but now that flags are private they can't, wonder if
...
...
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
浏览文件 @
004cc9d7
...
@@ -68,6 +68,7 @@ typedef struct ftdm_r2_call_t {
...
@@ -68,6 +68,7 @@ typedef struct ftdm_r2_call_t {
ftdm_channel_state_t
chanstate
;
ftdm_channel_state_t
chanstate
;
ftdm_size_t
dnis_index
;
ftdm_size_t
dnis_index
;
ftdm_size_t
ani_index
;
ftdm_size_t
ani_index
;
char
logname
[
255
];
char
name
[
10
];
char
name
[
10
];
unsigned
long
txdrops
;
unsigned
long
txdrops
;
}
ftdm_r2_call_t
;
}
ftdm_r2_call_t
;
...
@@ -88,13 +89,13 @@ typedef struct ft_r2_conf_s {
...
@@ -88,13 +89,13 @@ typedef struct ft_r2_conf_s {
int32_t
max_dnis
;
int32_t
max_dnis
;
int32_t
mfback_timeout
;
int32_t
mfback_timeout
;
int32_t
metering_pulse_timeout
;
int32_t
metering_pulse_timeout
;
int32_t
mf_dump_size
;
/* booleans */
/* booleans */
int
immediate_accept
;
int
immediate_accept
;
int
skip_category
;
int
skip_category
;
int
get_ani_first
;
int
get_ani_first
;
int
call_files
;
int
call_files
;
int
mf_files
;
int
double_answer
;
int
double_answer
;
int
charge_calls
;
int
charge_calls
;
int
forced_release
;
int
forced_release
;
...
@@ -117,6 +118,8 @@ typedef struct ftdm_r2_data_s {
...
@@ -117,6 +118,8 @@ typedef struct ftdm_r2_data_s {
int
forced_release
:
1
;
int
forced_release
:
1
;
/* whether accept the call when offered, or wait until the user decides to accept */
/* whether accept the call when offered, or wait until the user decides to accept */
int
accept_on_offer
:
1
;
int
accept_on_offer
:
1
;
/* Size of multi-frequency (or any media) dumps used during protocol errors */
int32_t
mf_dump_size
;
/* max time spent in ms doing real work in a single loop */
/* max time spent in ms doing real work in a single loop */
int32_t
jobmax
;
int32_t
jobmax
;
/* Total number of loops performed so far */
/* Total number of loops performed so far */
...
@@ -125,6 +128,8 @@ typedef struct ftdm_r2_data_s {
...
@@ -125,6 +128,8 @@ typedef struct ftdm_r2_data_s {
uint64_t
loops
[
11
];
uint64_t
loops
[
11
];
/* LWP */
/* LWP */
uint32_t
monitor_thread_id
;
uint32_t
monitor_thread_id
;
/* Logging directory */
char
logdir
[
512
];
}
ftdm_r2_data_t
;
}
ftdm_r2_data_t
;
/* one element per span will be stored in g_mod_data_hash global var to keep track of them
/* one element per span will be stored in g_mod_data_hash global var to keep track of them
...
@@ -409,10 +414,11 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status)
...
@@ -409,10 +414,11 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status)
}
}
/* always called from the monitor thread */
/* always called from the monitor thread */
static
void
ftdm_r2_on_call_init
(
openr2_chan_t
*
r2chan
)
static
void
ftdm_r2_on_call_init
(
openr2_chan_t
*
r2chan
,
const
char
*
logname
)
{
{
ftdm_r2_call_t
*
r2call
;
ftdm_r2_call_t
*
r2call
;
ftdm_channel_t
*
ftdmchan
=
openr2_chan_get_client_data
(
r2chan
);
ftdm_channel_t
*
ftdmchan
=
openr2_chan_get_client_data
(
r2chan
);
ftdm_r2_data_t
*
r2data
=
ftdmchan
->
span
->
signal_data
;
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_NOTICE
,
"Received request to start call
\n
"
);
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_NOTICE
,
"Received request to start call
\n
"
);
...
@@ -441,12 +447,15 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
...
@@ -441,12 +447,15 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
ft_r2_clean_call
(
ftdmchan
->
call_data
);
ft_r2_clean_call
(
ftdmchan
->
call_data
);
r2call
=
R2CALL
(
ftdmchan
);
r2call
=
R2CALL
(
ftdmchan
);
if
(
ftdmchan
->
state
==
FTDM_CHANNEL_STATE_DOWN
)
{
snprintf
(
r2call
->
logname
,
sizeof
(
r2call
->
logname
),
"%s"
,
logname
);
R2CALL
(
ftdmchan
)
->
chanstate
=
FTDM_CHANNEL_STATE_DOWN
;
}
else
{
/* start io dump */
R2CALL
(
ftdmchan
)
->
chanstate
=
FTDM_CHANNEL_STATE_DIALING
;
if
(
r2data
->
mf_dump_size
)
{
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_ENABLE_INPUT_DUMP
,
&
r2data
->
mf_dump_size
);
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_ENABLE_OUTPUT_DUMP
,
&
r2data
->
mf_dump_size
);
}
}
R2CALL
(
ftdmchan
)
->
chanstate
=
FTDM_CHANNEL_STATE_DOWN
;
ftdm_set_state
(
ftdmchan
,
FTDM_CHANNEL_STATE_COLLECT
);
ftdm_set_state
(
ftdmchan
,
FTDM_CHANNEL_STATE_COLLECT
);
}
}
...
@@ -454,9 +463,16 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
...
@@ -454,9 +463,16 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
static
void
ftdm_r2_on_call_offered
(
openr2_chan_t
*
r2chan
,
const
char
*
ani
,
const
char
*
dnis
,
openr2_calling_party_category_t
category
)
static
void
ftdm_r2_on_call_offered
(
openr2_chan_t
*
r2chan
,
const
char
*
ani
,
const
char
*
dnis
,
openr2_calling_party_category_t
category
)
{
{
ftdm_channel_t
*
ftdmchan
=
openr2_chan_get_client_data
(
r2chan
);
ftdm_channel_t
*
ftdmchan
=
openr2_chan_get_client_data
(
r2chan
);
ftdm_r2_data_t
*
r2data
=
ftdmchan
->
span
->
signal_data
;
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_NOTICE
,
"Call offered with ANI = %s, DNIS = %s, Category = (%d)
\n
"
,
ani
,
dnis
,
category
);
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_NOTICE
,
"Call offered with ANI = %s, DNIS = %s, Category = (%d)
\n
"
,
ani
,
dnis
,
category
);
ftdm_set_state
(
ftdmchan
,
FTDM_CHANNEL_STATE_RING
);
ftdm_set_state
(
ftdmchan
,
FTDM_CHANNEL_STATE_RING
);
/* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */
if
(
r2data
->
mf_dump_size
)
{
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_DISABLE_INPUT_DUMP
,
NULL
);
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_DISABLE_OUTPUT_DUMP
,
NULL
);
}
}
}
/*
/*
...
@@ -484,6 +500,32 @@ static void clear_accept_pending(ftdm_channel_t *fchan)
...
@@ -484,6 +500,32 @@ static void clear_accept_pending(ftdm_channel_t *fchan)
}
}
}
}
static
void
dump_mf
(
openr2_chan_t
*
r2chan
)
{
char
dfile
[
512
];
FILE
*
f
=
NULL
;
ftdm_channel_t
*
ftdmchan
=
openr2_chan_get_client_data
(
r2chan
);
ftdm_r2_data_t
*
r2data
=
ftdmchan
->
span
->
signal_data
;
if
(
r2data
->
mf_dump_size
)
{
char
*
logname
=
R2CALL
(
ftdmchan
)
->
logname
;
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Dumping IO output in prefix %s
\n
"
,
logname
);
snprintf
(
dfile
,
sizeof
(
dfile
),
logname
?
"%s.s%dc%d.input.alaw"
:
"%s/s%dc%d.input.alaw"
,
logname
?
logname
:
r2data
->
logdir
,
ftdmchan
->
span_id
,
ftdmchan
->
chan_id
);
f
=
fopen
(
dfile
,
"w"
);
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Dumping IO input in file %s
\n
"
,
dfile
);
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_DUMP_INPUT
,
f
);
fclose
(
f
);
snprintf
(
dfile
,
sizeof
(
dfile
),
logname
?
"%s.s%dc%d.output.alaw"
:
"%s/s%dc%d.output.alaw"
,
logname
?
logname
:
r2data
->
logdir
,
ftdmchan
->
span_id
,
ftdmchan
->
chan_id
);
f
=
fopen
(
dfile
,
"w"
);
ftdm_log_chan
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Dumping IO output in file %s
\n
"
,
dfile
);
ftdm_channel_command
(
ftdmchan
,
FTDM_COMMAND_DUMP_OUTPUT
,
f
);
fclose
(
f
);
}
}
static
void
ftdm_r2_on_call_accepted
(
openr2_chan_t
*
r2chan
,
openr2_call_mode_t
mode
)
static
void
ftdm_r2_on_call_accepted
(
openr2_chan_t
*
r2chan
,
openr2_call_mode_t
mode
)
{
{
ftdm_channel_t
*
ftdmchan
=
openr2_chan_get_client_data
(
r2chan
);
ftdm_channel_t
*
ftdmchan
=
openr2_chan_get_client_data
(
r2chan
);
...
@@ -493,6 +535,7 @@ static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t m
...
@@ -493,6 +535,7 @@ static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t m
/* at this point the MF signaling has ended and there is no point on keep reading */
/* at this point the MF signaling has ended and there is no point on keep reading */
openr2_chan_disable_read
(
r2chan
);
openr2_chan_disable_read
(
r2chan
);
R2CALL
(
ftdmchan
)
->
accepted
=
1
;
R2CALL
(
ftdmchan
)
->
accepted
=
1
;
if
(
OR2_DIR_BACKWARD
==
openr2_chan_get_direction
(
r2chan
))
{
if
(
OR2_DIR_BACKWARD
==
openr2_chan_get_direction
(
r2chan
))
{
...
@@ -579,7 +622,7 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err
...
@@ -579,7 +622,7 @@ static void ftdm_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_err
return
;
return
;
}
}
ftdm_log_chan_msg
(
ftdmchan
,
FTDM_LOG_ERROR
,
"Protocol error
\n
"
);
dump_mf
(
r2chan
);
clear_accept_pending
(
ftdmchan
);
clear_accept_pending
(
ftdmchan
);
...
@@ -1042,24 +1085,28 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
...
@@ -1042,24 +1085,28 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
/* .variant */
OR2_VAR_ITU
,
/* .variant */
OR2_VAR_ITU
,
/* .category */
OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
,
/* .category */
OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
,
/* .loglevel */
OR2_LOG_ERROR
|
OR2_LOG_WARNING
,
/* .loglevel */
OR2_LOG_ERROR
|
OR2_LOG_WARNING
,
/* .logdir */
(
char
*
)
"/usr/local/freeswitch/log/"
,
/* FIXME: get PREFIX variable */
#ifdef WIN32
/* .logdir */
(
char
*
)
"c:
\\
"
,
#else
/* .logdir */
(
char
*
)
"/tmp"
,
#endif
/* .advanced_protocol_file */
NULL
,
/* .advanced_protocol_file */
NULL
,
/* .max_ani */
10
,
/* .max_ani */
10
,
/* .max_dnis */
4
,
/* .max_dnis */
4
,
/* .mfback_timeout */
-
1
,
/* .mfback_timeout */
-
1
,
/* .metering_pulse_timeout */
-
1
,
/* .metering_pulse_timeout */
-
1
,
/* .mf_dump_size */
0
,
/* .immediate_accept */
-
1
,
/* .immediate_accept */
-
1
,
/* .skip_category */
-
1
,
/* .skip_category */
-
1
,
/* .get_ani_first */
-
1
,
/* .get_ani_first */
-
1
,
/* .call_files */
0
,
/* .call_files */
0
,
/* .mf_files */
0
,
/* .double_answer */
-
1
,
/* .double_answer */
-
1
,
/* .charge_calls */
-
1
,
/* .charge_calls */
-
1
,
/* .forced_release */
-
1
,
/* .forced_release */
-
1
,
/* .allow_collect_calls */
-
1
/* .allow_collect_calls */
-
1
};
};
assert
(
sig_cb
!=
NULL
);
ftdm_assert_return
(
sig_cb
!=
NULL
,
FTDM_FAIL
,
"No signaling cb provided
\n
"
);
if
(
span
->
signal_type
)
{
if
(
span
->
signal_type
)
{
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Span is already configured for signalling."
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Span is already configured for signalling."
);
...
@@ -1119,6 +1166,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
...
@@ -1119,6 +1166,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
continue
;
continue
;
}
}
log_level
=
val
;
log_level
=
val
;
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %s with loglevel %s
\n
"
,
span
->
name
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"advanced_protocol_file"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"advanced_protocol_file"
))
{
if
(
!
val
)
{
if
(
!
val
)
{
break
;
break
;
...
@@ -1128,46 +1176,51 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
...
@@ -1128,46 +1176,51 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
continue
;
continue
;
}
}
r2conf
.
advanced_protocol_file
=
(
char
*
)
val
;
r2conf
.
advanced_protocol_file
=
(
char
*
)
val
;
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %d with advanced protocol file %s
\n
"
,
span
->
span_id
,
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %s with advanced protocol file %s
\n
"
,
span
->
name
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"mf_dump_size"
))
{
r2conf
.
mf_dump_size
=
atoi
(
val
);
if
(
r2conf
.
mf_dump_size
<
0
)
{
r2conf
.
mf_dump_size
=
FTDM_IO_DUMP_DEFAULT_BUFF_SIZE
;
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %s with default mf_dump_size = %d bytes
\n
"
,
span
->
name
,
r2conf
.
mf_dump_size
);
}
else
{
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %s with mf_dump_size = %d bytes
\n
"
,
span
->
name
,
r2conf
.
mf_dump_size
);
}
}
else
if
(
!
strcasecmp
(
var
,
"allow_collect_calls"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"allow_collect_calls"
))
{
r2conf
.
allow_collect_calls
=
ftdm_true
(
val
);
r2conf
.
allow_collect_calls
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with allow collect calls max ani = %d
\n
"
,
span
->
span_id
,
r2conf
.
allow_collect_calls
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with allow collect calls max ani = %d
\n
"
,
span
->
name
,
r2conf
.
allow_collect_calls
);
}
else
if
(
!
strcasecmp
(
var
,
"double_answer"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"double_answer"
))
{
r2conf
.
double_answer
=
ftdm_true
(
val
);
r2conf
.
double_answer
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with double answer = %d
\n
"
,
span
->
span_id
,
r2conf
.
double_answer
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with double answer = %d
\n
"
,
span
->
name
,
r2conf
.
double_answer
);
}
else
if
(
!
strcasecmp
(
var
,
"immediate_accept"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"immediate_accept"
))
{
r2conf
.
immediate_accept
=
ftdm_true
(
val
);
r2conf
.
immediate_accept
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with immediate accept = %d
\n
"
,
span
->
span_id
,
r2conf
.
immediate_accept
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with immediate accept = %d
\n
"
,
span
->
name
,
r2conf
.
immediate_accept
);
}
else
if
(
!
strcasecmp
(
var
,
"skip_category"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"skip_category"
))
{
r2conf
.
skip_category
=
ftdm_true
(
val
);
r2conf
.
skip_category
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with skip category = %d
\n
"
,
span
->
span_id
,
r2conf
.
skip_category
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with skip category = %d
\n
"
,
span
->
name
,
r2conf
.
skip_category
);
}
else
if
(
!
strcasecmp
(
var
,
"forced_release"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"forced_release"
))
{
r2conf
.
forced_release
=
ftdm_true
(
val
);
r2conf
.
forced_release
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with forced release = %d
\n
"
,
span
->
span_id
,
r2conf
.
forced_release
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with forced release = %d
\n
"
,
span
->
name
,
r2conf
.
forced_release
);
}
else
if
(
!
strcasecmp
(
var
,
"charge_calls"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"charge_calls"
))
{
r2conf
.
charge_calls
=
ftdm_true
(
val
);
r2conf
.
charge_calls
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with charge calls = %d
\n
"
,
span
->
span_id
,
r2conf
.
charge_calls
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with charge calls = %d
\n
"
,
span
->
name
,
r2conf
.
charge_calls
);
}
else
if
(
!
strcasecmp
(
var
,
"get_ani_first"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"get_ani_first"
))
{
r2conf
.
get_ani_first
=
ftdm_true
(
val
);
r2conf
.
get_ani_first
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with get ani first = %d
\n
"
,
span
->
span_id
,
r2conf
.
get_ani_first
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with get ani first = %d
\n
"
,
span
->
name
,
r2conf
.
get_ani_first
);
}
else
if
(
!
strcasecmp
(
var
,
"call_files"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"call_files"
))
{
r2conf
.
call_files
=
ftdm_true
(
val
);
r2conf
.
call_files
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %d with call files = %d
\n
"
,
span
->
span_id
,
r2conf
.
call_files
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %s with call files = %d
\n
"
,
span
->
name
,
r2conf
.
call_files
);
}
else
if
(
!
strcasecmp
(
var
,
"mf_files"
))
{
r2conf
.
mf_files
=
ftdm_true
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %d with mf files = %d
\n
"
,
span
->
span_id
,
r2conf
.
mf_files
);
}
else
if
(
!
strcasecmp
(
var
,
"mfback_timeout"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"mfback_timeout"
))
{
r2conf
.
mfback_timeout
=
atoi
(
val
);
r2conf
.
mfback_timeout
=
atoi
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with MF backward timeout = %dms
\n
"
,
span
->
span_id
,
r2conf
.
mfback_timeout
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with MF backward timeout = %dms
\n
"
,
span
->
name
,
r2conf
.
mfback_timeout
);
}
else
if
(
!
strcasecmp
(
var
,
"metering_pulse_timeout"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"metering_pulse_timeout"
))
{
r2conf
.
metering_pulse_timeout
=
atoi
(
val
);
r2conf
.
metering_pulse_timeout
=
atoi
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with metering pulse timeout = %dms
\n
"
,
span
->
span_id
,
r2conf
.
metering_pulse_timeout
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with metering pulse timeout = %dms
\n
"
,
span
->
name
,
r2conf
.
metering_pulse_timeout
);
}
else
if
(
!
strcasecmp
(
var
,
"max_ani"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"max_ani"
))
{
r2conf
.
max_ani
=
atoi
(
val
);
r2conf
.
max_ani
=
atoi
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with max ani = %d
\n
"
,
span
->
span_id
,
r2conf
.
max_ani
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with max ani = %d
\n
"
,
span
->
name
,
r2conf
.
max_ani
);
}
else
if
(
!
strcasecmp
(
var
,
"max_dnis"
))
{
}
else
if
(
!
strcasecmp
(
var
,
"max_dnis"
))
{
r2conf
.
max_dnis
=
atoi
(
val
);
r2conf
.
max_dnis
=
atoi
(
val
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
d with max dnis = %d
\n
"
,
span
->
span_id
,
r2conf
.
max_dnis
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Configuring R2 span %
s with max dnis = %d
\n
"
,
span
->
name
,
r2conf
.
max_dnis
);
}
else
{
}
else
{
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Unknown R2 parameter [%s]"
,
var
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Unknown R2 parameter [%s]"
,
var
);
return
FTDM_FAIL
;
return
FTDM_FAIL
;
...
@@ -1212,10 +1265,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
...
@@ -1212,10 +1265,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
openr2_context_set_immediate_accept
(
r2data
->
r2context
,
r2conf
.
immediate_accept
);
openr2_context_set_immediate_accept
(
r2data
->
r2context
,
r2conf
.
immediate_accept
);
openr2_context_set_span_id
(
r2data
->
r2context
,
span
->
span_id
);
openr2_context_set_span_id
(
r2data
->
r2context
,
span
->
span_id
);
if
(
r2conf
.
logdir
&&
r2conf
.
logdir
[
0
])
{
ftdm_log
(
FTDM_LOG_DEBUG
,
"Setting span %s logdir to %s
\n
"
,
span
->
name
,
r2conf
.
logdir
);
ftdm_log
(
FTDM_LOG_DEBUG
,
"Setting openr2 for span %s logdir to %s
\n
"
,
span
->
name
,
r2conf
.
logdir
);
openr2_context_set_log_directory
(
r2data
->
r2context
,
r2conf
.
logdir
);
openr2_context_set_log_directory
(
r2data
->
r2context
,
r2conf
.
logdir
);
snprintf
(
r2data
->
logdir
,
sizeof
(
r2data
->
logdir
),
"%s"
,
r2conf
.
logdir
);
}
if
(
r2conf
.
advanced_protocol_file
)
{
if
(
r2conf
.
advanced_protocol_file
)
{
openr2_context_configure_from_advanced_file
(
r2data
->
r2context
,
r2conf
.
advanced_protocol_file
);
openr2_context_configure_from_advanced_file
(
r2data
->
r2context
,
r2conf
.
advanced_protocol_file
);
}
}
...
@@ -1253,6 +1306,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
...
@@ -1253,6 +1306,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
hashtable_insert
(
spanpvt
->
r2calls
,
(
void
*
)
r2call
->
name
,
r2call
,
HASHTABLE_FLAG_FREE_VALUE
);
hashtable_insert
(
spanpvt
->
r2calls
,
(
void
*
)
r2call
->
name
,
r2call
,
HASHTABLE_FLAG_FREE_VALUE
);
}
}
r2data
->
mf_dump_size
=
r2conf
.
mf_dump_size
;
r2data
->
flags
=
0
;
r2data
->
flags
=
0
;
spanpvt
->
r2context
=
r2data
->
r2context
;
spanpvt
->
r2context
=
r2data
->
r2context
;
...
...
libs/freetdm/src/include/freetdm.h
浏览文件 @
004cc9d7
...
@@ -351,6 +351,7 @@ typedef struct ftdm_channel_config {
...
@@ -351,6 +351,7 @@ typedef struct ftdm_channel_config {
ftdm_chan_type_t
type
;
ftdm_chan_type_t
type
;
float
rxgain
;
float
rxgain
;
float
txgain
;
float
txgain
;
uint8_t
debugdtmf
;
}
ftdm_channel_config_t
;
}
ftdm_channel_config_t
;
/*!
/*!
...
@@ -431,9 +432,38 @@ typedef enum {
...
@@ -431,9 +432,38 @@ typedef enum {
FTDM_COMMAND_WINK
,
FTDM_COMMAND_WINK
,
FTDM_COMMAND_ENABLE_PROGRESS_DETECT
,
FTDM_COMMAND_ENABLE_PROGRESS_DETECT
,
FTDM_COMMAND_DISABLE_PROGRESS_DETECT
,
FTDM_COMMAND_DISABLE_PROGRESS_DETECT
,
/*!< Start tracing input and output from channel to the given file */
FTDM_COMMAND_TRACE_INPUT
,
FTDM_COMMAND_TRACE_INPUT
,
FTDM_COMMAND_TRACE_OUTPUT
,
FTDM_COMMAND_TRACE_OUTPUT
,
/*!< Stop both Input and Output trace, closing the files */
FTDM_COMMAND_TRACE_END_ALL
,
FTDM_COMMAND_TRACE_END_ALL
,
/*!< Enable DTMF debugging */
FTDM_COMMAND_ENABLE_DEBUG_DTMF
,
/*!< Disable DTMF debugging (if not disabled explicitly, it is disabled automatically when calls hangup) */
FTDM_COMMAND_DISABLE_DEBUG_DTMF
,
/*!< Start dumping all input to a circular buffer. The size of the circular buffer can be specified, default used otherwise */
FTDM_COMMAND_ENABLE_INPUT_DUMP
,
/*!< Stop dumping all input to a circular buffer. */
FTDM_COMMAND_DISABLE_INPUT_DUMP
,
/*!< Start dumping all output to a circular buffer. The size of the circular buffer can be specified, default used otherwise */
FTDM_COMMAND_ENABLE_OUTPUT_DUMP
,
/*!< Stop dumping all output to a circular buffer. */
FTDM_COMMAND_DISABLE_OUTPUT_DUMP
,
/*!< Dump the current input circular buffer to the specified FILE* structure */
FTDM_COMMAND_DUMP_INPUT
,
/*!< Dump the current output circular buffer to the specified FILE* structure */
FTDM_COMMAND_DUMP_OUTPUT
,
FTDM_COMMAND_ENABLE_CALLERID_DETECT
,
FTDM_COMMAND_ENABLE_CALLERID_DETECT
,
FTDM_COMMAND_DISABLE_CALLERID_DETECT
,
FTDM_COMMAND_DISABLE_CALLERID_DETECT
,
FTDM_COMMAND_ENABLE_ECHOCANCEL
,
FTDM_COMMAND_ENABLE_ECHOCANCEL
,
...
...
libs/freetdm/src/include/private/ftdm_core.h
浏览文件 @
004cc9d7
...
@@ -342,21 +342,24 @@ typedef enum {
...
@@ -342,21 +342,24 @@ typedef enum {
FTDM_TYPE_CHANNEL
FTDM_TYPE_CHANNEL
}
ftdm_data_type_t
;
}
ftdm_data_type_t
;
#ifdef FTDM_DEBUG_DTMF
/* number of bytes for the IO dump circular buffer (5 seconds worth of audio by default) */
/* number of bytes for the circular buffer (5 seconds worth of audio) */
#define FTDM_IO_DUMP_DEFAULT_BUFF_SIZE 8 * 5000
#define DTMF_DEBUG_SIZE 8 * 5000
/* number of 20ms cycles before timeout and close the debug dtmf file (5 seconds) */
#define DTMF_DEBUG_TIMEOUT 250
typedef
struct
{
typedef
struct
{
FILE
*
file
;
char
*
buffer
;
char
buffer
[
DTMF_DEBUG_SIZE
]
;
ftdm_size_t
size
;
int
windex
;
int
windex
;
int
wrapped
;
int
wrapped
;
int
closetimeout
;
}
ftdm_io_dump_t
;
/* number of interval cycles before timeout and close the debug dtmf file (5 seconds if interval is 20) */
#define DTMF_DEBUG_TIMEOUT 250
typedef
struct
{
uint8_t
enabled
;
uint8_t
requested
;
FILE
*
file
;
int32_t
closetimeout
;
ftdm_mutex_t
*
mutex
;
ftdm_mutex_t
*
mutex
;
}
ftdm_dtmf_debug_t
;
}
ftdm_dtmf_debug_t
;
#endif
typedef
struct
{
typedef
struct
{
const
char
*
file
;
const
char
*
file
;
...
@@ -471,9 +474,9 @@ struct ftdm_channel {
...
@@ -471,9 +474,9 @@ struct ftdm_channel {
void
*
user_private
;
void
*
user_private
;
ftdm_timer_id_t
hangup_timer
;
ftdm_timer_id_t
hangup_timer
;
ftdm_channel_iostats_t
iostats
;
ftdm_channel_iostats_t
iostats
;
#ifdef FTDM_DEBUG_DTMF
ftdm_dtmf_debug_t
dtmfdbg
;
ftdm_dtmf_debug_t
dtmfdbg
;
#endif
ftdm_io_dump_t
rxdump
;
ftdm_io_dump_t
txdump
;
};
};
struct
ftdm_span
{
struct
ftdm_span
{
...
...
libs/freetdm/src/include/private/ftdm_types.h
浏览文件 @
004cc9d7
...
@@ -58,6 +58,7 @@ typedef int ftdm_filehandle_t;
...
@@ -58,6 +58,7 @@ typedef int ftdm_filehandle_t;
extern
"C"
{
extern
"C"
{
#endif
#endif
#define FTDM_COMMAND_OBJ_SIZE *((ftdm_size_t *)obj)
#define FTDM_COMMAND_OBJ_INT *((int *)obj)
#define FTDM_COMMAND_OBJ_INT *((int *)obj)
#define FTDM_COMMAND_OBJ_CHAR_P (char *)obj
#define FTDM_COMMAND_OBJ_CHAR_P (char *)obj
#define FTDM_COMMAND_OBJ_FLOAT *(float *)obj
#define FTDM_COMMAND_OBJ_FLOAT *(float *)obj
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论