Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
12b5bde2
提交
12b5bde2
authored
9月 04, 2012
作者:
Steve Underwood
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of git.freeswitch.org:freeswitch
上级
7c6f6e30
f012b7ab
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
591 行增加
和
322 行删除
+591
-322
ftmod_libpri.c
libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
+307
-193
ftmod_libpri.h
libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h
+26
-0
lpwrap_pri.c
libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c
+240
-123
lpwrap_pri.h
libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h
+18
-6
没有找到文件。
libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
浏览文件 @
12b5bde2
...
...
@@ -38,6 +38,8 @@
static
ftdm_status_t
ftdm_libpri_start
(
ftdm_span_t
*
span
);
static
ftdm_io_interface_t
ftdm_libpri_interface
;
static
int
on_timeout_t302
(
struct
lpwrap_pri
*
spri
,
struct
lpwrap_timer
*
timer
);
static
void
_ftdm_channel_set_state_force
(
ftdm_channel_t
*
chan
,
const
ftdm_channel_state_t
state
)
{
...
...
@@ -902,8 +904,10 @@ static ftdm_state_map_t isdn_state_map = {
*/
static
ftdm_status_t
state_advance
(
ftdm_channel_t
*
chan
)
{
ftdm_libpri_data_t
*
isdn_data
=
chan
->
span
->
signal_data
;
q931_call
*
call
=
(
q931_call
*
)
chan
->
call_data
;
ftdm_span_t
*
span
=
ftdm_channel_get_span
(
chan
);
ftdm_libpri_data_t
*
isdn_data
=
span
->
signal_data
;
ftdm_libpri_b_chan_t
*
chan_priv
=
chan
->
call_data
;
q931_call
*
call
=
chan_priv
->
call
;
ftdm_status_t
status
;
ftdm_sigmsg_t
sig
;
...
...
@@ -920,21 +924,26 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
switch
(
ftdm_channel_get_state
(
chan
))
{
case
FTDM_CHANNEL_STATE_DOWN
:
{
ftdm_channel_t
*
chtmp
=
chan
;
if
(
ftdm_channel_get_type
(
chan
)
==
FTDM_CHAN_TYPE_B
)
{
ftdm_channel_t
*
chtmp
=
chan
;
if
(
call
)
{
pri_destroycall
(
isdn_data
->
spri
.
pri
,
call
);
chan
->
call_data
=
NULL
;
}
if
(
call
)
{
pri_destroycall
(
isdn_data
->
spri
.
pri
,
call
);
chan_priv
->
call
=
NULL
;
}
if
(
ftdm_channel_close
(
&
chtmp
)
!=
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_WARNING
,
"-- Failed to close channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
chan
),
ftdm_channel_get_id
(
chan
));
}
else
{
ftdm_log
(
FTDM_LOG_DEBUG
,
"-- Closed channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
chan
),
ftdm_channel_get_id
(
chan
));
/* Stop T302 */
lpwrap_stop_timer
(
&
isdn_data
->
spri
,
&
chan_priv
->
t302
);
if
(
ftdm_channel_close
(
&
chtmp
)
!=
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_WARNING
,
"-- Failed to close channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
chan
),
ftdm_channel_get_id
(
chan
));
}
else
{
ftdm_log
(
FTDM_LOG_DEBUG
,
"-- Closed channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
chan
),
ftdm_channel_get_id
(
chan
));
}
}
}
break
;
...
...
@@ -943,7 +952,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
{
if
(
ftdm_test_flag
(
chan
,
FTDM_CHANNEL_OUTBOUND
))
{
sig
.
event_id
=
FTDM_SIGEVENT_PROGRESS
;
if
((
status
=
ftdm_span_send_signal
(
ftdm_channel_get_span
(
chan
)
,
&
sig
)
!=
FTDM_SUCCESS
))
{
if
((
status
=
ftdm_span_send_signal
(
span
,
&
sig
)
!=
FTDM_SUCCESS
))
{
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_HANGUP
);
}
}
else
if
(
call
)
{
...
...
@@ -958,7 +967,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
{
if
(
ftdm_test_flag
(
chan
,
FTDM_CHANNEL_OUTBOUND
))
{
sig
.
event_id
=
FTDM_SIGEVENT_RINGING
;
if
((
status
=
ftdm_span_send_signal
(
ftdm_channel_get_span
(
chan
)
,
&
sig
)
!=
FTDM_SUCCESS
))
{
if
((
status
=
ftdm_span_send_signal
(
span
,
&
sig
)
!=
FTDM_SUCCESS
))
{
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_HANGUP
);
}
}
else
if
(
call
)
{
...
...
@@ -974,7 +983,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
{
if
(
ftdm_test_flag
(
chan
,
FTDM_CHANNEL_OUTBOUND
))
{
sig
.
event_id
=
FTDM_SIGEVENT_PROGRESS_MEDIA
;
if
((
status
=
ftdm_span_send_signal
(
ftdm_channel_get_span
(
chan
)
,
&
sig
)
!=
FTDM_SUCCESS
))
{
if
((
status
=
ftdm_span_send_signal
(
span
,
&
sig
)
!=
FTDM_SUCCESS
))
{
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_HANGUP
);
}
}
else
if
(
call
)
{
...
...
@@ -994,7 +1003,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
if
(
ftdm_test_flag
(
chan
,
FTDM_CHANNEL_OUTBOUND
))
{
/* PROCEED from other end, notify user */
sig
.
event_id
=
FTDM_SIGEVENT_PROCEED
;
if
((
status
=
ftdm_span_send_signal
(
ftdm_channel_get_span
(
chan
)
,
&
sig
)
!=
FTDM_SUCCESS
))
{
if
((
status
=
ftdm_span_send_signal
(
span
,
&
sig
)
!=
FTDM_SUCCESS
))
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Failed to send PROCEED sigevent on Channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
chan
),
ftdm_channel_get_id
(
chan
));
...
...
@@ -1024,6 +1033,11 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
caller_data
->
hangup_cause
=
FTDM_CAUSE_DESTINATION_OUT_OF_ORDER
;
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_HANGUP
);
}
else
{
/* Start T302 */
lpwrap_start_timer
(
&
isdn_data
->
spri
,
&
chan_priv
->
t302
,
isdn_data
->
overlap_timeout_ms
,
&
on_timeout_t302
);
}
}
else
{
ftdm_log_chan_msg
(
chan
,
FTDM_LOG_ERROR
,
"Overlap receiving on outbound call?
\n
"
);
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_RESTART
);
...
...
@@ -1042,7 +1056,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
pri_proceeding
(
isdn_data
->
spri
.
pri
,
call
,
ftdm_channel_get_id
(
chan
),
0
);
// pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
sig
.
event_id
=
FTDM_SIGEVENT_START
;
if
((
status
=
ftdm_span_send_signal
(
ftdm_channel_get_span
(
chan
)
,
&
sig
)
!=
FTDM_SUCCESS
))
{
if
((
status
=
ftdm_span_send_signal
(
span
,
&
sig
)
!=
FTDM_SUCCESS
))
{
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_HANGUP
);
}
}
else
{
...
...
@@ -1054,10 +1068,20 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
case
FTDM_CHANNEL_STATE_RESTART
:
{
chan
->
caller_data
.
hangup_cause
=
FTDM_CAUSE_NORMAL_UNSPECIFIED
;
sig
.
event_id
=
FTDM_SIGEVENT_RESTART
;
status
=
ftdm_span_send_signal
(
ftdm_channel_get_span
(
chan
),
&
sig
);
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_DOWN
);
if
(
ftdm_channel_get_type
(
chan
)
==
FTDM_CHAN_TYPE_B
)
{
chan
->
caller_data
.
hangup_cause
=
FTDM_CAUSE_NORMAL_UNSPECIFIED
;
sig
.
event_id
=
FTDM_SIGEVENT_RESTART
;
status
=
ftdm_span_send_signal
(
span
,
&
sig
);
if
(
!
(
chan_priv
->
flags
&
FTDM_LIBPRI_B_REMOTE_RESTART
))
{
/* Locally triggered restart, send RESTART to remote, wait for ACK */
pri_reset
(
isdn_data
->
spri
.
pri
,
ftdm_channel_get_id
(
chan
));
}
else
{
/* Remote restart complete, clear flag */
chan_priv
->
flags
&=
~
FTDM_LIBPRI_B_REMOTE_RESTART
;
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_DOWN
);
}
}
}
break
;
...
...
@@ -1065,7 +1089,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
{
if
(
ftdm_test_flag
(
chan
,
FTDM_CHANNEL_OUTBOUND
))
{
sig
.
event_id
=
FTDM_SIGEVENT_UP
;
if
((
status
=
ftdm_span_send_signal
(
ftdm_channel_get_span
(
chan
)
,
&
sig
)
!=
FTDM_SUCCESS
))
{
if
((
status
=
ftdm_span_send_signal
(
span
,
&
sig
)
!=
FTDM_SUCCESS
))
{
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_HANGUP
);
}
}
else
if
(
call
)
{
...
...
@@ -1109,7 +1133,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
ton
=
isdn_data
->
ton
;
}
chan
->
call_data
=
call
;
chan
_priv
->
call
=
call
;
sr
=
pri_sr_new
();
if
(
!
sr
)
{
...
...
@@ -1155,7 +1179,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
pri_hangup
(
isdn_data
->
spri
.
pri
,
call
,
caller_data
->
hangup_cause
);
// pri_destroycall(isdn_data->spri.pri, call);
// chan
->call_data
= NULL;
// chan
_priv->call
= NULL;
}
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_HANGUP_COMPLETE
);
}
...
...
@@ -1165,7 +1189,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
{
// if (call) {
// pri_destroycall(isdn_data->spri.pri, call);
// chan
->call_data
= NULL;
// chan
_priv->call
= NULL;
// }
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_DOWN
);
}
...
...
@@ -1174,7 +1198,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
case
FTDM_CHANNEL_STATE_TERMINATING
:
{
sig
.
event_id
=
FTDM_SIGEVENT_STOP
;
status
=
ftdm_span_send_signal
(
ftdm_channel_get_span
(
chan
)
,
&
sig
);
status
=
ftdm_span_send_signal
(
span
,
&
sig
);
/* user moves us to HANGUP and from there we go to DOWN */
}
default:
...
...
@@ -1203,18 +1227,48 @@ static __inline__ void check_state(ftdm_span_t *span)
}
}
/**
* \brief Handler for libpri
information event (incoming call?)
* \brief Handler for libpri
keypad digit event
* \param spri Pri wrapper structure (libpri, span, dchan)
* \param event_type Event type (unused)
* \param pevent Event
* \return 0
*/
static
int
on_
info
(
lpwrap_pri_t
*
spri
,
lpwrap_pri_event_t
event_type
,
pri_event
*
pevent
)
static
int
on_
keypad_digit
(
lpwrap_pri_t
*
spri
,
lpwrap_pri_event_t
event_type
,
pri_event
*
pevent
)
{
ftdm_span_t
*
span
=
spri
->
span
;
ftdm_channel_t
*
chan
=
ftdm_span_get_channel
(
span
,
pevent
->
ring
.
channel
);
if
(
!
chan
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"-- Keypad event on invalid channel %d:%d
\n
"
,
ftdm_span_get_id
(
span
),
pevent
->
ring
.
channel
);
return
0
;
}
ftdm_log_chan
(
chan
,
FTDM_LOG_DEBUG
,
"-- Keypad event received, incoming digits: '%s'
\n
"
,
pevent
->
digit
.
digits
);
/* Enqueue DTMF digits on channel */
ftdm_channel_queue_dtmf
(
chan
,
pevent
->
digit
.
digits
);
return
0
;
}
/**
* \brief Handler for libpri information event (overlap receiving)
* \param spri Pri wrapper structure (libpri, span, dchan)
* \param event_type Event type (unused)
* \param pevent Event
* \return 0
*/
static
int
on_information
(
lpwrap_pri_t
*
spri
,
lpwrap_pri_event_t
event_type
,
pri_event
*
pevent
)
{
ftdm_span_t
*
span
=
spri
->
span
;
ftdm_channel_t
*
chan
=
ftdm_span_get_channel
(
span
,
pevent
->
ring
.
channel
);
ftdm_libpri_b_chan_t
*
chan_priv
=
NULL
;
ftdm_caller_data_t
*
caller_data
=
NULL
;
ftdm_libpri_data_t
*
isdn_data
=
span
->
signal_data
;
if
(
!
chan
)
{
ftdm_log
(
FTDM_LOG_CRIT
,
"-- Info on channel %d:%d but it's not in use?
\n
"
,
ftdm_span_get_id
(
span
),
pevent
->
ring
.
channel
);
...
...
@@ -1222,11 +1276,19 @@ static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
}
caller_data
=
ftdm_channel_get_caller_data
(
chan
);
chan_priv
=
chan
->
call_data
;
switch
(
ftdm_channel_get_state
(
chan
))
{
case
FTDM_CHANNEL_STATE_COLLECT
:
/* TE-mode overlap receiving */
ftdm_log_chan
(
chan
,
FTDM_LOG_DEBUG
,
"-- Incoming INFORMATION indication, current called number: '%s', number complete: %s
\n
"
,
pevent
->
ring
.
callednum
,
pevent
->
ring
.
complete
?
"yes"
:
"no"
);
case
FTDM_CHANNEL_STATE_DIALTONE
:
/* NT-mode overlap receiving */
ftdm_log_chan
(
chan
,
FTDM_LOG_DEBUG
,
"-- Incoming INFORMATION indication, received digits: '%s', number complete: %c, collected digits: '%s'
\n
"
,
pevent
->
ring
.
callednum
,
pevent
->
ring
.
complete
?
'Y'
:
'N'
,
caller_data
->
dnis
.
digits
);
/* Stop T302 */
lpwrap_stop_timer
(
spri
,
&
chan_priv
->
t302
);
/* append digits to dnis */
if
(
!
ftdm_strlen_zero
(
pevent
->
ring
.
callednum
))
{
...
...
@@ -1241,7 +1303,7 @@ static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
len
=
ftdm_min
(
sizeof
(
caller_data
->
dnis
.
digits
)
-
1
-
offset
,
digits
);
/* max. length without terminator */
if
(
len
<
digits
)
{
ftdm_log_chan
(
chan
,
FTDM_LOG_WARNING
,
"
Length %d of digit string
exceeds available space %d of DNIS, truncating!
\n
"
,
ftdm_log_chan
(
chan
,
FTDM_LOG_WARNING
,
"
Digit string of length %d
exceeds available space %d of DNIS, truncating!
\n
"
,
digits
,
len
);
}
if
(
len
)
{
...
...
@@ -1250,25 +1312,16 @@ static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
}
}
if
(
pevent
->
ring
.
complete
)
{
ftdm_log_chan_msg
(
chan
,
FTDM_LOG_DEBUG
,
"Number complete indicated, moving channel to RING state
\n
"
);
ftdm_log_chan_msg
(
chan
,
FTDM_LOG_DEBUG
,
"Number complete indicat
ion receiv
ed, moving channel to RING state
\n
"
);
/* notify switch */
ftdm_set_state
(
chan
,
FTDM_CHANNEL_STATE_RING
);
}
break
;
case
FTDM_CHANNEL_STATE_DIALTONE
:
/* NT-mode overlap receiving */
ftdm_log_chan
(
chan
,
FTDM_LOG_DEBUG
,
"-- Incoming INFORMATION indication, current called number: '%s'
\n
"
,
pevent
->
ring
.
callednum
);
/* Need to add proper support for overlap receiving in NT-mode (requires FreeSWITCH + FreeTDM core support) */
if
(
strlen
(
pevent
->
ring
.
callednum
)
>
3
)
{
ftdm_log
(
FTDM_LOG_DEBUG
,
"final number is: %s
\n
"
,
pevent
->
ring
.
callednum
);
pri_answer
(
spri
->
pri
,
pevent
->
ring
.
call
,
0
,
1
);
}
else
{
/* Restart T302 */
lpwrap_start_timer
(
spri
,
&
chan_priv
->
t302
,
isdn_data
->
overlap_timeout_ms
,
&
on_timeout_t302
);
}
break
;
default:
ftdm_log_chan
(
chan
,
FTDM_LOG_ERROR
,
"-- INFORMATION indication on channel %d:%d in invalid state '%s'
\n
"
,
ftdm_channel_get_span_id
(
chan
),
ftdm_channel_get_id
(
chan
),
ftdm_log_chan
(
chan
,
FTDM_LOG_ERROR
,
"-- INFORMATION indication in invalid state '%s'
\n
"
,
ftdm_channel_get_state_str
(
chan
));
}
return
0
;
...
...
@@ -1650,6 +1703,7 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
{
ftdm_span_t
*
span
=
spri
->
span
;
ftdm_libpri_data_t
*
isdn_data
=
span
->
signal_data
;
ftdm_libpri_b_chan_t
*
chan_priv
=
NULL
;
ftdm_channel_t
*
chan
=
NULL
;
ftdm_caller_data_t
*
caller_data
=
NULL
;
int
ret
=
0
;
...
...
@@ -1730,11 +1784,14 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
}
}
if
(
chan
->
call_data
)
{
/* Get per-channel private data */
chan_priv
=
chan
->
call_data
;
if
(
chan_priv
->
call
)
{
/* we could drop the incoming call, but most likely the pointer is just a ghost of the past,
* this check is just to detect potentially unreleased pointers */
ftdm_log_chan
(
chan
,
FTDM_LOG_WARNING
,
"Channel already has call %p!
\n
"
,
chan
->
call_data
);
chan
->
call_data
=
NULL
;
ftdm_log_chan
(
chan
,
FTDM_LOG_WARNING
,
"Channel already has call %p!
\n
"
,
chan
_priv
->
call
);
chan
_priv
->
call
=
NULL
;
}
caller_data
=
ftdm_channel_get_caller_data
(
chan
);
...
...
@@ -1761,7 +1818,7 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
// scary to trust this pointer, you'd think they would give you a copy of the call data so you own it......
/* hurr, this is valid as along as nobody releases the call */
chan
->
call_data
=
pevent
->
ring
.
call
;
chan
_priv
->
call
=
pevent
->
ring
.
call
;
/* Open Channel if inband information is available */
if
((
pevent
->
ring
.
progressmask
&
PRI_PROG_INBAND_AVAILABLE
))
{
...
...
@@ -1799,6 +1856,21 @@ done:
return
ret
;
}
/**
* Timeout handler for T302 (overlap receiving)
*/
static
int
on_timeout_t302
(
struct
lpwrap_pri
*
spri
,
struct
lpwrap_timer
*
timer
)
{
ftdm_libpri_b_chan_t
*
chan_priv
=
ftdm_container_of
(
timer
,
ftdm_libpri_b_chan_t
,
t302
);
ftdm_channel_t
*
chan
=
chan_priv
->
channel
;
ftdm_log
(
FTDM_LOG_NOTICE
,
"-- T302 timed out, going to state RING
\n
"
);
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_RING
);
return
0
;
}
/**
* \brief Processes freetdm event
* \param span Span on which the event was fired
...
...
@@ -1826,22 +1898,15 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
}
ftdm_set_flag
(
event
->
channel
,
FTDM_CHANNEL_SUSPENDED
);
ftdm_channel_get_alarms
(
event
->
channel
,
&
alarmbits
);
ftdm_log
(
FTDM_LOG_WARNING
,
"channel %d:%d (%d:%d) has alarms! [%s]
\n
"
,
ftdm_channel_get_span_id
(
event
->
channel
),
ftdm_channel_get_id
(
event
->
channel
),
ftdm_channel_get_ph_span_id
(
event
->
channel
),
ftdm_channel_get_ph_id
(
event
->
channel
),
ftdm_channel_get_last_error
(
event
->
channel
));
ftdm_log_chan_msg
(
event
->
channel
,
FTDM_LOG_WARNING
,
"channel has alarms!
\n
"
);
}
break
;
case
FTDM_OOB_ALARM_CLEAR
:
{
ftdm_log
(
FTDM_LOG_WARNING
,
"channel %d:%d (%d:%d) alarms Cleared!
\n
"
,
ftdm_channel_get_span_id
(
event
->
channel
),
ftdm_channel_get_id
(
event
->
channel
),
ftdm_channel_get_ph_span_id
(
event
->
channel
),
ftdm_channel_get_ph_id
(
event
->
channel
));
ftdm_clear_flag
(
event
->
channel
,
FTDM_CHANNEL_SUSPENDED
);
ftdm_channel_get_alarms
(
event
->
channel
,
&
alarmbits
);
ftdm_log_chan_msg
(
event
->
channel
,
FTDM_LOG_WARNING
,
"channel alarms cleared!
\n
"
);
}
break
;
}
...
...
@@ -1892,11 +1957,6 @@ static __inline__ void check_events(ftdm_span_t *span)
static
int
check_flags
(
lpwrap_pri_t
*
spri
)
{
ftdm_span_t
*
span
=
spri
->
span
;
if
(
!
ftdm_running
()
||
ftdm_test_flag
(
span
,
FTDM_SPAN_STOP_THREAD
))
{
return
-
1
;
}
check_state
(
span
);
check_events
(
span
);
return
0
;
...
...
@@ -1911,24 +1971,84 @@ static int check_flags(lpwrap_pri_t *spri)
*/
static
int
on_restart
(
lpwrap_pri_t
*
spri
,
lpwrap_pri_event_t
event_type
,
pri_event
*
pevent
)
{
ftdm_channel_t
*
chan
=
NULL
;
ftdm_span_t
*
span
=
spri
->
span
;
ftdm_channel_t
*
chan
=
ftdm_span_get_channel
(
span
,
pevent
->
restart
.
channel
)
;
int
i
;
ftdm_log
(
FTDM_LOG_NOTICE
,
"-- Restarting %d:%d
\n
"
,
ftdm_span_get_id
(
span
),
pevent
->
restart
.
channel
);
_ftdm_channel_set_state_force
(
spri
->
dchan
,
FTDM_CHANNEL_STATE_UP
);
if
(
pevent
->
restart
.
channel
<
1
)
{
ftdm_log_chan_msg
(
spri
->
dchan
,
FTDM_LOG_NOTICE
,
"-- Restarting interface
\n
"
);
if
(
!
chan
)
{
return
0
;
for
(
i
=
1
;
i
<=
ftdm_span_get_chan_count
(
span
);
i
++
)
{
chan
=
ftdm_span_get_channel
(
span
,
i
);
if
(
!
chan
)
continue
;
if
(
ftdm_channel_get_type
(
chan
)
==
FTDM_CHAN_TYPE_B
)
{
ftdm_libpri_b_chan_t
*
chan_priv
=
chan
->
call_data
;
chan_priv
->
flags
|=
FTDM_LIBPRI_B_REMOTE_RESTART
;
/* Remote triggered RESTART, set flag */
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_RESTART
);
}
}
}
else
if
((
chan
=
ftdm_span_get_channel
(
span
,
pevent
->
restart
.
channel
)))
{
ftdm_libpri_b_chan_t
*
chan_priv
=
chan
->
call_data
;
if
(
pevent
->
restart
.
channel
<
1
)
{
ftdm_set_state_all
(
span
,
FTDM_CHANNEL_STATE_RESTART
);
}
else
{
ftdm_log_chan_msg
(
chan
,
FTDM_LOG_NOTICE
,
"-- Restarting single channel
\n
"
);
chan_priv
->
flags
|=
FTDM_LIBPRI_B_REMOTE_RESTART
;
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_RESTART
);
}
else
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Invalid restart indicator / channel id '%d' received
\n
"
,
pevent
->
restart
.
channel
);
}
_ftdm_channel_set_state_force
(
spri
->
dchan
,
FTDM_CHANNEL_STATE_UP
);
return
0
;
}
/**
* \brief Handler for libpri restart acknowledge event
* \param spri Pri wrapper structure (libpri, span, dchan)
* \param event_type Event type (unused)
* \param pevent Event
* \return 0
*/
static
int
on_restart_ack
(
lpwrap_pri_t
*
spri
,
lpwrap_pri_event_t
event_type
,
pri_event
*
pevent
)
{
ftdm_channel_t
*
chan
=
NULL
;
ftdm_span_t
*
span
=
spri
->
span
;
int
i
;
if
(
pevent
->
restartack
.
channel
<
1
)
{
ftdm_log_chan_msg
(
spri
->
dchan
,
FTDM_LOG_NOTICE
,
"-- Restart of interface completed
\n
"
);
for
(
i
=
1
;
i
<=
ftdm_span_get_chan_count
(
span
);
i
++
)
{
chan
=
ftdm_span_get_channel
(
span
,
i
);
if
(
!
chan
)
continue
;
if
(
ftdm_channel_get_type
(
chan
)
==
FTDM_CHAN_TYPE_B
)
{
ftdm_libpri_b_chan_t
*
chan_priv
=
chan
->
call_data
;
if
(
!
(
chan_priv
->
flags
&
FTDM_LIBPRI_B_REMOTE_RESTART
))
{
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_DOWN
);
}
}
}
}
else
if
((
chan
=
ftdm_span_get_channel
(
span
,
pevent
->
restart
.
channel
)))
{
ftdm_log_chan_msg
(
chan
,
FTDM_LOG_NOTICE
,
"-- Restart of channel completed
\n
"
);
ftdm_set_state_locked
(
chan
,
FTDM_CHANNEL_STATE_DOWN
);
}
else
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Invalid restart indicator / channel id '%d' received
\n
"
,
pevent
->
restartack
.
channel
);
}
_ftdm_channel_set_state_force
(
spri
->
dchan
,
FTDM_CHANNEL_STATE_UP
);
return
0
;
}
/*
* FACILITY Advice-On-Charge handler
*/
...
...
@@ -2224,111 +2344,89 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
ftdm_span_t
*
span
=
(
ftdm_span_t
*
)
obj
;
ftdm_libpri_data_t
*
isdn_data
=
span
->
signal_data
;
int
down
=
0
;
int
got_d
=
0
;
int
res
=
0
;
int
i
;
ftdm_set_flag
(
span
,
FTDM_SPAN_IN_THREAD
);
isdn_data
->
dchan
=
NULL
;
while
(
ftdm_running
()
&&
!
ftdm_test_flag
(
span
,
FTDM_SPAN_STOP_THREAD
))
{
if
(
!
got_d
)
{
int
i
,
x
;
for
(
i
=
1
,
x
=
0
;
i
<=
ftdm_span_get_chan_count
(
span
);
i
++
)
{
ftdm_channel_t
*
chan
=
ftdm_span_get_channel
(
span
,
i
);
if
(
ftdm_channel_get_type
(
chan
)
==
FTDM_CHAN_TYPE_DQ921
)
{
if
(
ftdm_channel_open
(
ftdm_span_get_id
(
span
),
i
,
&
isdn_data
->
dchan
)
==
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_DEBUG
,
"opening D-Channel #%d %d:%d
\n
"
,
x
,
ftdm_channel_get_span_id
(
isdn_data
->
dchan
),
ftdm_channel_get_id
(
isdn_data
->
dchan
));
got_d
=
1
;
x
++
;
break
;
}
else
{
ftdm_log
(
FTDM_LOG_ERROR
,
"failed to open D-Channel #%d %d:%d
\n
"
,
x
,
ftdm_channel_get_span_id
(
chan
),
ftdm_channel_get_id
(
chan
));
}
}
/*
* Open D-Channel
*/
for
(
i
=
1
;
i
<=
ftdm_span_get_chan_count
(
span
);
i
++
)
{
ftdm_channel_t
*
chan
=
ftdm_span_get_channel
(
span
,
i
);
if
(
ftdm_channel_get_type
(
chan
)
==
FTDM_CHAN_TYPE_DQ921
)
{
if
(
ftdm_channel_open
(
ftdm_span_get_id
(
span
),
i
,
&
isdn_data
->
dchan
)
==
FTDM_SUCCESS
)
{
ftdm_log_chan_msg
(
chan
,
FTDM_LOG_DEBUG
,
"Opened D-Channel
\n
"
);
break
;
}
else
{
ftdm_log_chan_msg
(
chan
,
FTDM_LOG_CRIT
,
"Failed to open D-Channel
\n
"
);
goto
out
;
}
}
if
(
!
got_d
||
!
isdn_data
->
dchan
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Failed to get a D-Channel in span %d
\n
"
,
ftdm_span_get_id
(
span
));
break
;
}
}
/* Initialize libpri trunk */
switch
(
ftdm_span_get_trunk_type
(
span
))
{
case
FTDM_TRUNK_E1
:
case
FTDM_TRUNK_T1
:
case
FTDM_TRUNK_J1
:
res
=
lpwrap_init_pri
(
&
isdn_data
->
spri
,
span
,
isdn_data
->
dchan
,
isdn_data
->
dialect
,
isdn_data
->
mode
,
isdn_data
->
debug_mask
);
break
;
case
FTDM_TRUNK_BRI
:
res
=
lpwrap_init_bri
(
&
isdn_data
->
spri
,
span
,
isdn_data
->
dchan
,
isdn_data
->
dialect
,
isdn_data
->
mode
,
1
,
isdn_data
->
debug_mask
);
#ifndef HAVE_LIBPRI_BRI
goto
out
;
#endif
break
;
case
FTDM_TRUNK_BRI_PTMP
:
res
=
lpwrap_init_bri
(
&
isdn_data
->
spri
,
span
,
isdn_data
->
dchan
,
isdn_data
->
dialect
,
isdn_data
->
mode
,
0
,
isdn_data
->
debug_mask
);
#ifndef HAVE_LIBPRI_BRI
goto
out
;
#endif
break
;
default:
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Invalid trunk type"
);
goto
out
;
}
/*
* Initialize BRI/PRI context
*/
res
=
lpwrap_init_pri
(
&
isdn_data
->
spri
,
span
,
isdn_data
->
dchan
,
isdn_data
->
dialect
,
isdn_data
->
mode
,
isdn_data
->
debug_mask
);
if
(
res
)
{
ftdm_log
(
FTDM_LOG_CRIT
,
"Failed to initialize BRI/PRI on span %d
\n
"
,
ftdm_span_get_id
(
span
));
goto
out
;
}
#ifdef HAVE_LIBPRI_AOC
/*
* Only enable facility on trunk if really required,
* this may help avoid problems on troublesome lines.
*/
if
(
isdn_data
->
opts
&
FTMOD_LIBPRI_OPT_FACILITY_AOC
)
{
pri_facility_enable
(
isdn_data
->
spri
.
pri
);
}
#endif
/* Support the different switch of service status */
if
(
isdn_data
->
service_message_support
)
{
pri_set_service_message_support
(
isdn_data
->
spri
.
pri
,
1
/* True */
);
}
if
(
res
==
0
)
{
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_ANY
,
on_anything
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_RING
,
on_ring
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_RINGING
,
on_ringing
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_PROCEEDING
,
on_proceeding
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_PROGRESS
,
on_progress
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_ANSWER
,
on_answer
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_DCHAN_UP
,
on_dchan_up
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_DCHAN_DOWN
,
on_dchan_down
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_HANGUP_REQ
,
on_hangup
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_HANGUP_ACK
,
on_hangup
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_HANGUP
,
on_hangup
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_INFO_RECEIVED
,
on_info
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_RESTART
,
on_restart
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_IO_FAIL
,
on_io_fail
);
#ifdef HAVE_LIBPRI_AOC
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_FACILITY
,
on_facility
);
/*
* Only enable facility on trunk if really required,
* this may help avoid problems on troublesome lines.
*/
if
(
isdn_data
->
opts
&
FTMOD_LIBPRI_OPT_FACILITY_AOC
)
{
pri_facility_enable
(
isdn_data
->
spri
.
pri
);
}
#endif
if
(
down
)
{
ftdm_log
(
FTDM_LOG_INFO
,
"PRI back up on span %d
\n
"
,
ftdm_span_get_id
(
span
));
ftdm_set_state_all
(
span
,
FTDM_CHANNEL_STATE_RESTART
);
down
=
0
;
}
isdn_data
->
spri
.
on_loop
=
check_flags
;
/* Support the different switch of service status */
if
(
isdn_data
->
service_message_support
)
{
pri_set_service_message_support
(
isdn_data
->
spri
.
pri
,
1
);
}
/* Callbacks for libpri events */
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_ANY
,
on_anything
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_RING
,
on_ring
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_RINGING
,
on_ringing
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_PROCEEDING
,
on_proceeding
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_PROGRESS
,
on_progress
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_ANSWER
,
on_answer
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_DCHAN_UP
,
on_dchan_up
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_DCHAN_DOWN
,
on_dchan_down
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_HANGUP_REQ
,
on_hangup
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_HANGUP_ACK
,
on_hangup
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_HANGUP
,
on_hangup
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_INFO_RECEIVED
,
on_information
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_KEYPAD_DIGIT
,
on_keypad_digit
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_RESTART
,
on_restart
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_RESTART_ACK
,
on_restart_ack
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_IO_FAIL
,
on_io_fail
);
LPWRAP_MAP_PRI_EVENT
(
isdn_data
->
spri
,
LPWRAP_PRI_EVENT_FACILITY
,
on_facility
);
/* Callback invoked on each iteration of the lpwrap_run_pri() event loop */
isdn_data
->
spri
.
on_loop
=
check_flags
;
lpwrap_run_pri
(
&
isdn_data
->
spri
);
}
else
{
ftdm_log
(
FTDM_LOG_CRIT
,
"PRI init failed!
\n
"
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"PRI init failed!"
);
break
;
/*
* Event loop
*/
while
(
ftdm_running
()
&&
!
ftdm_test_flag
(
span
,
FTDM_SPAN_STOP_THREAD
))
{
if
(
down
)
{
ftdm_log
(
FTDM_LOG_INFO
,
"PRI back up on span %d
\n
"
,
ftdm_span_get_id
(
span
));
ftdm_set_state_all
(
span
,
FTDM_CHANNEL_STATE_RESTART
);
down
=
0
;
}
lpwrap_run_pri
(
&
isdn_data
->
spri
);
if
(
!
ftdm_running
()
||
ftdm_test_flag
(
span
,
FTDM_SPAN_STOP_THREAD
))
{
break
;
}
...
...
@@ -2353,8 +2451,7 @@ out:
/* close d-channel, if set */
if
(
isdn_data
->
dchan
)
{
if
(
ftdm_channel_close
(
&
isdn_data
->
dchan
)
!=
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Failed to close D-Channel %d:%d
\n
"
,
ftdm_channel_get_span_id
(
isdn_data
->
dchan
),
ftdm_channel_get_id
(
isdn_data
->
dchan
));
ftdm_log_chan_msg
(
isdn_data
->
dchan
,
FTDM_LOG_ERROR
,
"Failed to close D-Channel
\n
"
);
}
}
...
...
@@ -2363,6 +2460,7 @@ out:
ftdm_clear_flag
(
span
,
FTDM_SPAN_IN_THREAD
);
ftdm_clear_flag
(
isdn_data
,
FTMOD_LIBPRI_RUNNING
);
lpwrap_destroy_pri
(
&
isdn_data
->
spri
);
return
NULL
;
}
...
...
@@ -2381,11 +2479,14 @@ static ftdm_status_t ftdm_libpri_stop(ftdm_span_t *span)
return
FTDM_FAIL
;
}
ftdm_set_state_all
(
span
,
FTDM_CHANNEL_STATE_RESTART
);
ftdm_log
(
FTDM_LOG_INFO
,
"Stopping span [s%d][%s]
\n
"
,
ftdm_span_get_id
(
span
),
ftdm_span_get_name
(
span
));
ftdm_set_state_all
(
span
,
FTDM_CHANNEL_STATE_RESTART
);
check_state
(
span
);
ftdm_set_flag
(
span
,
FTDM_SPAN_STOP_THREAD
);
lpwrap_stop_pri
(
&
isdn_data
->
spri
);
while
(
ftdm_test_flag
(
span
,
FTDM_SPAN_IN_THREAD
))
{
ftdm_sleep
(
100
);
...
...
@@ -2411,6 +2512,9 @@ static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span)
return
FTDM_FAIL
;
}
ftdm_log
(
FTDM_LOG_INFO
,
"Starting span [s%d][%s]
\n
"
,
ftdm_span_get_id
(
span
),
ftdm_span_get_name
(
span
));
ftdm_clear_flag
(
span
,
FTDM_SPAN_STOP_THREAD
);
ftdm_clear_flag
(
span
,
FTDM_SPAN_IN_THREAD
);
...
...
@@ -2552,7 +2656,6 @@ static uint32_t parse_opts(const char *in)
static
FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION
(
ftdm_libpri_configure_span
)
{
ftdm_libpri_data_t
*
isdn_data
=
NULL
;
//ftdm_channel_t *dchan = NULL;
uint32_t
bchan_count
=
0
;
uint32_t
dchan_count
=
0
;
uint32_t
i
;
...
...
@@ -2569,23 +2672,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
case
FTDM_CHAN_TYPE_DQ921
:
if
(
dchan_count
>
1
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Span has more than 2 D-Channels!
\n
"
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Span has more than 2 D-Channels!"
);
return
FTDM_FAIL
;
}
else
{
#if 0
if (ftdm_channel_open(ftdm_span_get_id(span), i, &dchan) == FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_DEBUG, "opening D-Channel %d:%d\n", ftdm_channel_get_span_id(dchan), ftdm_channel_get_id(dchan));
_ftdm_channel_set_state_force(dchan, FTDM_CHANNEL_STATE_UP);
} else {
ftdm_log(FTDM_LOG_ERROR, "Failed to open D-Channel %d:%d\n", ftdm_channel_get_span_id(chan), ftdm_channel_getid(chan));
snprintf(span->last_error, sizeof(span->last_error), "Failed to open D-Channel %d:%d\n", ftdm_channel_get_span_id(chan), ftdm_channel_getid(chan));
return FTDM_FAIL;
}
#endif
dchan_count
++
;
}
dchan_count
++
;
break
;
case
FTDM_CHAN_TYPE_B
:
bchan_count
++
;
break
;
...
...
@@ -2595,12 +2685,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
}
if
(
!
dchan_count
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Span has no D-Channel!
\n
"
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Span has no D-Channel!"
);
return
FTDM_FAIL
;
}
if
(
!
bchan_count
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Span has no B-Channels!
\n
"
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Span has no B-Channels!"
);
return
FTDM_FAIL
;
}
...
...
@@ -2609,7 +2697,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
memset
(
isdn_data
,
0
,
sizeof
(
*
isdn_data
));
/* set some default values */
isdn_data
->
ton
=
PRI_UNKNOWN
;
isdn_data
->
ton
=
PRI_UNKNOWN
;
isdn_data
->
overlap_timeout_ms
=
OVERLAP_TIMEOUT_MS_DEFAULT
;
/* Use span's trunk_mode as a reference for the default libpri mode */
if
(
ftdm_span_get_trunk_mode
(
span
)
==
FTDM_TRUNK_MODE_NET
)
{
...
...
@@ -2623,7 +2712,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
case
FTDM_TRUNK_BRI_PTMP
:
#ifndef HAVE_LIBPRI_BRI
ftdm_log
(
FTDM_LOG_ERROR
,
"Unsupported trunk type: '%s', libpri too old
\n
"
,
ftdm_span_get_trunk_type_str
(
span
));
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Unsupported trunk type [%s], libpri too old"
,
ftdm_span_get_trunk_type_str
(
span
));
goto
error
;
#endif
case
FTDM_TRUNK_E1
:
...
...
@@ -2639,7 +2727,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
break
;
default:
ftdm_log
(
FTDM_LOG_ERROR
,
"Invalid trunk type: '%s'
\n
"
,
ftdm_span_get_trunk_type_str
(
span
));
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Invalid trunk type [%s]"
,
ftdm_span_get_trunk_type_str
(
span
));
goto
error
;
}
...
...
@@ -2648,7 +2735,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
*/
if
(
msn_filter_init
(
isdn_data
)
!=
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Failed to init MSN filter
\n
"
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Failed to init MSN filter"
);
goto
error
;
}
...
...
@@ -2663,7 +2749,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
if
(
ftdm_strlen_zero
(
val
))
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Parameter '%s' has no value
\n
"
,
var
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Parameter [%s] has no value"
,
var
);
goto
error
;
}
...
...
@@ -2691,6 +2776,17 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
isdn_data
->
overlap
=
FTMOD_LIBPRI_OVERLAP_NONE
;
}
}
else
if
(
!
strcasecmp
(
var
,
"digit_timeout"
)
||
!
strcasecmp
(
var
,
"t302"
))
{
int
tmp
=
atoi
(
val
);
if
(
!
tmp
)
{
isdn_data
->
overlap_timeout_ms
=
0
;
/* disabled */
}
else
if
((
isdn_data
->
overlap_timeout_ms
=
ftdm_clamp
(
tmp
,
OVERLAP_TIMEOUT_MS_MIN
,
OVERLAP_TIMEOUT_MS_MAX
))
!=
tmp
)
{
ftdm_log
(
FTDM_LOG_WARNING
,
"'%s' value '%d' outside of range [%d:%d], using '%d' ms instead
\n
"
,
var
,
tmp
,
OVERLAP_TIMEOUT_MS_MIN
,
OVERLAP_TIMEOUT_MS_MAX
,
isdn_data
->
overlap_timeout_ms
);
}
}
else
if
(
!
strcasecmp
(
var
,
"debug"
))
{
if
(
parse_debug
(
val
,
&
isdn_data
->
debug_mask
)
==
-
1
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Invalid debug flag, ignoring parameter
\n
"
);
...
...
@@ -2705,13 +2801,11 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
else
if
(
!
strcasecmp
(
var
,
"local-number"
)
||
!
strcasecmp
(
var
,
"msn"
))
{
if
(
msn_filter_add
(
isdn_data
,
val
)
!=
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Invalid MSN/DDI(s) '%s' specified
\n
"
,
val
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Invalid MSN/DDI(s) '%s' specified!"
,
val
);
goto
error
;
}
}
else
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Unknown parameter '%s', aborting configuration
\n
"
,
var
);
snprintf
(
span
->
last_error
,
sizeof
(
span
->
last_error
),
"Unknown parameter [%s]"
,
var
);
goto
error
;
}
}
...
...
@@ -2748,8 +2842,28 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
ftdm_set_flag
(
span
,
FTDM_SPAN_SUGGEST_CHAN_ID
);
}
/* Allocate per-channel private data */
for
(
i
=
1
;
i
<=
ftdm_span_get_chan_count
(
span
);
i
++
)
{
ftdm_channel_t
*
chan
=
ftdm_span_get_channel
(
span
,
i
);
if
(
!
chan
)
continue
;
if
(
ftdm_channel_get_type
(
chan
)
==
FTDM_CHAN_TYPE_B
)
{
ftdm_libpri_b_chan_t
*
priv
=
NULL
;
priv
=
calloc
(
1
,
sizeof
(
*
priv
));
if
(
!
priv
)
{
ftdm_log_chan_msg
(
chan
,
FTDM_LOG_CRIT
,
"Failed to allocate per-channel private data
\n
"
);
goto
error
;
}
priv
->
channel
=
chan
;
chan
->
call_data
=
priv
;
}
}
return
FTDM_SUCCESS
;
error:
/* TODO: free per-channel private data */
msn_filter_destroy
(
isdn_data
);
ftdm_safe_free
(
isdn_data
);
return
FTDM_FAIL
;
...
...
libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h
浏览文件 @
12b5bde2
...
...
@@ -35,6 +35,10 @@
#include "freetdm.h"
#include "lpwrap_pri.h"
#define OVERLAP_TIMEOUT_MS_DEFAULT 5000
/* 5 sec */
#define OVERLAP_TIMEOUT_MS_MIN 3000
/* 3 sec */
#define OVERLAP_TIMEOUT_MS_MAX 30000
/* 30 sec */
typedef
enum
{
SERVICE_CHANGE_STATUS_INSERVICE
=
0
,
SERVICE_CHANGE_STATUS_MAINTENANCE
,
...
...
@@ -71,6 +75,7 @@ struct ftdm_libpri_data {
int
mode
;
int
dialect
;
int
overlap
;
/*!< Overlap dial flags */
int
overlap_timeout_ms
;
/*!< Overlap dial timeout */
unsigned
int
layer1
;
unsigned
int
ton
;
unsigned
int
service_message_support
;
...
...
@@ -84,6 +89,27 @@ struct ftdm_libpri_data {
typedef
struct
ftdm_libpri_data
ftdm_libpri_data_t
;
/*
* b-channel flags
*/
enum
{
FTDM_LIBPRI_B_NONE
=
0
,
FTDM_LIBPRI_B_REMOTE_RESTART
=
(
1
<<
0
),
/*!< Remote triggered channel restart */
};
/**
* Per-b-channel private data
*/
struct
ftdm_libpri_b_chan
{
struct
lpwrap_timer
t302
;
/*!< T302 overlap receive timer */
ftdm_channel_t
*
channel
;
/*!< back-pointer to b-channel */
q931_call
*
call
;
/*!< libpri opaque call handle */
uint32_t
flags
;
/*!< channel flags */
};
typedef
struct
ftdm_libpri_b_chan
ftdm_libpri_b_chan_t
;
#endif
/* For Emacs:
...
...
libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c
浏览文件 @
12b5bde2
...
...
@@ -36,51 +36,7 @@
#include "private/ftdm_core.h"
#include "lpwrap_pri.h"
#ifndef HAVE_GETTIMEOFDAY
#ifdef WIN32
#include <mmsystem.h>
static
__inline
int
gettimeofday
(
struct
timeval
*
tp
,
void
*
nothing
)
{
#ifdef WITHOUT_MM_LIB
SYSTEMTIME
st
;
time_t
tt
;
struct
tm
tmtm
;
/* mktime converts local to UTC */
GetLocalTime
(
&
st
);
tmtm
.
tm_sec
=
st
.
wSecond
;
tmtm
.
tm_min
=
st
.
wMinute
;
tmtm
.
tm_hour
=
st
.
wHour
;
tmtm
.
tm_mday
=
st
.
wDay
;
tmtm
.
tm_mon
=
st
.
wMonth
-
1
;
tmtm
.
tm_year
=
st
.
wYear
-
1900
;
tmtm
.
tm_isdst
=
-
1
;
tt
=
mktime
(
&
tmtm
);
tp
->
tv_sec
=
tt
;
tp
->
tv_usec
=
st
.
wMilliseconds
*
1000
;
#else
/**
** The earlier time calculations using GetLocalTime
** had a time resolution of 10ms.The timeGetTime, part
** of multimedia apis offer a better time resolution
** of 1ms.Need to link against winmm.lib for this
**/
unsigned
long
Ticks
=
0
;
unsigned
long
Sec
=
0
;
unsigned
long
Usec
=
0
;
Ticks
=
timeGetTime
();
Sec
=
Ticks
/
1000
;
Usec
=
(
Ticks
-
(
Sec
*
1000
))
*
1000
;
tp
->
tv_sec
=
Sec
;
tp
->
tv_usec
=
Usec
;
#endif
/* WITHOUT_MM_LIB */
(
void
)
nothing
;
return
0
;
}
#endif
/* WIN32 */
#endif
/* HAVE_GETTIMEOFDAY */
static
struct
lpwrap_pri_event_list
LPWRAP_PRI_EVENT_LIST
[]
=
{
static
struct
lpwrap_pri_event_list
LPWRAP_PRI_EVENT_LIST
[
LPWRAP_PRI_EVENT_MAX
]
=
{
{
0
,
LPWRAP_PRI_EVENT_ANY
,
"ANY"
},
{
1
,
LPWRAP_PRI_EVENT_DCHAN_UP
,
"DCHAN_UP"
},
{
2
,
LPWRAP_PRI_EVENT_DCHAN_DOWN
,
"DCHAN_DOWN"
},
...
...
@@ -103,8 +59,6 @@ static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = {
{
19
,
LPWRAP_PRI_EVENT_IO_FAIL
,
"IO_FAIL"
},
};
#define LINE "--------------------------------------------------------------------------------"
const
char
*
lpwrap_pri_event_str
(
lpwrap_pri_event_t
event_id
)
{
if
(
event_id
<
0
||
event_id
>=
LPWRAP_PRI_EVENT_MAX
)
...
...
@@ -170,6 +124,10 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
return
(
int
)
buflen
;
}
/*
* Unified init function for BRI + PRI libpri spans
*/
int
lpwrap_init_pri
(
struct
lpwrap_pri
*
spri
,
ftdm_span_t
*
span
,
ftdm_channel_t
*
dchan
,
int
swtype
,
int
node
,
int
debug
)
{
int
ret
=
-
1
;
...
...
@@ -179,115 +137,255 @@ int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *
spri
->
span
=
span
;
if
(
!
spri
->
dchan
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"No D-Channel available, unable to create PRI
\n
"
);
ftdm_log
(
FTDM_LOG_ERROR
,
"No D-Channel available, unable to create BRI/PRI
\n
"
);
return
ret
;
}
if
(
ftdm_mutex_create
(
&
spri
->
timer_mutex
)
!=
FTDM_SUCCESS
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Failed to create timer list mutex
\n
"
);
return
ret
;
}
if
((
spri
->
pri
=
pri_new_cb
(
spri
->
dchan
->
sockfd
,
node
,
swtype
,
__pri_lpwrap_read
,
__pri_lpwrap_write
,
spri
)))
{
unsigned
char
buf
[
4
]
=
{
0
};
size_t
buflen
=
sizeof
(
buf
),
len
=
0
;
switch
(
ftdm_span_get_trunk_type
(
span
))
{
case
FTDM_TRUNK_E1
:
case
FTDM_TRUNK_J1
:
case
FTDM_TRUNK_T1
:
spri
->
pri
=
pri_new_cb
(
spri
->
dchan
->
sockfd
,
node
,
swtype
,
__pri_lpwrap_read
,
__pri_lpwrap_write
,
spri
);
break
;
#ifdef HAVE_LIBPRI_BRI
case
FTDM_TRUNK_BRI
:
spri
->
pri
=
pri_new_bri_cb
(
spri
->
dchan
->
sockfd
,
1
,
node
,
swtype
,
__pri_lpwrap_read
,
__pri_lpwrap_write
,
spri
);
break
;
case
FTDM_TRUNK_BRI_PTMP
:
spri
->
pri
=
pri_new_bri_cb
(
spri
->
dchan
->
sockfd
,
0
,
node
,
swtype
,
__pri_lpwrap_read
,
__pri_lpwrap_write
,
spri
);
break
;
#endif
default:
ftdm_log
(
FTDM_LOG_CRIT
,
"Invalid/unsupported trunk type '%s'
\n
"
,
ftdm_span_get_trunk_type_str
(
span
));
ftdm_mutex_destroy
(
&
spri
->
timer_mutex
);
return
ret
;
}
if
(
spri
->
pri
)
{
pri_set_debug
(
spri
->
pri
,
debug
);
#ifdef HAVE_LIBPRI_AOC
pri_aoc_events_enable
(
spri
->
pri
,
1
);
#endif
ftdm_channel_write
(
spri
->
dchan
,
buf
,
buflen
,
&
len
);
ret
=
0
;
}
else
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Unable to create PRI
\n
"
);
ftdm_log
(
FTDM_LOG_CRIT
,
"Unable to create BRI/PRI
\n
"
);
ftdm_mutex_destroy
(
&
spri
->
timer_mutex
);
}
return
ret
;
}
int
lpwrap_init_bri
(
struct
lpwrap_pri
*
spri
,
ftdm_span_t
*
span
,
ftdm_channel_t
*
dchan
,
int
swtype
,
int
node
,
int
ptp
,
int
debug
)
#define timeval_to_ms(x) \
(((ftdm_time_t)(x)->tv_sec * 1000) + (ftdm_time_t)((x)->tv_usec / 1000))
int
lpwrap_start_timer
(
struct
lpwrap_pri
*
spri
,
struct
lpwrap_timer
*
timer
,
const
uint32_t
timeout_ms
,
timeout_handler
callback
)
{
int
ret
=
-
1
;
struct
lpwrap_timer
**
prev
,
*
cur
;
#ifdef HAVE_LIBPRI_BRI
memset
(
spri
,
0
,
sizeof
(
struct
lpwrap_pri
));
spri
->
dchan
=
dchan
;
spri
->
span
=
span
;
if
(
!
spri
||
!
timer
||
timer
->
timeout
)
return
-
1
;
if
(
!
spri
->
dchan
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"No D-Channel available, unable to create BRI
\n
"
);
return
ret
;
ftdm_log_chan
(
spri
->
dchan
,
FTDM_LOG_DEBUG
,
"-- Starting timer %p with timeout %u ms
\n
"
,
timer
,
timeout_ms
);
timer
->
timeout
=
ftdm_current_time_in_ms
()
+
timeout_ms
;
timer
->
callback
=
callback
;
timer
->
next
=
NULL
;
ftdm_mutex_lock
(
spri
->
timer_mutex
);
for
(
prev
=
&
spri
->
timer_list
,
cur
=
spri
->
timer_list
;
cur
;
prev
=
&
(
*
prev
)
->
next
,
cur
=
cur
->
next
)
{
if
(
cur
->
timeout
<
timer
->
timeout
)
{
*
prev
=
timer
;
timer
->
next
=
cur
;
break
;
}
}
if
(
!
cur
)
{
*
prev
=
timer
;
}
if
((
spri
->
pri
=
pri_new_bri_cb
(
spri
->
dchan
->
sockfd
,
ptp
,
node
,
swtype
,
__pri_lpwrap_read
,
__pri_lpwrap_write
,
spri
)))
{
unsigned
char
buf
[
4
]
=
{
0
}
;
size_t
buflen
=
sizeof
(
buf
),
len
=
0
;
ftdm_mutex_unlock
(
spri
->
timer_mutex
);
return
0
;
}
pri_set_debug
(
spri
->
pri
,
debug
);
#ifdef HAVE_LIBPRI_AOC
pri_aoc_events_enable
(
spri
->
pri
,
1
);
#endif
ftdm_channel_write
(
spri
->
dchan
,
buf
,
buflen
,
&
len
);
int
lpwrap_stop_timer
(
struct
lpwrap_pri
*
spri
,
struct
lpwrap_timer
*
timer
)
{
struct
lpwrap_timer
**
prev
,
*
cur
;
ret
=
0
;
}
else
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Unable to create BRI
\n
"
);
if
(
!
spri
||
!
timer
)
return
-
1
;
if
(
!
timer
->
timeout
)
return
0
;
ftdm_log_chan
(
spri
->
dchan
,
FTDM_LOG_DEBUG
,
"-- Stopping timer %p
\n
"
,
timer
);
ftdm_mutex_lock
(
spri
->
timer_mutex
);
for
(
prev
=
&
spri
->
timer_list
,
cur
=
spri
->
timer_list
;
cur
;
prev
=
&
(
*
prev
)
->
next
,
cur
=
cur
->
next
)
{
if
(
cur
==
timer
)
{
*
prev
=
cur
->
next
;
break
;
}
}
#else
ftdm_log
(
FTDM_LOG_ERROR
,
"Installed libpri version (%s) has no BRI support
\n
"
,
pri_get_version
());
#endif
return
ret
;
ftdm_mutex_unlock
(
spri
->
timer_mutex
);
timer
->
next
=
NULL
;
timer
->
timeout
=
0
;
timer
->
callback
=
NULL
;
return
0
;
}
static
struct
lpwrap_timer
*
lpwrap_timer_next
(
struct
lpwrap_pri
*
spri
)
{
return
spri
?
spri
->
timer_list
:
NULL
;
}
int
lpwrap_one_loop
(
struct
lpwrap_pri
*
spri
)
static
int
lpwrap_run_expired
(
struct
lpwrap_pri
*
spri
,
ftdm_time_t
now_ms
)
{
fd_set
rfds
,
efds
;
struct
timeval
now
=
{
0
,
0
},
*
next
=
NULL
;
pri_event
*
event
=
NULL
;
event_handler
handler
;
int
sel
;
struct
lpwrap_timer
*
expired_list
=
NULL
;
struct
lpwrap_timer
**
prev
,
*
cur
;
if
(
spri
->
on_loop
)
{
if
((
sel
=
spri
->
on_loop
(
spri
))
<
0
)
{
return
sel
;
if
(
!
spri
||
!
spri
->
timer_list
)
return
0
;
ftdm_mutex_lock
(
spri
->
timer_mutex
);
/* Move all timers to expired list */
expired_list
=
spri
->
timer_list
;
for
(
prev
=
&
expired_list
,
cur
=
expired_list
;
cur
;
prev
=
&
(
*
prev
)
->
next
,
cur
=
cur
->
next
)
{
if
(
cur
->
timeout
>
now_ms
)
{
*
prev
=
NULL
;
break
;
}
}
/* Move non-expired timer to front of timer_list (or clear list if there are none) */
spri
->
timer_list
=
cur
;
ftdm_mutex_unlock
(
spri
->
timer_mutex
);
/* fire callbacks */
while
((
cur
=
expired_list
))
{
expired_list
=
cur
->
next
;
if
(
cur
->
callback
)
cur
->
callback
(
spri
,
cur
);
/* stop timer */
cur
->
next
=
NULL
;
cur
->
timeout
=
0
;
cur
->
callback
=
NULL
;
}
if
(
spri
->
errs
>=
2
)
{
spri
->
errs
=
0
;
return
-
1
;
return
0
;
}
#define LPWRAP_MAX_TIMEOUT_MS 100
#define LPWRAP_MAX_ERRORS 2
int
lpwrap_run_pri_once
(
struct
lpwrap_pri
*
spri
)
{
struct
timeval
*
next
=
NULL
;
struct
lpwrap_timer
*
timer
=
NULL
;
pri_event
*
event
=
NULL
;
ftdm_wait_flag_t
flags
;
ftdm_time_t
now_ms
,
next_ms
,
timeout_ms
,
tmp_ms
;
int
ret
;
if
(
spri
->
on_loop
)
{
if
((
ret
=
spri
->
on_loop
(
spri
))
<
0
)
return
FTDM_FAIL
;
}
FD_ZERO
(
&
rfds
);
FD_ZERO
(
&
efds
);
/* Default timeout when no scheduled events are pending */
timeout_ms
=
LPWRAP_MAX_TIMEOUT_MS
;
next_ms
=
0
;
now_ms
=
ftdm_current_time_in_ms
();
/*
* Get the next scheduled timer from libpri to set the maximum timeout,
* but limit it to MAX_TIMEOUT_MS (100ms).
*/
if
((
next
=
pri_schedule_next
(
spri
->
pri
)))
{
next_ms
=
timeval_to_ms
(
next
);
if
(
now_ms
>=
next_ms
)
{
/* Already late, handle timeout */
timeout_ms
=
0
;
}
else
{
/* Calculate new timeout and limit it to MAX_TIMEOUT_MS miliseconds */
tmp_ms
=
ftdm_min
(
next_ms
-
now_ms
,
LPWRAP_MAX_TIMEOUT_MS
);
timeout_ms
=
ftdm_min
(
timeout_ms
,
tmp_ms
);
}
}
#ifdef _MSC_VER
//Windows macro for FD_SET includes a warning C4127: conditional expression is constant
#pragma warning(push)
#pragma warning(disable:4127)
#endif
/*
* Next lpwrap_timer timeout
*/
if
((
timer
=
lpwrap_timer_next
(
spri
)))
{
if
(
now_ms
>=
timer
->
timeout
)
{
/* Already late, handle timeout */
timeout_ms
=
0
;
}
else
{
/* Calculate new timeout and limit it to MAX_TIMEOUT_MS miliseconds */
tmp_ms
=
ftdm_min
(
timer
->
timeout
-
now_ms
,
LPWRAP_MAX_TIMEOUT_MS
);
timeout_ms
=
ftdm_min
(
timeout_ms
,
tmp_ms
);
}
}
FD_SET
(
pri_fd
(
spri
->
pri
),
&
rfds
);
FD_SET
(
pri_fd
(
spri
->
pri
),
&
efds
);
/* */
if
(
timeout_ms
>
0
)
{
flags
=
FTDM_READ
|
FTDM_EVENTS
;
ret
=
ftdm_channel_wait
(
spri
->
dchan
,
&
flags
,
timeout_ms
);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
if
(
spri
->
flags
&
LPWRAP_PRI_ABORT
)
return
FTDM_SUCCESS
;
now
.
tv_sec
=
0
;
now
.
tv_usec
=
100000
;
if
(
ret
==
FTDM_TIMEOUT
)
{
now_ms
=
ftdm_current_time_in_ms
()
;
sel
=
select
(
pri_fd
(
spri
->
pri
)
+
1
,
&
rfds
,
NULL
,
&
efds
,
&
now
);
if
(
!
sel
)
{
if
((
next
=
pri_schedule_next
(
spri
->
pri
)))
{
gettimeofday
(
&
now
,
NULL
);
if
(
now
.
tv_sec
>=
next
->
tv_sec
&&
(
now
.
tv_usec
>=
next
->
tv_usec
||
next
->
tv_usec
<=
100000
))
{
//ftdm_log(FTDM_LOG_DEBUG, "Check event\n");
if
(
next
)
{
if
(
next_ms
<
now_ms
)
{
ftdm_log_chan
(
spri
->
dchan
,
FTDM_LOG_DEBUG
,
"pri timer %d ms late
\n
"
,
(
int
)(
now_ms
-
next_ms
));
}
event
=
pri_schedule_run
(
spri
->
pri
);
}
if
(
timer
)
{
if
(
timer
->
timeout
<
now_ms
)
{
ftdm_log_chan
(
spri
->
dchan
,
FTDM_LOG_DEBUG
,
"lpwrap timer %d ms late
\n
"
,
(
int
)(
now_ms
-
timer
->
timeout
));
}
lpwrap_run_expired
(
spri
,
now_ms
);
}
}
else
if
(
flags
&
(
FTDM_READ
|
FTDM_EVENTS
))
{
event
=
pri_check_event
(
spri
->
pri
);
}
}
else
{
/*
* Scheduled event has already expired, handle it immediately
*/
if
(
next
)
{
event
=
pri_schedule_run
(
spri
->
pri
);
}
if
(
timer
)
{
lpwrap_run_expired
(
spri
,
now_ms
);
}
}
else
if
(
sel
>
0
)
{
event
=
pri_check_event
(
spri
->
pri
);
}
if
(
spri
->
flags
&
LPWRAP_PRI_ABORT
)
return
FTDM_SUCCESS
;
if
(
event
)
{
event_handler
handler
;
/* 0 is catchall event handler */
if
(
event
->
e
<
0
||
event
->
e
>=
LPWRAP_PRI_EVENT_MAX
)
{
handler
=
spri
->
eventmap
[
0
];
...
...
@@ -303,28 +401,47 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
ftdm_log
(
FTDM_LOG_CRIT
,
"No event handler found for event %d.
\n
"
,
event
->
e
);
}
}
return
sel
;
return
FTDM_SUCCESS
;
}
int
lpwrap_run_pri
(
struct
lpwrap_pri
*
spri
)
{
int
ret
=
0
;
for
(;;)
{
if
((
ret
=
lpwrap_one_loop
(
spri
))
<
0
)
{
#ifndef WIN32 //This needs to be adressed fror WIN32 still
if
(
errno
==
EINTR
){
/* Igonore an interrupted system call */
continue
;
}
#endif
ftdm_log
(
FTDM_LOG_CRIT
,
"Error = %i [%s]
\n
"
,
ret
,
strerror
(
errno
));
while
(
!
(
spri
->
flags
&
LPWRAP_PRI_ABORT
))
{
ret
=
lpwrap_run_pri_once
(
spri
);
if
(
ret
)
{
ftdm_log
(
FTDM_LOG_ERROR
,
"Error = %d, [%s]
\n
"
,
ret
,
strerror
(
errno
));
spri
->
errs
++
;
}
else
{
spri
->
errs
=
0
;
}
if
(
!
ftdm_running
())
break
;
if
(
spri
->
errs
>=
LPWRAP_MAX_ERRORS
)
{
ftdm_log
(
FTDM_LOG_CRIT
,
"Too many errors on span, restarting
\n
"
);
spri
->
errs
=
0
;
break
;
}
}
return
ret
;
}
int
lpwrap_stop_pri
(
struct
lpwrap_pri
*
spri
)
{
spri
->
flags
|=
LPWRAP_PRI_ABORT
;
return
FTDM_SUCCESS
;
}
int
lpwrap_destroy_pri
(
struct
lpwrap_pri
*
spri
)
{
if
(
spri
->
timer_mutex
)
ftdm_mutex_destroy
(
&
spri
->
timer_mutex
);
return
FTDM_SUCCESS
;
}
/* For Emacs:
* Local Variables:
* mode:c
...
...
libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h
浏览文件 @
12b5bde2
...
...
@@ -92,10 +92,14 @@ typedef enum {
}
lpwrap_pri_switch_t
;
typedef
enum
{
LPWRAP_PRI_READY
=
(
1
<<
0
)
LPWRAP_PRI_READY
=
(
1
<<
0
),
LPWRAP_PRI_ABORT
=
(
1
<<
1
)
}
lpwrap_pri_flag_t
;
struct
lpwrap_pri
;
struct
lpwrap_timer
;
typedef
int
(
*
timeout_handler
)(
struct
lpwrap_pri
*
,
struct
lpwrap_timer
*
);
typedef
int
(
*
event_handler
)(
struct
lpwrap_pri
*
,
lpwrap_pri_event_t
,
pri_event
*
);
typedef
int
(
*
loop_handler
)(
struct
lpwrap_pri
*
);
...
...
@@ -108,6 +112,8 @@ struct lpwrap_pri {
event_handler
eventmap
[
LPWRAP_PRI_EVENT_MAX
];
loop_handler
on_loop
;
int
errs
;
struct
lpwrap_timer
*
timer_list
;
ftdm_mutex_t
*
timer_mutex
;
};
typedef
struct
lpwrap_pri
lpwrap_pri_t
;
...
...
@@ -118,15 +124,21 @@ struct lpwrap_pri_event_list {
const
char
*
name
;
};
struct
lpwrap_timer
{
struct
lpwrap_timer
*
next
;
ftdm_time_t
timeout
;
timeout_handler
callback
;
};
int
lpwrap_start_timer
(
struct
lpwrap_pri
*
spri
,
struct
lpwrap_timer
*
timer
,
const
uint32_t
timeout_ms
,
timeout_handler
callback
);
int
lpwrap_stop_timer
(
struct
lpwrap_pri
*
spri
,
struct
lpwrap_timer
*
timer
);
#define LPWRAP_MAP_PRI_EVENT(spri, event, func) spri.eventmap[event] = func;
const
char
*
lpwrap_pri_event_str
(
lpwrap_pri_event_t
event_id
);
int
lpwrap_one_loop
(
struct
lpwrap_pri
*
spri
);
int
lpwrap_init_pri
(
struct
lpwrap_pri
*
spri
,
ftdm_span_t
*
span
,
ftdm_channel_t
*
dchan
,
int
swtype
,
int
node
,
int
debug
);
int
lpwrap_init_bri
(
struct
lpwrap_pri
*
spri
,
ftdm_span_t
*
span
,
ftdm_channel_t
*
dchan
,
int
swtype
,
int
node
,
int
ptp
,
int
debug
);
int
lpwrap_destroy_pri
(
struct
lpwrap_pri
*
spri
);
int
lpwrap_run_pri_once
(
struct
lpwrap_pri
*
spri
);
int
lpwrap_run_pri
(
struct
lpwrap_pri
*
spri
);
#define lpwrap_run_bri(x) lpwrap_run_pri(x)
int
lpwrap_stop_pri
(
struct
lpwrap_pri
*
spri
);
#endif
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论