diff --git a/libs/freetdm/mod_openzap/mod_openzap.c b/libs/freetdm/mod_openzap/mod_openzap.c index 64d19abdec..d0002ebd16 100644 --- a/libs/freetdm/mod_openzap/mod_openzap.c +++ b/libs/freetdm/mod_openzap/mod_openzap.c @@ -333,6 +333,8 @@ static switch_status_t channel_on_init(switch_core_session_t *session) globals.calls++; switch_mutex_unlock(globals.mutex); + zap_channel_init(tech_pvt->zchan); + return SWITCH_STATUS_SUCCESS; } diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 2a02885da2..4cdd259fb8 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -358,6 +358,7 @@ struct zap_channel { uint32_t packet_len; zap_channel_state_t state; zap_channel_state_t last_state; + zap_channel_state_t init_state; zap_mutex_t *mutex; teletone_dtmf_detect_state_t dtmf_detect; uint32_t buffer_delay; @@ -538,6 +539,7 @@ int zap_hash_equalkeys(void *k1, void *k2); uint32_t zap_hash_hashfromstring(void *ky); uint32_t zap_running(void); zap_status_t zap_channel_complete_state(zap_channel_t *zchan); +zap_status_t zap_channel_init(zap_channel_t *zchan); ZIO_CODEC_FUNCTION(zio_slin2ulaw); ZIO_CODEC_FUNCTION(zio_ulaw2slin); diff --git a/libs/freetdm/src/ss7_boost_client.c b/libs/freetdm/src/ss7_boost_client.c index 53a8c8e726..21690506b1 100644 --- a/libs/freetdm/src/ss7_boost_client.c +++ b/libs/freetdm/src/ss7_boost_client.c @@ -135,6 +135,8 @@ int ss7bc_connection_close(ss7bc_connection_t *mcon) close(mcon->socket); } + zap_mutex_lock(mcon->mutex); + zap_mutex_unlock(mcon->mutex); zap_mutex_destroy(&mcon->mutex); memset(mcon, 0, sizeof(*mcon)); mcon->socket = -1; diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c index b54bacbb26..7be39a47b6 100644 --- a/libs/freetdm/src/zap_io.c +++ b/libs/freetdm/src/zap_io.c @@ -722,6 +722,7 @@ zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, c } if (span_id && globals.spans[span_id].channel_request) { + zap_mutex_unlock(globals.mutex); status = globals.spans[span_id].channel_request(&globals.spans[span_id], direction, caller_data, zchan); goto done; } @@ -846,6 +847,16 @@ static zap_status_t zap_channel_reset(zap_channel_t *zchan) return ZAP_SUCCESS; } +zap_status_t zap_channel_init(zap_channel_t *zchan) +{ + if (zchan->init_state != ZAP_CHANNEL_STATE_DOWN) { + zap_set_state_locked(zchan, zchan->init_state); + zchan->init_state = ZAP_CHANNEL_STATE_DOWN; + } + + return ZAP_SUCCESS; +} + zap_status_t zap_channel_open_chan(zap_channel_t *zchan) { zap_status_t status = ZAP_FAIL; @@ -960,6 +971,8 @@ zap_status_t zap_channel_done(zap_channel_t *zchan) zap_clear_flag_locked(zchan, ZAP_CHANNEL_PROGRESS); zap_clear_flag_locked(zchan, ZAP_CHANNEL_MEDIA); zap_clear_flag_locked(zchan, ZAP_CHANNEL_ANSWERED); + zchan->init_state = ZAP_CHANNEL_STATE_DOWN; + zap_log(ZAP_LOG_DEBUG, "channel done %u:%u\n", zchan->span_id, zchan->chan_id); return ZAP_SUCCESS; } diff --git a/libs/freetdm/src/zap_ss7_boost.c b/libs/freetdm/src/zap_ss7_boost.c index 4b0c33a488..fac6cf9840 100644 --- a/libs/freetdm/src/zap_ss7_boost.c +++ b/libs/freetdm/src/zap_ss7_boost.c @@ -101,7 +101,7 @@ static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event, int for if (force) { break; } - if (zap_test_flag(zchan, ZAP_CHANNEL_INUSE)) { + if (zap_test_flag(zchan, ZAP_CHANNEL_INUSE) || zchan->state != ZAP_CHANNEL_STATE_DOWN) { if (zchan->state == ZAP_CHANNEL_STATE_DOWN || zchan->state >= ZAP_CHANNEL_STATE_TERMINATING) { int x = 0; zap_log(ZAP_LOG_WARNING, "Channel %d:%d ~ %d:%d is already in use waiting for it to become available.\n"); @@ -182,6 +182,7 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request) if (OUTBOUND_REQUESTS[r].status == BST_READY && OUTBOUND_REQUESTS[r].zchan) { *zchan = OUTBOUND_REQUESTS[r].zchan; status = ZAP_SUCCESS; + (*zchan)->init_state = ZAP_CHANNEL_STATE_PROGRESS_MEDIA; } else { status = ZAP_FAIL; *zchan = NULL; @@ -206,16 +207,16 @@ static void handle_call_start_ack(ss7bc_connection_t *mcon, ss7bc_event_t *event OUTBOUND_REQUESTS[event->call_setup_id].event = *event; - if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event, 1))) { - OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY; + if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event, 0))) { if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) { zap_log(ZAP_LOG_ERROR, "OPEN ERROR [%s]\n", zchan->last_error); release_request_id(event->call_setup_id); } else { - zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_PROGRESS_MEDIA); zap_set_flag(zchan, ZAP_CHANNEL_OUTBOUND); + zap_set_flag_locked(zchan, ZAP_CHANNEL_INUSE); zchan->extra_id = event->call_setup_id; OUTBOUND_REQUESTS[event->call_setup_id].zchan = zchan; + OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY; return; } } @@ -243,17 +244,30 @@ static void handle_call_done(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_e } } -static void handle_call_start_nack(ss7bc_connection_t *mcon, ss7bc_event_t *event) +static void handle_call_start_nack(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) { - OUTBOUND_REQUESTS[event->call_setup_id].event = *event; - OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL; - release_request_id(event->call_setup_id); - ss7bc_exec_command(mcon, - event->span, - event->chan, - event->call_setup_id, - SIGBOOST_EVENT_CALL_START_NACK_ACK, - 0); + + if (event->call_setup_id) { + OUTBOUND_REQUESTS[event->call_setup_id].event = *event; + OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL; + + ss7bc_exec_command(mcon, + event->span, + event->chan, + event->call_setup_id, + SIGBOOST_EVENT_CALL_START_NACK_ACK, + 0); + + release_request_id(event->call_setup_id); + } else { + zap_channel_t *zchan; + if ((zchan = find_zchan(span, event, 1))) { + assert(!zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)); + zchan->caller_data.hangup_cause = event->release_cause; + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_TERMINATING); + } + } + } static void handle_call_stop(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) @@ -281,6 +295,7 @@ static void handle_call_answer(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc zap_channel_t *zchan; if ((zchan = find_zchan(span, event, 1))) { + assert(zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)); zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_UP); } else { zap_log(ZAP_LOG_CRIT, "ANSWER CANT FIND A CHAN %d:%d\n", event->span+1,event->chan+1); @@ -351,6 +366,12 @@ static void handle_restart_ack(ss7bc_connection_t *mcon, zap_span_t *span, ss7bc static int parse_ss7_event(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) { zap_mutex_lock(signal_mutex); + + if (!zap_running()) { + zap_log(ZAP_LOG_WARNING, "System is shutting down.\n"); + goto end; + } + if (zap_test_flag(span, ZAP_SPAN_SUSPENDED) && event->event_id != SIGBOOST_EVENT_SYSTEM_RESTART_ACK && event->event_id != SIGBOOST_EVENT_HEARTBEAT) { @@ -399,7 +420,7 @@ static int parse_ss7_event(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_eve handle_call_start_ack(mcon, event); break; case SIGBOOST_EVENT_CALL_START_NACK: - handle_call_start_nack(mcon, event); + handle_call_start_nack(span, mcon, event); break; case SIGBOOST_EVENT_CALL_ANSWERED: handle_call_answer(span, mcon, event); @@ -506,7 +527,6 @@ static __inline__ void state_advance(zap_channel_t *zchan) zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); } } else { - if (!(zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS) || zap_test_flag(zchan, ZAP_CHANNEL_MEDIA))) { ss7bc_exec_command(mcon, zchan->physical_span_id-1, @@ -536,7 +556,7 @@ static __inline__ void state_advance(zap_channel_t *zchan) break; case ZAP_CHANNEL_STATE_HANGUP: { - if (zap_test_flag(zchan, ZAP_CHANNEL_ANSWERED)) { + if (zap_test_flag(zchan, ZAP_CHANNEL_ANSWERED) || zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS) || zap_test_flag(zchan, ZAP_CHANNEL_MEDIA)) { ss7bc_exec_command(mcon, zchan->physical_span_id-1, zchan->physical_chan_id-1, @@ -627,11 +647,21 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj) SIGBOOST_EVENT_SYSTEM_RESTART, 0); - while (zap_running() && zap_test_flag(ss7_boost_data, ZAP_SS7_BOOST_RUNNING)) { + while (zap_test_flag(ss7_boost_data, ZAP_SS7_BOOST_RUNNING)) { fd_set rfds, efds; struct timeval tv = { 0, ms * 1000 }; int max, activity, i = 0; ss7bc_event_t *event = NULL; + + if (!zap_running()) { + ss7bc_exec_command(mcon, + 0, + 0, + -1, + SIGBOOST_EVENT_SYSTEM_RESTART, + 0); + break; + } FD_ZERO(&rfds); FD_ZERO(&efds);