diff --git a/libs/freetdm/mod_openzap/mod_openzap.c b/libs/freetdm/mod_openzap/mod_openzap.c index e0e4b6ac43..79d4a7b55a 100644 --- a/libs/freetdm/mod_openzap/mod_openzap.c +++ b/libs/freetdm/mod_openzap/mod_openzap.c @@ -981,6 +981,7 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t *sp = NULL; if (!(session = switch_core_session_request(openzap_endpoint_interface, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n"); return ZAP_FAIL; } @@ -1045,6 +1046,7 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t } if (zap_channel_add_token(sigmsg->channel, switch_core_session_get_uuid(session), 0) != ZAP_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding token\n"); switch_core_session_destroy(&session); return ZAP_FAIL; } @@ -1351,11 +1353,11 @@ static ZIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) case ZAP_SIGEVENT_STOP: { while((session = zap_channel_get_session(sigmsg->channel, 0))) { - switch_core_session_signal_lock(session); + //switch_core_session_signal_lock(session); channel = switch_core_session_get_channel(session); switch_channel_hangup(channel, sigmsg->channel->caller_data.hangup_cause); zap_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session)); - switch_core_session_signal_unlock(session); + //switch_core_session_signal_unlock(session); switch_core_session_rwunlock(session); } } @@ -1364,23 +1366,23 @@ static ZIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) { if ((session = zap_channel_get_session(sigmsg->channel, 0))) { zap_tone_type_t tt = ZAP_TONE_DTMF; - switch_core_session_signal_lock(session); + //switch_core_session_signal_lock(session); channel = switch_core_session_get_channel(session); switch_channel_mark_answered(channel); if (zap_channel_command(sigmsg->channel, ZAP_COMMAND_ENABLE_DTMF_DETECT, &tt) != ZAP_SUCCESS) { zap_log(ZAP_LOG_ERROR, "TONE ERROR\n"); } - switch_core_session_signal_unlock(session); + //switch_core_session_signal_unlock(session); switch_core_session_rwunlock(session); } } case ZAP_SIGEVENT_PROGRESS_MEDIA: { if ((session = zap_channel_get_session(sigmsg->channel, 0))) { - switch_core_session_signal_lock(session); + //switch_core_session_signal_lock(session); channel = switch_core_session_get_channel(session); switch_channel_mark_pre_answered(channel); - switch_core_session_signal_unlock(session); + //switch_core_session_signal_unlock(session); switch_core_session_rwunlock(session); } } @@ -1388,10 +1390,10 @@ static ZIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) case ZAP_SIGEVENT_PROGRESS: { if ((session = zap_channel_get_session(sigmsg->channel, 0))) { - switch_core_session_signal_lock(session); + //switch_core_session_signal_lock(session); channel = switch_core_session_get_channel(session); switch_channel_mark_ring_ready(channel); - switch_core_session_signal_unlock(session); + //switch_core_session_signal_unlock(session); switch_core_session_rwunlock(session); } } diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 57c87fb549..0f8fba7ecc 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -175,6 +175,7 @@ */ #define zap_test_flag(obj, flag) ((obj)->flags & flag) #define zap_test_pflag(obj, flag) ((obj)->pflags & flag) +#define zap_test_sflag(obj, flag) ((obj)->sflags & flag) #define zap_set_alarm_flag(obj, flag) (obj)->alarm_flags |= (flag) @@ -198,6 +199,12 @@ (obj)->pflags |= (flag); \ zap_mutex_unlock(obj->mutex); +#define zap_set_sflag(obj, flag) (obj)->sflags |= (flag) +#define zap_set_sflag_locked(obj, flag) assert(obj->mutex != NULL); \ + zap_mutex_lock(obj->mutex); \ + (obj)->sflags |= (flag); \ + zap_mutex_unlock(obj->mutex); + /*! \brief Clear a flag on an arbitrary object while locked \command obj the object to test @@ -211,16 +218,35 @@ #define zap_clear_pflag_locked(obj, flag) assert(obj->mutex != NULL); zap_mutex_lock(obj->mutex); (obj)->pflags &= ~(flag); zap_mutex_unlock(obj->mutex); +#define zap_clear_sflag(obj, flag) (obj)->sflags &= ~(flag) + +#define zap_clear_sflag_locked(obj, flag) assert(obj->mutex != NULL); zap_mutex_lock(obj->mutex); (obj)->sflags &= ~(flag); zap_mutex_unlock(obj->mutex); + #define zap_set_state_locked(obj, s) if ( obj->state == s ) { \ zap_log(ZAP_LOG_WARNING, "Why bother changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, zap_channel_state2str(obj->state), zap_channel_state2str(s)); \ } else if (zap_test_flag(obj, ZAP_CHANNEL_READY)) { \ int st = obj->state; \ - zap_channel_set_state(obj, s); \ + zap_channel_set_state(obj, s, 1); \ if (obj->state == s) zap_log(ZAP_LOG_DEBUG, "Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, zap_channel_state2str(st), zap_channel_state2str(s)); \ else zap_log(ZAP_LOG_WARNING, "VETO Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, zap_channel_state2str(st), zap_channel_state2str(s)); \ } +typedef enum { + ZAP_STATE_CHANGE_FAIL, + ZAP_STATE_CHANGE_SUCCESS, + ZAP_STATE_CHANGE_SAME, +} zap_state_change_result_t; + +#define zap_set_state_r(obj, s, l, r) if ( obj->state == s ) { \ + zap_log(ZAP_LOG_WARNING, "Why bother changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, zap_channel_state2str(obj->state), zap_channel_state2str(s)); r = ZAP_STATE_CHANGE_SAME; \ + } else if (zap_test_flag(obj, ZAP_CHANNEL_READY)) { \ + int st = obj->state; \ + r = (zap_channel_set_state(obj, s, l) == ZAP_SUCCESS) ? ZAP_STATE_CHANGE_SUCCESS : ZAP_STATE_CHANGE_FAIL; \ + if (obj->state == s) {zap_log(ZAP_LOG_DEBUG, "Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, zap_channel_state2str(st), zap_channel_state2str(s));} \ + else {zap_log(ZAP_LOG_WARNING, "VETO Changing state on %d:%d from %s to %s\n", obj->span_id, obj->chan_id, zap_channel_state2str(st), zap_channel_state2str(s)); } \ + } + #define zap_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119) @@ -358,6 +384,7 @@ struct zap_channel { zap_socket_t sockfd; zap_channel_flag_t flags; uint32_t pflags; + uint32_t sflags; zap_alarm_flag_t alarm_flags; zap_channel_feature_t features; zap_codec_t effective_codec; @@ -455,6 +482,7 @@ struct zap_span { void *mod_data; char *type; int suggest_chan_id; + zap_state_map_t *state_map; }; @@ -515,7 +543,7 @@ zap_status_t zap_channel_get_alarms(zap_channel_t *zchan); zap_status_t zap_channel_send_fsk_data(zap_channel_t *zchan, zap_fsk_data_state_t *fsk_data, float db_level); zap_status_t zap_channel_clear_token(zap_channel_t *zchan, const char *token); zap_status_t zap_channel_add_token(zap_channel_t *zchan, char *token, int end); -zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state); +zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state, int lock); zap_status_t zap_span_load_tones(zap_span_t *span, char *mapname); zap_size_t zap_channel_dequeue_dtmf(zap_channel_t *zchan, char *dtmf, zap_size_t len); zap_status_t zap_channel_queue_dtmf(zap_channel_t *zchan, const char *dtmf); diff --git a/libs/freetdm/src/include/ss7_boost_client.h b/libs/freetdm/src/include/ss7_boost_client.h index d2fee452bc..4184f5385e 100644 --- a/libs/freetdm/src/include/ss7_boost_client.h +++ b/libs/freetdm/src/include/ss7_boost_client.h @@ -119,7 +119,8 @@ int ss7bc_connection_close(ss7bc_connection_t *mcon); int ss7bc_connection_open(ss7bc_connection_t *mcon, char *local_ip, int local_port, char *ip, int port); ss7bc_event_t *ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration); ss7bc_event_t *ss7bc_connection_readp(ss7bc_connection_t *mcon, int iteration); -int ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event); +int __ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event, const char *file, const char *func, int line); +#define ss7bc_connection_write(_m,_e) __ss7bc_connection_write(_m, _e, __FILE__, __func__, __LINE__) void ss7bc_event_init(ss7bc_event_t *event, ss7bc_event_id_t event_id, int chan, int span); void ss7bc_call_init(ss7bc_event_t *event, const char *calling, const char *called, int setup_id); const char *ss7bc_event_id_name(uint32_t event_id); diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h index 5ee75505ab..8b25e9fc07 100644 --- a/libs/freetdm/src/include/zap_types.h +++ b/libs/freetdm/src/include/zap_types.h @@ -66,6 +66,9 @@ struct zap_io_interface; #define ZAP_DEFAULT_DTMF_ON 250 #define ZAP_DEFAULT_DTMF_OFF 50 +#define ZAP_END -1 +#define ZAP_ANY_STATE -1 + typedef uint64_t zap_time_t; typedef enum { @@ -343,6 +346,33 @@ typedef enum { ZAP_CHANNEL_ANSWERED = (1 << 23) } zap_channel_flag_t; +typedef enum { + ZSM_NONE, + ZSM_UNACCEPTABLE, + ZSM_ACCEPTABLE +} zap_state_map_type_t; + +typedef enum { + ZSD_INBOUND, + ZSD_OUTBOUND, +} zap_state_direction_t; + +#define ZAP_MAP_NODE_SIZE 512 +#define ZAP_MAP_MAX ZAP_CHANNEL_STATE_INVALID+2 + +struct zap_state_map_node { + zap_state_direction_t direction; + zap_state_map_type_t type; + zap_channel_state_t check_states[ZAP_MAP_MAX]; + zap_channel_state_t states[ZAP_MAP_MAX]; +}; +typedef struct zap_state_map_node zap_state_map_node_t; + +struct zap_state_map { + zap_state_map_node_t nodes[ZAP_MAP_NODE_SIZE]; +}; +typedef struct zap_state_map zap_state_map_t; + typedef struct zap_channel zap_channel_t; typedef struct zap_event zap_event_t; typedef struct zap_sigmsg zap_sigmsg_t; diff --git a/libs/freetdm/src/ss7_boost_client.c b/libs/freetdm/src/ss7_boost_client.c index 21690506b1..75d274cfaf 100644 --- a/libs/freetdm/src/ss7_boost_client.c +++ b/libs/freetdm/src/ss7_boost_client.c @@ -135,9 +135,11 @@ 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); + if (mcon->mutex) { + zap_mutex_lock(mcon->mutex); + zap_mutex_unlock(mcon->mutex); + zap_mutex_destroy(&mcon->mutex); + } memset(mcon, 0, sizeof(*mcon)); mcon->socket = -1; @@ -245,17 +247,19 @@ ss7bc_event_t *ss7bc_connection_readp(ss7bc_connection_t *mcon, int iteration) } -int ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event) +int __ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event, const char *file, const char *func, int line) { int err; if (!event || mcon->socket < 0 || !mcon->mutex) { - zap_log(ZAP_LOG_DEBUG, "Critical Error: No Event Device\n"); + zap_log(file, func, line, ZAP_LOG_LEVEL_CRIT, "Critical Error: No Event Device\n"); return -EINVAL; + abort(); } if (event->span > 16 || event->chan > 31) { - zap_log(ZAP_LOG_CRIT, "Critical Error: TX Cmd=%s Invalid Span=%i Chan=%i\n", ss7bc_event_id_name(event->event_id), event->span,event->chan); + zap_log(file, func, line, ZAP_LOG_LEVEL_CRIT, "Critical Error: TX Cmd=%s Invalid Span=%i Chan=%i\n", ss7bc_event_id_name(event->event_id), event->span,event->chan); + abort(); return -1; } @@ -269,9 +273,10 @@ int ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event) if (err != sizeof(ss7bc_event_t)) { err = -1; + abort(); } - zap_log(ZAP_LOG_DEBUG, "TX EVENT: %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i Cd=[%s] Ci=[%s]\n", + zap_log(file, func, line, ZAP_LOG_LEVEL_DEBUG, "TX EVENT: %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i Cd=[%s] Ci=[%s]\n", ss7bc_event_id_name(event->event_id), event->event_id, event->span+1, @@ -286,6 +291,7 @@ int ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event) return err; } + void ss7bc_call_init(ss7bc_event_t *event, const char *calling, const char *called, int setup_id) { memset(event, 0, sizeof(ss7bc_event_t)); diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c index 5bdb83f3df..9fa317c0e4 100644 --- a/libs/freetdm/src/zap_io.c +++ b/libs/freetdm/src/zap_io.c @@ -621,16 +621,69 @@ zap_status_t zap_channel_complete_state(zap_channel_t *zchan) return ZAP_SUCCESS; } - -zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state) +static int zap_parse_state_map(zap_channel_t *zchan, zap_channel_state_t state, zap_state_map_t *state_map) { - int ok = 1; + int x = 0, ok = 0; + zap_state_direction_t direction = zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND) ? ZSD_OUTBOUND : ZSD_INBOUND; + + for(x = 0; x < ZAP_MAP_NODE_SIZE; x++) { + int i = 0, proceed = 0; + if (!state_map->nodes[x].type) { + break; + } + + if (state_map->nodes[x].direction != direction) { + continue; + } + + if (state_map->nodes[x].check_states[0] == ZAP_ANY_STATE) { + proceed = 1; + } else { + for(i = 0; i < ZAP_MAP_MAX; i++) { + if (state_map->nodes[x].check_states[i] == zchan->state) { + proceed = 1; + break; + } + } + } + + if (!proceed) { + continue; + } + + for(i = 0; i < ZAP_MAP_MAX; i++) { + ok = (state_map->nodes[x].type == ZSM_ACCEPTABLE); + if (state_map->nodes[x].states[i] == ZAP_END) { + break; + } + if (state_map->nodes[x].states[i] == state) { + ok = !ok; + goto end; + } + } + } + end: + + return ok; +} + +zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t state, int lock) +{ + int ok = 0; if (!zap_test_flag(zchan, ZAP_CHANNEL_READY)) { return ZAP_FAIL; } - zap_mutex_lock(zchan->mutex); + if (lock) { + zap_mutex_lock(zchan->mutex); + } + + if (zchan->span->state_map) { + ok = zap_parse_state_map(zchan, state, zchan->span->state_map); + goto end; + } + switch(zchan->state) { case ZAP_CHANNEL_STATE_HANGUP: case ZAP_CHANNEL_STATE_TERMINATING: @@ -649,6 +702,7 @@ zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t sta break; case ZAP_CHANNEL_STATE_UP: { + ok = 0; switch(state) { case ZAP_CHANNEL_STATE_PROGRESS: case ZAP_CHANNEL_STATE_PROGRESS_MEDIA: @@ -661,11 +715,12 @@ zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t sta break; case ZAP_CHANNEL_STATE_DOWN: { + ok = 0; + switch(state) { - case ZAP_CHANNEL_STATE_BUSY: - case ZAP_CHANNEL_STATE_HANGUP: - case ZAP_CHANNEL_STATE_TERMINATING: - ok = 0; + case ZAP_CHANNEL_STATE_DIALTONE: + case ZAP_CHANNEL_STATE_RING: + ok = 1; break; default: break; @@ -683,14 +738,28 @@ zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t sta } } break; + case ZAP_CHANNEL_STATE_RING: + { + switch(state) { + case ZAP_CHANNEL_STATE_UP: + ok = 0; + break; + default: + break; + } + } + break; default: break; } + end: + if (state == zchan->state) { ok = 0; } - + + if (ok) { if (zchan->state == ZAP_CHANNEL_STATE_DOWN) { zchan->span->active_count++; @@ -704,7 +773,9 @@ zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t sta zchan->state = state; } - zap_mutex_unlock(zchan->mutex); + if (lock) { + zap_mutex_unlock(zchan->mutex); + } return ok ? ZAP_SUCCESS : ZAP_FAIL; } @@ -868,6 +939,7 @@ static zap_status_t zap_channel_reset(zap_channel_t *zchan) 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; diff --git a/libs/freetdm/src/zap_ss7_boost.c b/libs/freetdm/src/zap_ss7_boost.c index 5d586e6d56..885a75f296 100644 --- a/libs/freetdm/src/zap_ss7_boost.c +++ b/libs/freetdm/src/zap_ss7_boost.c @@ -35,6 +35,11 @@ #include "ss7_boost_client.h" #include "zap_ss7_boost.h" +typedef enum { + SFLAG_FREE_REQ_ID = (1 << 0), + SFLAG_SENT_FINAL_RESPONSE = (1 << 1) +} sflag_t; + typedef uint16_t ss7_boost_request_id_t; typedef enum { @@ -51,7 +56,11 @@ typedef struct { zap_channel_t *zchan; } ss7_boost_request_t; -#define MAX_REQ_ID MAX_PENDING_CALLS +#define MAX_REQ_ID ZAP_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN * ZAP_MAX_CHANNELS_PHYSICAL_SPAN + + //#define MAX_REQ_ID 5 + +static uint16_t SETUP_GRID[ZAP_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN+1][ZAP_MAX_CHANNELS_PHYSICAL_SPAN+1] = {{ 0 }}; static ss7_boost_request_t OUTBOUND_REQUESTS[MAX_REQ_ID+1] = {{ 0 }}; @@ -60,34 +69,66 @@ static zap_mutex_t *signal_mutex = NULL; static uint8_t req_map[MAX_REQ_ID+1] = { 0 }; -static void release_request_id(ss7_boost_request_id_t r) +static void __release_request_id_span_chan(int span, int chan, const char *func, int line) +{ + int id; + + zap_mutex_lock(request_mutex); + if ((id = SETUP_GRID[span][chan])) { + req_map[id] = 0; + SETUP_GRID[span][chan] = 0; + } + zap_mutex_unlock(request_mutex); +} +#define release_request_id_span_chan(s, c) __release_request_id_span_chan(s, c, __FUNCTION__, __LINE__) + +static void __release_request_id(ss7_boost_request_id_t r, const char *func, int line) { zap_mutex_lock(request_mutex); req_map[r] = 0; zap_mutex_unlock(request_mutex); } +#define release_request_id(r) __release_request_id(r, __FUNCTION__, __LINE__) -static ss7_boost_request_id_t next_request_id(void) +static ss7_boost_request_id_t last_req = 0; + +static ss7_boost_request_id_t __next_request_id(const char *func, int line) { - ss7_boost_request_id_t r = 0; - int ok = 0; + ss7_boost_request_id_t r = 0, i = 0; + int found=0; - while(!ok) { - zap_mutex_lock(request_mutex); - for (r = 1; r <= MAX_REQ_ID; r++) { - if (!req_map[r]) { - ok = 1; - req_map[r] = 1; - break; - } + zap_mutex_lock(request_mutex); + //r = ++last_req; + //while(!r || req_map[r]) { + + for (i=1; i<= MAX_REQ_ID; i++){ + r = ++last_req; + + if (r >= MAX_REQ_ID) { + r = last_req = 1; } - zap_mutex_unlock(request_mutex); - if (!ok) { - zap_sleep(5); + + if (req_map[r]) { + /* Busy find another */ + continue; + } + + req_map[r] = 1; + found=1; + break; + } + + zap_mutex_unlock(request_mutex); + + if (!found) { + return 0; + } + return r; } +#define next_request_id() __next_request_id(__FUNCTION__, __LINE__) static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event, int force) { @@ -104,7 +145,11 @@ static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event, int for 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"); + zap_log(ZAP_LOG_WARNING, "Channel %d:%d ~ %d:%d is already in use waiting for it to become available.\n", + span->channels[i].span_id, + span->channels[i].chan_id, + span->channels[i].physical_span_id, + span->channels[i].physical_chan_id); zap_mutex_unlock(signal_mutex); for (x = 0; x < 200; x++) { @@ -140,7 +185,8 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request) zap_status_t status = ZAP_FAIL; ss7_boost_request_id_t r; ss7bc_event_t event = {0}; - int sanity = 60000; + int sanity = 5000; + ss7_boost_request_status_t st; if (zap_test_flag(span, ZAP_SPAN_SUSPENDED)) { zap_log(ZAP_LOG_CRIT, "SPAN is not online.\n"); @@ -155,6 +201,11 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request) } r = next_request_id(); + if (r == 0) { + zap_log(ZAP_LOG_CRIT, "All tanks ids are busy.\n"); + *zchan = NULL; + return ZAP_FAIL; + } ss7bc_call_init(&event, caller_data->cid_num.digits, caller_data->ani.digits, r); zap_set_string(event.redirection_string, caller_data->rdnis.digits); @@ -172,11 +223,12 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request) while(zap_running() && OUTBOUND_REQUESTS[r].status == BST_WAITING) { zap_sleep(1); - if (!--sanity) { + if (--sanity <= 0) { status = ZAP_FAIL; *zchan = NULL; goto done; } + //printf("WTF %d\n", sanity); } if (OUTBOUND_REQUESTS[r].status == BST_READY && OUTBOUND_REQUESTS[r].zchan) { @@ -190,7 +242,19 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request) done: - OUTBOUND_REQUESTS[r].status = BST_FREE; + st = OUTBOUND_REQUESTS[r].status; + OUTBOUND_REQUESTS[r].status = BST_FREE; + + if (st == BST_FAIL) { + release_request_id(r); + } else if (st != BST_READY) { + ss7bc_exec_command(&ss7_boost_data->mcon, + 0, + 0, + r, + SIGBOOST_EVENT_CALL_START_NACK, + 0); + } return status; } @@ -206,20 +270,32 @@ static void handle_call_start_ack(ss7bc_connection_t *mcon, ss7bc_event_t *event zap_channel_t *zchan; OUTBOUND_REQUESTS[event->call_setup_id].event = *event; + zap_mutex_lock(request_mutex); + assert(SETUP_GRID[event->span][event->chan] == 0); + SETUP_GRID[event->span][event->chan] = event->call_setup_id; + zap_mutex_unlock(request_mutex); 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); + //release_request_id(event->call_setup_id); } else { zap_set_flag(zchan, ZAP_CHANNEL_OUTBOUND); zap_set_flag_locked(zchan, ZAP_CHANNEL_INUSE); zchan->extra_id = event->call_setup_id; + zap_log(ZAP_LOG_DEBUG, "Assign chan %d:%d (%d:%d) CSid=%d\n", zchan->span_id, zchan->chan_id, event->span+1,event->chan+1, event->call_setup_id); + zchan->sflags = 0; OUTBOUND_REQUESTS[event->call_setup_id].zchan = zchan; OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY; return; } } + + printf("WTF BAD ACK CSid=%d span=%d chan=%d\n", event->call_setup_id, event->span+1,event->chan+1); + if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event, 1))) { + printf("WTF BAD ACK2 %d:%d (%d:%d) CSid=%d xtra_id=%d out=%d state=%s\n", zchan->span_id, zchan->chan_id, event->span+1,event->chan+1, event->call_setup_id, zchan->extra_id, zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND), zap_channel_state2str(zchan->state)); + } + zap_log(ZAP_LOG_CRIT, "START ACK CANT FIND A CHAN %d:%d\n", event->span+1,event->chan+1); ss7bc_exec_command(mcon, @@ -235,39 +311,79 @@ 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; + int r = 0; if ((zchan = find_zchan(span, event, 1))) { + zap_mutex_lock(zchan->mutex); + + if (zchan->state == ZAP_CHANNEL_STATE_DOWN || zchan->state == ZAP_CHANNEL_STATE_HANGUP_COMPLETE) { + goto done; + } + + zap_set_state_r(zchan, ZAP_CHANNEL_STATE_HANGUP_COMPLETE, 0, r); - 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); + if (r) { + zap_set_sflag(zchan, SFLAG_FREE_REQ_ID); + return; + } + } + + done: + + if (zchan) { + zap_mutex_unlock(zchan->mutex); } + + release_request_id_span_chan(event->span, event->chan); } static void handle_call_start_nack(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) { - - if (event->call_setup_id) { - OUTBOUND_REQUESTS[event->call_setup_id].event = *event; - OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL; + zap_channel_t *zchan; + if (event->call_setup_id) { ss7bc_exec_command(mcon, - event->span, - event->chan, + 0, + 0, event->call_setup_id, SIGBOOST_EVENT_CALL_START_NACK_ACK, 0); - release_request_id(event->call_setup_id); + OUTBOUND_REQUESTS[event->call_setup_id].event = *event; + OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL; + return; } else { - zap_channel_t *zchan; if ((zchan = find_zchan(span, event, 1))) { + int r = 0; assert(!zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)); - zchan->caller_data.hangup_cause = event->release_cause; - zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_CANCEL); + + zap_mutex_lock(zchan->mutex); + zap_set_state_r(zchan, ZAP_CHANNEL_STATE_CANCEL, 0, r); + if (r == ZAP_STATE_CHANGE_SUCCESS) { + zchan->caller_data.hangup_cause = event->release_cause; + } + zap_mutex_unlock(zchan->mutex); + if (r) { + return; + } } } + if (zchan) { + zap_set_sflag_locked(zchan, SFLAG_SENT_FINAL_RESPONSE); + } + + + /* nobody else will do it so we have to do it ourselves */ + ss7bc_exec_command(mcon, + event->span, + event->chan, + 0, + SIGBOOST_EVENT_CALL_START_NACK_ACK, + 0); + + + } static void handle_call_stop(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) @@ -275,20 +391,38 @@ 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, 1))) { - zchan->caller_data.hangup_cause = event->release_cause; - zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_TERMINATING); - } else { - zap_log(ZAP_LOG_CRIT, "STOP CANT FIND A CHAN %d:%d\n", event->span+1,event->chan+1); - ss7bc_exec_command(mcon, - event->span, - event->chan, - 0, - SIGBOOST_EVENT_CALL_STOPPED_ACK, - 0); - } - + int r = 0; + zap_mutex_lock(zchan->mutex); + zap_set_state_r(zchan, ZAP_CHANNEL_STATE_TERMINATING, 0, r); + + if (r == ZAP_STATE_CHANGE_SUCCESS) { + zchan->caller_data.hangup_cause = event->release_cause; + } + + if (r) { + zap_set_sflag(zchan, SFLAG_FREE_REQ_ID); + } + + zap_mutex_unlock(zchan->mutex); + + if (r) { + return; + } + } /* else we have to do it ourselves.... */ + + if (zchan) { + zap_set_sflag_locked(zchan, SFLAG_SENT_FINAL_RESPONSE); + } + + ss7bc_exec_command(mcon, + event->span, + event->chan, + 0, + SIGBOOST_EVENT_CALL_STOPPED_ACK, + 0); + release_request_id_span_chan(event->span, event->chan); } static void handle_call_answer(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) @@ -296,8 +430,21 @@ 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); + int r = 0; + + if (zchan->extra_id == event->call_setup_id && zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) { + zap_mutex_lock(zchan->mutex); + if (zchan->state == ZAP_CHANNEL_STATE_DOWN && zchan->init_state != ZAP_CHANNEL_STATE_UP) { + zchan->init_state = ZAP_CHANNEL_STATE_UP; + r = 1; + } else { + zap_set_state_r(zchan, ZAP_CHANNEL_STATE_UP, 0, r); + } + zap_mutex_unlock(zchan->mutex); + } + if (!r) { + printf("WTF BAD ANSWER %d:%d (%d:%d) CSid=%d xtra_id=%d out=%d state=%s\n", zchan->span_id, zchan->chan_id, event->span+1,event->chan+1, event->call_setup_id, zchan->extra_id, zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND), zap_channel_state2str(zchan->state)); + } } else { zap_log(ZAP_LOG_CRIT, "ANSWER CANT FIND A CHAN %d:%d\n", event->span+1,event->chan+1); } @@ -314,7 +461,8 @@ static void handle_call_start(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_ if (zap_channel_open_chan(zchan) != ZAP_SUCCESS) { goto error; } - + + zchan->sflags = 0; zap_set_string(zchan->caller_data.cid_num.digits, (char *)event->calling_number_digits); zap_set_string(zchan->caller_data.cid_name, (char *)event->calling_number_digits); zap_set_string(zchan->caller_data.ani.digits, (char *)event->calling_number_digits); @@ -476,9 +624,14 @@ static __inline__ void state_advance(zap_channel_t *zchan) case ZAP_CHANNEL_STATE_DOWN: { if (zchan->extra_id) { - release_request_id((ss7_boost_request_id_t)zchan->extra_id); zchan->extra_id = 0; } + + if (zap_test_sflag(zchan, SFLAG_FREE_REQ_ID)) { + release_request_id_span_chan(zchan->physical_span_id-1, zchan->physical_chan_id-1); + } + + zchan->sflags = 0; zap_channel_done(zchan); } break; @@ -557,21 +710,27 @@ static __inline__ void state_advance(zap_channel_t *zchan) break; case ZAP_CHANNEL_STATE_HANGUP: { - 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, - 0, - SIGBOOST_EVENT_CALL_STOPPED, - zchan->caller_data.hangup_cause); + if (zap_test_sflag(zchan, SFLAG_SENT_FINAL_RESPONSE)) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); } else { - ss7bc_exec_command(mcon, - zchan->physical_span_id-1, - zchan->physical_chan_id-1, - 0, - SIGBOOST_EVENT_CALL_START_NACK, - zchan->caller_data.hangup_cause); - } + + zap_set_sflag_locked(zchan, SFLAG_SENT_FINAL_RESPONSE); + 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, + 0, + SIGBOOST_EVENT_CALL_STOPPED, + zchan->caller_data.hangup_cause); + } else { + ss7bc_exec_command(mcon, + zchan->physical_span_id-1, + zchan->physical_chan_id-1, + 0, + SIGBOOST_EVENT_CALL_START_NACK, + zchan->caller_data.hangup_cause); + } + } } break; case ZAP_CHANNEL_STATE_CANCEL: @@ -579,6 +738,7 @@ static __inline__ void state_advance(zap_channel_t *zchan) sig.event_id = ZAP_SIGEVENT_STOP; status = ss7_boost_data->signal_cb(&sig); zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); + zap_set_sflag_locked(zchan, SFLAG_SENT_FINAL_RESPONSE); ss7bc_exec_command(mcon, zchan->physical_span_id-1, zchan->physical_chan_id-1, @@ -592,12 +752,14 @@ static __inline__ void state_advance(zap_channel_t *zchan) sig.event_id = ZAP_SIGEVENT_STOP; status = ss7_boost_data->signal_cb(&sig); zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); + zap_set_sflag_locked(zchan, SFLAG_SENT_FINAL_RESPONSE); ss7bc_exec_command(mcon, zchan->physical_span_id-1, zchan->physical_chan_id-1, 0, SIGBOOST_EVENT_CALL_STOPPED_ACK, 0); + } break; default: @@ -617,9 +779,11 @@ static __inline__ void check_state(zap_span_t *span) zap_clear_flag_locked(span, ZAP_SPAN_STATE_CHANGE); for(j = 1; j <= span->chan_count; j++) { if (zap_test_flag((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE)) { - zap_clear_flag_locked((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE); + zap_mutex_lock(span->channels[j].mutex); + zap_clear_flag((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE); state_advance(&span->channels[j]); zap_channel_complete_state(&span->channels[j]); + zap_mutex_unlock(span->channels[j].mutex); } } } @@ -631,7 +795,7 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj) zap_span_t *span = (zap_span_t *) obj; zap_ss7_boost_data_t *ss7_boost_data = span->signal_data; ss7bc_connection_t *mcon, *pcon; - uint32_t ms = 10, too_long = 60000; + uint32_t ms = 10;//, too_long = 60000; ss7_boost_data->pcon = ss7_boost_data->mcon; @@ -657,8 +821,9 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj) mcon = &ss7_boost_data->mcon; pcon = &ss7_boost_data->pcon; - top: - + //top: + + init_outgoing_array(); ss7bc_exec_command(mcon, @@ -705,25 +870,26 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj) if (FD_ISSET(pcon->socket, &rfds)) { if ((event = ss7bc_connection_readp(pcon, i))) { parse_ss7_event(span, mcon, event); - } else goto top; + } //else goto top; } if (FD_ISSET(mcon->socket, &rfds)) { if ((event = ss7bc_connection_read(mcon, i))) { parse_ss7_event(span, mcon, event); - } else goto top; + } //else goto top; } } check_state(span); mcon->hb_elapsed += ms; - +#if 0 if (mcon->hb_elapsed >= too_long && (mcon->up || !zap_test_flag(span, ZAP_SPAN_SUSPENDED))) { zap_set_state_all(span, ZAP_CHANNEL_STATE_RESTART); zap_set_flag_locked(span, ZAP_SPAN_SUSPENDED); mcon->up = 0; zap_log(ZAP_LOG_CRIT, "Lost Heartbeat!\n"); } +#endif } @@ -758,6 +924,105 @@ zap_status_t zap_ss7_boost_start(zap_span_t *span) return zap_thread_create_detached(zap_ss7_boost_run, span); } +static zap_state_map_t boost_state_map = { + { + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {ZAP_ANY_STATE}, + {ZAP_CHANNEL_STATE_RESTART, ZAP_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_RESTART, ZAP_END}, + {ZAP_CHANNEL_STATE_DOWN, ZAP_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_DOWN, ZAP_END}, + {ZAP_CHANNEL_STATE_PROGRESS_MEDIA, ZAP_CHANNEL_STATE_PROGRESS, ZAP_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_PROGRESS_MEDIA, ZAP_CHANNEL_STATE_PROGRESS, ZAP_END}, + {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_TERMINATING, ZAP_CHANNEL_STATE_UP, ZAP_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_TERMINATING, ZAP_END}, + {ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_END}, + {ZAP_CHANNEL_STATE_DOWN, ZAP_END}, + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_UP, ZAP_END}, + {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_TERMINATING, ZAP_END} + }, + + /****************************************/ + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {ZAP_ANY_STATE}, + {ZAP_CHANNEL_STATE_RESTART, ZAP_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_RESTART, ZAP_END}, + {ZAP_CHANNEL_STATE_DOWN, ZAP_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_DOWN, ZAP_END}, + {ZAP_CHANNEL_STATE_RING, ZAP_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_RING, ZAP_END}, + {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_CANCEL, ZAP_CHANNEL_STATE_PROGRESS, ZAP_CHANNEL_STATE_PROGRESS_MEDIA, ZAP_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_TERMINATING, ZAP_END}, + {ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_END}, + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_CANCEL, ZAP_CHANNEL_STATE_HANGUP_COMPLETE, ZAP_CHANNEL_STATE_TERMINATING, ZAP_END}, + {ZAP_CHANNEL_STATE_DOWN, ZAP_END}, + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_PROGRESS, ZAP_CHANNEL_STATE_PROGRESS_MEDIA, ZAP_END}, + {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_CANCEL, ZAP_CHANNEL_STATE_UP, ZAP_END}, + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {ZAP_CHANNEL_STATE_UP, ZAP_END}, + {ZAP_CHANNEL_STATE_HANGUP, ZAP_CHANNEL_STATE_TERMINATING, ZAP_END}, + }, + + + } +}; + zap_status_t zap_ss7_boost_configure_span(zap_span_t *span, const char *local_ip, int local_port, const char *remote_ip, int remote_port, @@ -778,11 +1043,12 @@ zap_status_t zap_ss7_boost_configure_span(zap_span_t *span, zap_set_string(ss7_boost_data->mcon.cfg.remote_ip, remote_ip); ss7_boost_data->mcon.cfg.remote_port = remote_port; ss7_boost_data->signal_cb = sig_cb; - + span->signal_data = ss7_boost_data; span->signal_type = ZAP_SIGTYPE_SS7BOOST; span->outgoing_call = ss7_boost_outgoing_call; span->channel_request = ss7_boost_channel_request; + span->state_map = &boost_state_map; zap_set_flag_locked(span, ZAP_SPAN_SUSPENDED); return ZAP_SUCCESS;