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);
{
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;
}
#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
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);
+ }
}
/**
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);
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;
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;
}
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:
{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"},
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);
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;
}
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*/
{
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;
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;
}