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
This commit is contained in:
parent
e9e0edb33f
commit
200b25e256
|
@ -451,8 +451,8 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
|
|||
nack_map[r] = 1;
|
||||
if (sangoma_boost_data->sigmod) {
|
||||
sangomabc_exec_command(&sangoma_boost_data->mcon,
|
||||
(*zchan)->physical_span_id,
|
||||
(*zchan)->physical_chan_id,
|
||||
BOOST_SPAN((*zchan)),
|
||||
BOOST_CHAN((*zchan)),
|
||||
r,
|
||||
SIGBOOST_EVENT_CALL_START_NACK,
|
||||
0);
|
||||
|
@ -616,10 +616,22 @@ static void handle_call_done(zap_span_t *span, sangomabc_connection_t *mcon, san
|
|||
{
|
||||
zap_channel_t *zchan;
|
||||
int r = 0;
|
||||
|
||||
|
||||
if ((zchan = find_zchan(span, event, 1))) {
|
||||
zap_sangoma_boost_data_t *sangoma_boost_data = zchan->span->signal_data;
|
||||
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) {
|
||||
goto done;
|
||||
}
|
||||
|
@ -729,6 +741,18 @@ static void handle_call_start_nack(zap_span_t *span, sangomabc_connection_t *mco
|
|||
#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
|
||||
* \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
|
|||
if (r) {
|
||||
return;
|
||||
}
|
||||
} /* else we have to do it ourselves.... */
|
||||
|
||||
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);
|
||||
} 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);
|
||||
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
|
|||
zap_log(ZAP_LOG_CRIT, "START CANT FIND CHAN %d:%d AT ALL\n", event->span+1,event->chan+1);
|
||||
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);
|
||||
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);
|
||||
|
@ -996,6 +1023,9 @@ static int parse_sangoma_event(zap_span_t *span, sangomabc_connection_t *mcon, s
|
|||
case SIGBOOST_EVENT_CALL_STOPPED:
|
||||
handle_call_stop(span, mcon, event);
|
||||
break;
|
||||
case SIGBOOST_EVENT_CALL_RELEASED:
|
||||
handle_call_released(span, mcon, event);
|
||||
break;
|
||||
case SIGBOOST_EVENT_CALL_START_ACK:
|
||||
handle_call_start_ack(mcon, event);
|
||||
break;
|
||||
|
@ -1070,6 +1100,8 @@ static __inline__ void state_advance(zap_channel_t *zchan)
|
|||
switch (zchan->state) {
|
||||
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) {
|
||||
zchan->extra_id = 0;
|
||||
}
|
||||
|
@ -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)) {
|
||||
sangomabc_exec_command(mcon,
|
||||
zchan->physical_span_id-1,
|
||||
zchan->physical_chan_id-1,
|
||||
BOOST_SPAN(zchan),
|
||||
BOOST_CHAN(zchan),
|
||||
0,
|
||||
SIGBOOST_EVENT_CALL_START_NACK_ACK,
|
||||
0);
|
||||
|
||||
} else {
|
||||
/* we got a call stop msg, time to reply with call stopped ack */
|
||||
sangomabc_exec_command(mcon,
|
||||
zchan->physical_span_id-1,
|
||||
zchan->physical_chan_id-1,
|
||||
BOOST_SPAN(zchan),
|
||||
BOOST_CHAN(zchan),
|
||||
0,
|
||||
SIGBOOST_EVENT_CALL_STOPPED_ACK,
|
||||
0);
|
||||
call_stopped_ack_sent = 1;
|
||||
}
|
||||
}
|
||||
zchan->sflags = 0;
|
||||
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;
|
||||
case ZAP_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
|
|
|
@ -60,6 +60,7 @@ static struct sangomabc_map sangomabc_table[] = {
|
|||
{SIGBOOST_EVENT_CALL_ANSWERED, "CALL_ANSWERED"},
|
||||
{SIGBOOST_EVENT_CALL_STOPPED, "CALL_STOPPED"},
|
||||
{SIGBOOST_EVENT_CALL_STOPPED_ACK, "CALL_STOPPED_ACK"},
|
||||
{SIGBOOST_EVENT_CALL_RELEASED, "CALL_RELEASED"},
|
||||
{SIGBOOST_EVENT_SYSTEM_RESTART, "SYSTEM_RESTART"},
|
||||
{SIGBOOST_EVENT_SYSTEM_RESTART_ACK, "SYSTEM_RESTART_ACK"},
|
||||
{SIGBOOST_EVENT_HEARTBEAT, "HEARTBEAT"},
|
||||
|
@ -457,7 +458,13 @@ int __sangomabc_connection_write(sangomabc_connection_t *mcon, sangomabc_event_t
|
|||
event->fseqno = mcon->txseq++;
|
||||
}
|
||||
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) {
|
||||
mcon->sigmod->write_msg(mcon->span, event, event_size);
|
||||
|
@ -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!");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,19 @@ enum e_sigboost_event_id_values
|
|||
SIGBOOST_EVENT_CALL_ANSWERED = 0x84, /*132*/
|
||||
SIGBOOST_EVENT_CALL_STOPPED = 0x85, /*133*/
|
||||
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_ACK = 0x88, /*136*/
|
||||
SIGBOOST_EVENT_CALL_PROGRESS = 0x50, /*decimal 80*/
|
||||
|
|
|
@ -1507,22 +1507,24 @@ OZ_DECLARE(zap_status_t) zap_channel_done(zap_channel_t *zchan)
|
|||
{
|
||||
assert(zchan != NULL);
|
||||
|
||||
zap_mutex_lock(zchan->mutex);
|
||||
|
||||
memset(&zchan->caller_data, 0, sizeof(zchan->caller_data));
|
||||
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_INUSE);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_OUTBOUND);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_WINK);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_FLASH);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_STATE_CHANGE);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_HOLD);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_RINGING);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_PROGRESS_DETECT);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_CALLERID_DETECT);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_3WAY);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_PROGRESS);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_MEDIA);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_ANSWERED);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_INUSE);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_OUTBOUND);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_WINK);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_FLASH);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_STATE_CHANGE);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_HOLD);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_OFFHOOK);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_RINGING);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_PROGRESS_DETECT);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_CALLERID_DETECT);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_3WAY);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_PROGRESS);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_MEDIA);
|
||||
zap_clear_flag(zchan, ZAP_CHANNEL_ANSWERED);
|
||||
zap_mutex_lock(zchan->pre_buffer_mutex);
|
||||
zap_buffer_destroy(&zchan->pre_buffer);
|
||||
zchan->pre_buffer_size = 0;
|
||||
|
@ -1530,8 +1532,11 @@ OZ_DECLARE(zap_status_t) zap_channel_done(zap_channel_t *zchan)
|
|||
|
||||
zchan->init_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_mutex_unlock(zchan->mutex);
|
||||
|
||||
return ZAP_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue