diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 6261e2e57f..ee4b4a7ac7 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -536,7 +536,7 @@ void print_hex_bytes(uint8_t *data, zap_size_t dlen, char *buf, zap_size_t blen) 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); ZIO_CODEC_FUNCTION(zio_slin2ulaw); ZIO_CODEC_FUNCTION(zio_ulaw2slin); diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h index c4f477e625..2336e7ded3 100644 --- a/libs/freetdm/src/include/zap_types.h +++ b/libs/freetdm/src/include/zap_types.h @@ -302,11 +302,12 @@ typedef enum { ZAP_CHANNEL_STATE_IDLE, ZAP_CHANNEL_STATE_TERMINATING, ZAP_CHANNEL_STATE_HANGUP, + ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_CHANNEL_STATE_INVALID } zap_channel_state_t; #define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \ "RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \ - "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "HANGUP", "INVALID" + "RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "HANGUP", "HANGUP_COMPLETE", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t) typedef enum { diff --git a/libs/freetdm/src/zap_analog.c b/libs/freetdm/src/zap_analog.c index 7e6027e06b..3b1246961b 100644 --- a/libs/freetdm/src/zap_analog.c +++ b/libs/freetdm/src/zap_analog.c @@ -345,6 +345,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) } else { zap_clear_flag_locked(zchan, ZAP_CHANNEL_STATE_CHANGE); zap_clear_flag_locked(zchan->span, ZAP_SPAN_STATE_CHANGE); + zap_channel_complete_state(zchan); indicate = 0; state_counter = 0; zap_log(ZAP_LOG_DEBUG, "Executing state handler on %d:%d for %s\n", diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c index 13c68f0956..6ef687e7a1 100644 --- a/libs/freetdm/src/zap_io.c +++ b/libs/freetdm/src/zap_io.c @@ -599,6 +599,25 @@ zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token, int end) } +zap_status_t zap_channel_complete_state(zap_channel_t *zchan) +{ + zap_channel_state_t state = zchan->state; + + if (state == ZAP_CHANNEL_STATE_PROGRESS) { + zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS); + } else if (state == ZAP_CHANNEL_STATE_UP) { + zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS); + zap_set_flag(zchan, ZAP_CHANNEL_MEDIA); + zap_set_flag(zchan, ZAP_CHANNEL_ANSWERED); + } else if (state == ZAP_CHANNEL_STATE_PROGRESS_MEDIA) { + zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS); + zap_set_flag(zchan, ZAP_CHANNEL_MEDIA); + } + + return ZAP_SUCCESS; +} + + zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state) { int ok = 1; @@ -669,17 +688,6 @@ zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t sta } if (ok) { - if (state == ZAP_CHANNEL_STATE_PROGRESS) { - zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS); - } else if (state == ZAP_CHANNEL_STATE_UP) { - zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS); - zap_set_flag(zchan, ZAP_CHANNEL_MEDIA); - zap_set_flag(zchan, ZAP_CHANNEL_ANSWERED); - } else if (state == ZAP_CHANNEL_STATE_PROGRESS_MEDIA) { - zap_set_flag(zchan, ZAP_CHANNEL_PROGRESS); - zap_set_flag(zchan, ZAP_CHANNEL_MEDIA); - } - if (zchan->state == ZAP_CHANNEL_STATE_DOWN) { zchan->span->active_count++; } else if (state == ZAP_CHANNEL_STATE_DOWN) { diff --git a/libs/freetdm/src/zap_isdn.c b/libs/freetdm/src/zap_isdn.c index 8af35ef12a..f105174353 100644 --- a/libs/freetdm/src/zap_isdn.c +++ b/libs/freetdm/src/zap_isdn.c @@ -334,7 +334,7 @@ static __inline__ void state_advance(zap_channel_t *zchan) break; case ZAP_CHANNEL_STATE_RESTART: { - if (zchan->last_state > ZAP_CHANNEL_STATE_HANGUP) { + if (zchan->last_state != ZAP_CHANNEL_STATE_HANGUP && zchan->last_state != ZAP_CHANNEL_STATE_DOWN) { zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); } else { zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); @@ -523,6 +523,7 @@ static __inline__ void check_state(zap_span_t *span) for(j = 1; j <= span->chan_count; j++) { if (zap_test_flag((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE)) { state_advance(&span->channels[j]); + zap_channel_complete_state(&span->channels[j]); zap_clear_flag_locked((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE); } } diff --git a/libs/freetdm/src/zap_ss7_boost.c b/libs/freetdm/src/zap_ss7_boost.c index b131d6a1ba..685c13cc29 100644 --- a/libs/freetdm/src/zap_ss7_boost.c +++ b/libs/freetdm/src/zap_ss7_boost.c @@ -72,7 +72,7 @@ static ss7_boost_request_id_t next_request_id(void) return r + 1; } -static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event) +static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event, int force) { int i; zap_channel_t *zchan = NULL; @@ -81,6 +81,9 @@ static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event) for(i = 0; i <= span->chan_count; i++) { if (span->channels[i].physical_span_id == event->span+1 && span->channels[i].physical_chan_id == event->chan+1) { zchan = &span->channels[i]; + if (force) { + break; + } if (zap_test_flag(zchan, ZAP_CHANNEL_INUSE)) { if (zchan->state == ZAP_CHANNEL_STATE_DOWN || zchan->state >= ZAP_CHANNEL_STATE_TERMINATING) { int x = 0; @@ -108,6 +111,7 @@ static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event) break; } } + zap_mutex_unlock(signal_mutex); return zchan; @@ -185,7 +189,7 @@ 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))) { + if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event, 1))) { OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY; if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) { zap_log(ZAP_LOG_ERROR, "OPEN ERROR [%s]\n", zchan->last_error); @@ -208,6 +212,18 @@ static void handle_call_start_ack(ss7bc_connection_t *mcon, ss7bc_event_t *event } +static void handle_call_done(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) +{ + zap_channel_t *zchan; + + if ((zchan = find_zchan(span, event, 1))) { + + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); + } else { + zap_log(ZAP_LOG_CRIT, "DONE CANT FIND A CHAN %d:%d\n", event->span+1,event->chan+1); + } +} + static void handle_call_start_nack(ss7bc_connection_t *mcon, ss7bc_event_t *event) { OUTBOUND_REQUESTS[event->call_setup_id].event = *event; @@ -225,7 +241,7 @@ static void handle_call_stop(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_e { zap_channel_t *zchan; - if ((zchan = find_zchan(span, event))) { + if ((zchan = find_zchan(span, event, 1))) { zchan->caller_data.hangup_cause = event->release_cause; zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_TERMINATING); } else { @@ -245,7 +261,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))) { + if ((zchan = find_zchan(span, event, 1))) { 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); @@ -256,7 +272,7 @@ static void handle_call_start(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_ { zap_channel_t *zchan; - if (!(zchan = find_zchan(span, event))) { + if (!(zchan = find_zchan(span, event, 0))) { goto error; } @@ -372,11 +388,9 @@ static int parse_ss7_event(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_eve case SIGBOOST_EVENT_HEARTBEAT: handle_heartbeat(mcon, event); break; - case SIGBOOST_EVENT_CALL_START_NACK_ACK: - //handle_call_start_nack_ack(event); - break; case SIGBOOST_EVENT_CALL_STOPPED_ACK: - //handle_call_stop_ack(event); + case SIGBOOST_EVENT_CALL_START_NACK_ACK: + handle_call_done(span, mcon, event); break; case SIGBOOST_EVENT_INSERT_CHECK_LOOP: //handle_call_loop_start(event); @@ -432,7 +446,12 @@ static __inline__ void state_advance(zap_channel_t *zchan) zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); } } else { - + ss7bc_exec_command(mcon, + zchan->physical_span_id-1, + zchan->physical_chan_id-1, + 0, + SIGBOOST_EVENT_CALL_START_ACK, + 0); } } break; @@ -449,7 +468,7 @@ static __inline__ void state_advance(zap_channel_t *zchan) break; case ZAP_CHANNEL_STATE_RESTART: { - if (zchan->last_state > ZAP_CHANNEL_STATE_HANGUP) { + if (zchan->last_state != ZAP_CHANNEL_STATE_HANGUP && zchan->last_state != ZAP_CHANNEL_STATE_DOWN) { zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); } else { zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); @@ -464,12 +483,15 @@ static __inline__ void state_advance(zap_channel_t *zchan) zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); } } else { - ss7bc_exec_command(mcon, - zchan->physical_span_id-1, - zchan->physical_chan_id-1, - 0, - SIGBOOST_EVENT_CALL_START_ACK, - 0); + + if (!(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, + 0, + SIGBOOST_EVENT_CALL_START_ACK, + 0); + } ss7bc_exec_command(mcon, zchan->physical_span_id-1, @@ -484,6 +506,11 @@ static __inline__ void state_advance(zap_channel_t *zchan) { } break; + case ZAP_CHANNEL_STATE_HANGUP_COMPLETE: + { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); + } + break; case ZAP_CHANNEL_STATE_HANGUP: { if (zap_test_flag(zchan, ZAP_CHANNEL_ANSWERED)) { @@ -500,9 +527,7 @@ static __inline__ void state_advance(zap_channel_t *zchan) 0, SIGBOOST_EVENT_CALL_START_NACK, zchan->caller_data.hangup_cause); - } - zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); - + } } break; case ZAP_CHANNEL_STATE_TERMINATING: @@ -531,6 +556,7 @@ static __inline__ void check_state(zap_span_t *span) if (zap_test_flag((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE)) { zap_mutex_lock(signal_mutex); state_advance(&span->channels[j]); + zap_channel_complete_state(&span->channels[j]); zap_mutex_unlock(signal_mutex); zap_clear_flag_locked((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE); }