提交 200b25e2 authored 作者: Moises Silva's avatar Moises Silva

added new boost msg EVENT_CALL_RELEASED to fix race condition on call hangup

git-svn-id: http://svn.openzap.org/svn/openzap/branches/sangoma_boost@960 a93c3328-9c30-0410-af19-c9cd2b2d52af
上级 e9e0edb3
...@@ -451,8 +451,8 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request) ...@@ -451,8 +451,8 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
nack_map[r] = 1; nack_map[r] = 1;
if (sangoma_boost_data->sigmod) { if (sangoma_boost_data->sigmod) {
sangomabc_exec_command(&sangoma_boost_data->mcon, sangomabc_exec_command(&sangoma_boost_data->mcon,
(*zchan)->physical_span_id, BOOST_SPAN((*zchan)),
(*zchan)->physical_chan_id, BOOST_CHAN((*zchan)),
r, r,
SIGBOOST_EVENT_CALL_START_NACK, SIGBOOST_EVENT_CALL_START_NACK,
0); 0);
...@@ -616,10 +616,22 @@ static void handle_call_done(zap_span_t *span, sangomabc_connection_t *mcon, san ...@@ -616,10 +616,22 @@ static void handle_call_done(zap_span_t *span, sangomabc_connection_t *mcon, san
{ {
zap_channel_t *zchan; zap_channel_t *zchan;
int r = 0; int r = 0;
if ((zchan = find_zchan(span, event, 1))) { if ((zchan = find_zchan(span, event, 1))) {
zap_sangoma_boost_data_t *sangoma_boost_data = zchan->span->signal_data;
zap_mutex_lock(zchan->mutex); zap_mutex_lock(zchan->mutex);
if (sangoma_boost_data->sigmod) {
/* not really completely done, but if we ever get an incoming call before moving to HANGUP_COMPLETE
* handle_incoming_call() will take care of moving the state machine to release the channel */
sangomabc_exec_command(&sangoma_boost_data->mcon,
BOOST_SPAN(zchan),
BOOST_CHAN(zchan),
0,
SIGBOOST_EVENT_CALL_RELEASED,
0);
}
if (zchan->state == ZAP_CHANNEL_STATE_DOWN || zchan->state == ZAP_CHANNEL_STATE_HANGUP_COMPLETE) { if (zchan->state == ZAP_CHANNEL_STATE_DOWN || zchan->state == ZAP_CHANNEL_STATE_HANGUP_COMPLETE) {
goto done; goto done;
} }
...@@ -729,6 +741,18 @@ static void handle_call_start_nack(zap_span_t *span, sangomabc_connection_t *mco ...@@ -729,6 +741,18 @@ static void handle_call_start_nack(zap_span_t *span, sangomabc_connection_t *mco
#endif #endif
} }
static void handle_call_released(zap_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
{
zap_channel_t *zchan;
if ((zchan = find_zchan(span, event, 1))) {
zap_log(ZAP_LOG_DEBUG, "Releasing completely chan s%dc%d\n", event->span, event->chan);
zap_channel_done(zchan);
} else {
zap_log(ZAP_LOG_ERROR, "Odd, We could not find chan: s%dc%d to release the call completely!!\n", event->span, event->chan);
}
}
/** /**
* \brief Handler for call stop event * \brief Handler for call stop event
* \param span Span where event was fired * \param span Span where event was fired
...@@ -773,10 +797,10 @@ static void handle_call_stop(zap_span_t *span, sangomabc_connection_t *mcon, san ...@@ -773,10 +797,10 @@ static void handle_call_stop(zap_span_t *span, sangomabc_connection_t *mcon, san
if (r) { if (r) {
return; return;
} }
} /* else we have to do it ourselves.... */ } else { /* we have to do it ourselves.... */
zap_log(ZAP_LOG_ERROR, "Odd, We could not find chan: s%dc%d\n", event->span, event->chan);
zap_log(ZAP_LOG_WARNING, "We could not find chan: s%dc%d\n", event->span, event->chan); release_request_id_span_chan(event->span, event->chan);
release_request_id_span_chan(event->span, event->chan); }
} }
/** /**
...@@ -829,6 +853,9 @@ static void handle_call_start(zap_span_t *span, sangomabc_connection_t *mcon, sa ...@@ -829,6 +853,9 @@ static void handle_call_start(zap_span_t *span, sangomabc_connection_t *mcon, sa
zap_log(ZAP_LOG_CRIT, "START CANT FIND CHAN %d:%d AT ALL\n", event->span+1,event->chan+1); zap_log(ZAP_LOG_CRIT, "START CANT FIND CHAN %d:%d AT ALL\n", event->span+1,event->chan+1);
goto error; goto error;
} }
/* this handles race conditions where state handlers are still pending to be executed for finished calls
but an incoming call arrives first, we must complete the channel states and then try again to get the
zap channel */
advance_chan_states(zchan); advance_chan_states(zchan);
if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 0))) { if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 0))) {
zap_log(ZAP_LOG_CRIT, "START CANT FIND CHAN %d:%d EVEN AFTER STATE ADVANCE\n", event->span+1,event->chan+1); zap_log(ZAP_LOG_CRIT, "START CANT FIND CHAN %d:%d EVEN AFTER STATE ADVANCE\n", event->span+1,event->chan+1);
...@@ -996,6 +1023,9 @@ static int parse_sangoma_event(zap_span_t *span, sangomabc_connection_t *mcon, s ...@@ -996,6 +1023,9 @@ static int parse_sangoma_event(zap_span_t *span, sangomabc_connection_t *mcon, s
case SIGBOOST_EVENT_CALL_STOPPED: case SIGBOOST_EVENT_CALL_STOPPED:
handle_call_stop(span, mcon, event); handle_call_stop(span, mcon, event);
break; break;
case SIGBOOST_EVENT_CALL_RELEASED:
handle_call_released(span, mcon, event);
break;
case SIGBOOST_EVENT_CALL_START_ACK: case SIGBOOST_EVENT_CALL_START_ACK:
handle_call_start_ack(mcon, event); handle_call_start_ack(mcon, event);
break; break;
...@@ -1070,6 +1100,8 @@ static __inline__ void state_advance(zap_channel_t *zchan) ...@@ -1070,6 +1100,8 @@ static __inline__ void state_advance(zap_channel_t *zchan)
switch (zchan->state) { switch (zchan->state) {
case ZAP_CHANNEL_STATE_DOWN: case ZAP_CHANNEL_STATE_DOWN:
{ {
int call_stopped_ack_sent = 0;
zap_sangoma_boost_data_t *sangoma_boost_data = zchan->span->signal_data;
if (zchan->extra_id) { if (zchan->extra_id) {
zchan->extra_id = 0; zchan->extra_id = 0;
} }
...@@ -1083,24 +1115,32 @@ static __inline__ void state_advance(zap_channel_t *zchan) ...@@ -1083,24 +1115,32 @@ static __inline__ void state_advance(zap_channel_t *zchan)
if (zchan->call_data && ((uint32_t)(intptr_t)zchan->call_data == SIGBOOST_EVENT_CALL_START_NACK)) { if (zchan->call_data && ((uint32_t)(intptr_t)zchan->call_data == SIGBOOST_EVENT_CALL_START_NACK)) {
sangomabc_exec_command(mcon, sangomabc_exec_command(mcon,
zchan->physical_span_id-1, BOOST_SPAN(zchan),
zchan->physical_chan_id-1, BOOST_CHAN(zchan),
0, 0,
SIGBOOST_EVENT_CALL_START_NACK_ACK, SIGBOOST_EVENT_CALL_START_NACK_ACK,
0); 0);
} else { } else {
/* we got a call stop msg, time to reply with call stopped ack */
sangomabc_exec_command(mcon, sangomabc_exec_command(mcon,
zchan->physical_span_id-1, BOOST_SPAN(zchan),
zchan->physical_chan_id-1, BOOST_CHAN(zchan),
0, 0,
SIGBOOST_EVENT_CALL_STOPPED_ACK, SIGBOOST_EVENT_CALL_STOPPED_ACK,
0); 0);
call_stopped_ack_sent = 1;
} }
} }
zchan->sflags = 0; zchan->sflags = 0;
zchan->call_data = NULL; zchan->call_data = NULL;
zap_channel_done(zchan); if (sangoma_boost_data->sigmod && call_stopped_ack_sent) {
/* we dont want to call zap_channel_done just yet until call released is received */
zap_log(ZAP_LOG_DEBUG, "Waiting for call release confirmation before declaring chan %d:%d as available \n",
zchan->span_id, zchan->chan_id);
} else {
zap_channel_done(zchan);
}
} }
break; break;
case ZAP_CHANNEL_STATE_PROGRESS_MEDIA: case ZAP_CHANNEL_STATE_PROGRESS_MEDIA:
......
...@@ -60,6 +60,7 @@ static struct sangomabc_map sangomabc_table[] = { ...@@ -60,6 +60,7 @@ static struct sangomabc_map sangomabc_table[] = {
{SIGBOOST_EVENT_CALL_ANSWERED, "CALL_ANSWERED"}, {SIGBOOST_EVENT_CALL_ANSWERED, "CALL_ANSWERED"},
{SIGBOOST_EVENT_CALL_STOPPED, "CALL_STOPPED"}, {SIGBOOST_EVENT_CALL_STOPPED, "CALL_STOPPED"},
{SIGBOOST_EVENT_CALL_STOPPED_ACK, "CALL_STOPPED_ACK"}, {SIGBOOST_EVENT_CALL_STOPPED_ACK, "CALL_STOPPED_ACK"},
{SIGBOOST_EVENT_CALL_RELEASED, "CALL_RELEASED"},
{SIGBOOST_EVENT_SYSTEM_RESTART, "SYSTEM_RESTART"}, {SIGBOOST_EVENT_SYSTEM_RESTART, "SYSTEM_RESTART"},
{SIGBOOST_EVENT_SYSTEM_RESTART_ACK, "SYSTEM_RESTART_ACK"}, {SIGBOOST_EVENT_SYSTEM_RESTART_ACK, "SYSTEM_RESTART_ACK"},
{SIGBOOST_EVENT_HEARTBEAT, "HEARTBEAT"}, {SIGBOOST_EVENT_HEARTBEAT, "HEARTBEAT"},
...@@ -457,7 +458,13 @@ int __sangomabc_connection_write(sangomabc_connection_t *mcon, sangomabc_event_t ...@@ -457,7 +458,13 @@ int __sangomabc_connection_write(sangomabc_connection_t *mcon, sangomabc_event_t
event->fseqno = mcon->txseq++; event->fseqno = mcon->txseq++;
} }
event->bseqno = mcon->rxseq; event->bseqno = mcon->rxseq;
event->version = SIGBOOST_VERSION; event->version = SIGBOOST_VERSION;
if (boost_full_event(event->event_id)) {
sangomabc_print_event_call(mcon, event, 0, 1, file, func, line);
} else {
sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)event, 0, 1, file, func, line);
}
if (mcon->sigmod) { if (mcon->sigmod) {
mcon->sigmod->write_msg(mcon->span, event, event_size); mcon->sigmod->write_msg(mcon->span, event, event_size);
...@@ -473,12 +480,6 @@ int __sangomabc_connection_write(sangomabc_connection_t *mcon, sangomabc_event_t ...@@ -473,12 +480,6 @@ int __sangomabc_connection_write(sangomabc_connection_t *mcon, sangomabc_event_t
zap_assert_return(err == event_size, -1, "Failed to send the boost message completely!"); zap_assert_return(err == event_size, -1, "Failed to send the boost message completely!");
if (boost_full_event(event->event_id)) {
sangomabc_print_event_call(mcon, event, 0, 1, file, func, line);
} else {
sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)event, 0, 1, file, func, line);
}
return err; return err;
} }
......
...@@ -28,6 +28,19 @@ enum e_sigboost_event_id_values ...@@ -28,6 +28,19 @@ enum e_sigboost_event_id_values
SIGBOOST_EVENT_CALL_ANSWERED = 0x84, /*132*/ SIGBOOST_EVENT_CALL_ANSWERED = 0x84, /*132*/
SIGBOOST_EVENT_CALL_STOPPED = 0x85, /*133*/ SIGBOOST_EVENT_CALL_STOPPED = 0x85, /*133*/
SIGBOOST_EVENT_CALL_STOPPED_ACK = 0x86, /*134*/ SIGBOOST_EVENT_CALL_STOPPED_ACK = 0x86, /*134*/
/* CALL_RELEASED is aimed to fix a race condition that became obvious
* when the boost socket was replaced by direct function calls
* and the channel hunting was moved to openzap, the problem is
* we can get CALL_STOPPED msg and reply with CALL_STOPPED_ACK
* but the signaling module will still (in PRI) send RELEASE and
* wait for RELEASE_COMPLETE from the isdn network before
* marking the channel as available, therefore openzap should
* also not mark the channel as available until CALL_RELEASED
* is received, for socket mode we can continue working as usual
* with CALL_STOPPED being the last step because the hunting is
* done in the signaling module.
* */
SIGBOOST_EVENT_CALL_RELEASED = 0x51, /* 81 */
SIGBOOST_EVENT_SYSTEM_RESTART = 0x87, /*135*/ SIGBOOST_EVENT_SYSTEM_RESTART = 0x87, /*135*/
SIGBOOST_EVENT_SYSTEM_RESTART_ACK = 0x88, /*136*/ SIGBOOST_EVENT_SYSTEM_RESTART_ACK = 0x88, /*136*/
SIGBOOST_EVENT_CALL_PROGRESS = 0x50, /*decimal 80*/ SIGBOOST_EVENT_CALL_PROGRESS = 0x50, /*decimal 80*/
......
...@@ -1507,22 +1507,24 @@ OZ_DECLARE(zap_status_t) zap_channel_done(zap_channel_t *zchan) ...@@ -1507,22 +1507,24 @@ OZ_DECLARE(zap_status_t) zap_channel_done(zap_channel_t *zchan)
{ {
assert(zchan != NULL); assert(zchan != NULL);
zap_mutex_lock(zchan->mutex);
memset(&zchan->caller_data, 0, sizeof(zchan->caller_data)); memset(&zchan->caller_data, 0, sizeof(zchan->caller_data));
zap_clear_flag_locked(zchan, ZAP_CHANNEL_INUSE); zap_clear_flag(zchan, ZAP_CHANNEL_INUSE);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_OUTBOUND); zap_clear_flag(zchan, ZAP_CHANNEL_OUTBOUND);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_WINK); zap_clear_flag(zchan, ZAP_CHANNEL_WINK);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_FLASH); zap_clear_flag(zchan, ZAP_CHANNEL_FLASH);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_STATE_CHANGE); zap_clear_flag(zchan, ZAP_CHANNEL_STATE_CHANGE);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_HOLD); zap_clear_flag(zchan, ZAP_CHANNEL_HOLD);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK); zap_clear_flag(zchan, ZAP_CHANNEL_OFFHOOK);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_RINGING); zap_clear_flag(zchan, ZAP_CHANNEL_RINGING);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_PROGRESS_DETECT); zap_clear_flag(zchan, ZAP_CHANNEL_PROGRESS_DETECT);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_CALLERID_DETECT); zap_clear_flag(zchan, ZAP_CHANNEL_CALLERID_DETECT);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_3WAY); zap_clear_flag(zchan, ZAP_CHANNEL_3WAY);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_PROGRESS); zap_clear_flag(zchan, ZAP_CHANNEL_PROGRESS);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_MEDIA); zap_clear_flag(zchan, ZAP_CHANNEL_MEDIA);
zap_clear_flag_locked(zchan, ZAP_CHANNEL_ANSWERED); zap_clear_flag(zchan, ZAP_CHANNEL_ANSWERED);
zap_mutex_lock(zchan->pre_buffer_mutex); zap_mutex_lock(zchan->pre_buffer_mutex);
zap_buffer_destroy(&zchan->pre_buffer); zap_buffer_destroy(&zchan->pre_buffer);
zchan->pre_buffer_size = 0; zchan->pre_buffer_size = 0;
...@@ -1530,8 +1532,11 @@ OZ_DECLARE(zap_status_t) zap_channel_done(zap_channel_t *zchan) ...@@ -1530,8 +1532,11 @@ OZ_DECLARE(zap_status_t) zap_channel_done(zap_channel_t *zchan)
zchan->init_state = ZAP_CHANNEL_STATE_DOWN; zchan->init_state = ZAP_CHANNEL_STATE_DOWN;
zchan->state = ZAP_CHANNEL_STATE_DOWN; zchan->state = ZAP_CHANNEL_STATE_DOWN;
zap_log(ZAP_LOG_DEBUG, "channel done %u:%u\n", zchan->span_id, zchan->chan_id); zap_log(ZAP_LOG_DEBUG, "channel done %u:%u\n", zchan->span_id, zchan->chan_id);
zap_mutex_unlock(zchan->mutex);
return ZAP_SUCCESS; return ZAP_SUCCESS;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论