diff --git a/libs/openzap/Makefile.in b/libs/openzap/Makefile.in index 50b22e5c05..03454e6677 100644 --- a/libs/openzap/Makefile.in +++ b/libs/openzap/Makefile.in @@ -29,7 +29,7 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -CFLAGS=@COMP_VENDOR_CFLAGS@ +CFLAGS=@COMP_VENDOR_CFLAGS@ @DEFS@ SRC=src SOURCES=\ $(SRC)/hashtable.c \ @@ -68,6 +68,7 @@ $(SRC)/isdn/5ESSStateTE.c \ $(SRC)/isdn/Q932mes.c \ $(SRC)/zap_zt.c \ $(SRC)/zap_wanpipe.c \ +$(SRC)/ss7_boost_client.c \ $(SRC)/zap_ss7_boost.c OBJS=\ @@ -107,6 +108,7 @@ $(SRC)/isdn/5ESSStateTE.o \ $(SRC)/isdn/Q932mes.o \ $(SRC)/zap_zt.o \ $(SRC)/zap_wanpipe.o \ +$(SRC)/ss7_boost_client.o \ $(SRC)/zap_ss7_boost.o HEADERS= $(SRC)/include/fsk.h \ diff --git a/libs/openzap/configure.ac b/libs/openzap/configure.ac index cd73f2ddba..ffe599eb37 100644 --- a/libs/openzap/configure.ac +++ b/libs/openzap/configure.ac @@ -44,6 +44,9 @@ sun) COMP_VENDOR_CFLAGS="-std=c99 -Wall -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes" ;; esac + +AC_CHECK_HEADERS([netinet/sctp.h]) + # Enable debugging AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug],[build with debug information])],[enable_debug="$enable_debug"],[enable_debug="yes"]) diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c index 437e3204c8..fcd635434e 100644 --- a/libs/openzap/mod_openzap/mod_openzap.c +++ b/libs/openzap/mod_openzap/mod_openzap.c @@ -33,6 +33,7 @@ #include "openzap.h" #include "zap_analog.h" #include "zap_isdn.h" +#include "zap_ss7_boost.h" #ifndef __FUNCTION__ #define __FUNCTION__ __SWITCH_FUNC__ @@ -807,7 +808,8 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi char name[128]; zap_status_t status; int direction = ZAP_TOP_DOWN; - + zap_caller_data_t caller_data = {{ 0 }}; + if (!outbound_profile) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n"); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; @@ -846,10 +848,14 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi chan_id = 0; } + zap_set_string(caller_data.ani, dest); + zap_set_string(caller_data.cid_name, outbound_profile->caller_id_name); + zap_set_string(caller_data.cid_num, outbound_profile->caller_id_number); + if (chan_id) { status = zap_channel_open(span_id, chan_id, &zchan); } else { - status = zap_channel_open_any(span_id, direction, &zchan); + status = zap_channel_open_any(span_id, direction, &caller_data, &zchan); } if (status != ZAP_SUCCESS) { @@ -875,9 +881,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi snprintf(name, sizeof(name), "OPENZAP/%s", dest); switch_channel_set_name(channel, name); - zap_set_string(zchan->caller_data.ani, dest); - zap_set_string(zchan->caller_data.cid_name, outbound_profile->caller_id_name); - zap_set_string(zchan->caller_data.cid_num, outbound_profile->caller_id_number); + zchan->caller_data = caller_data; caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); switch_channel_set_caller_profile(channel, caller_profile); tech_pvt->caller_profile = caller_profile; @@ -1535,6 +1539,7 @@ static switch_status_t load_config(void) if (!id) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n"); + continue; } span_id = atoi(id); @@ -1561,6 +1566,70 @@ static switch_status_t load_config(void) } } + if ((spans = switch_xml_child(cfg, "boost_spans"))) { + for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { + char *id = (char *) switch_xml_attr_soft(myspan, "id"); + char *context = "default"; + char *dialplan = "XML"; + uint32_t span_id = 0; + zap_span_t *span = NULL; + char *tonegroup = NULL; + char *local_ip = NULL; + int local_port = 0; + char *remote_ip = NULL; + int remote_port = 0; + + for (param = switch_xml_child(myspan, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcasecmp(var, "tonegroup")) { + tonegroup = val; + } else if (!strcasecmp(var, "local-ip")) { + local_ip = val; + } else if (!strcasecmp(var, "local-port")) { + local_port = atoi(val); + } else if (!strcasecmp(var, "remote-ip")) { + remote_ip = val; + } else if (!strcasecmp(var, "remote-port")) { + remote_port = atoi(val); + } else if (!strcasecmp(var, "context")) { + context = val; + } else if (!strcasecmp(var, "dialplan")) { + dialplan = val; + } + } + + if (!(id && local_ip && local_port && remote_ip && remote_port) ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param\n"); + continue; + } + + span_id = atoi(id); + + if (!tonegroup) { + tonegroup = "us"; + } + + if (zap_span_find(span_id, &span) != ZAP_SUCCESS) { + zap_log(ZAP_LOG_ERROR, "Error finding OpenZAP span %d\n", span_id); + continue; + } + + if (zap_ss7_boost_configure_span(span, local_ip, local_port, remote_ip, remote_port, on_isdn_signal) != ZAP_SUCCESS) { + zap_log(ZAP_LOG_ERROR, "Error starting OpenZAP span %d error: %s\n", span_id, span->last_error); + continue; + } + + SPAN_CONFIG[span->span_id].span = span; + switch_copy_string(SPAN_CONFIG[span->span_id].context, context, sizeof(SPAN_CONFIG[span->span_id].context)); + switch_copy_string(SPAN_CONFIG[span->span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span->span_id].dialplan)); + + zap_ss7_boost_start(span); + } + } + + switch_xml_free(xml); diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h index 4c48e2baab..67693b0c77 100644 --- a/libs/openzap/src/include/openzap.h +++ b/libs/openzap/src/include/openzap.h @@ -150,7 +150,9 @@ #define assert(_Expression) ((void)(_Expression)) #endif -#define ZAP_MAX_CHANNELS_SPAN 513 +#define ZAP_MAX_CHANNELS_PHYSICAL_SPAN 32 +#define ZAP_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN 16 +#define ZAP_MAX_CHANNELS_SPAN ZAP_MAX_CHANNELS_PHYSICAL_SPAN * ZAP_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN #define ZAP_MAX_SPANS_INTERFACE 33 #define GOTO_STATUS(label,st) status = st; goto label ; @@ -506,7 +508,7 @@ zap_status_t zap_span_set_event_callback(zap_span_t *span, zio_event_cb_t event_ zap_status_t zap_channel_set_event_callback(zap_channel_t *zchan, zio_event_cb_t event_callback); zap_status_t zap_channel_open(uint32_t span_id, uint32_t chan_id, zap_channel_t **zchan); zap_status_t zap_channel_open_chan(zap_channel_t *zchan); -zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, zap_channel_t **zchan); +zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, const zap_caller_data_t *caller_data, zap_channel_t **zchan); zap_status_t zap_channel_close(zap_channel_t **zchan); zap_status_t zap_channel_done(zap_channel_t *zchan); zap_status_t zap_channel_use(zap_channel_t *zchan); diff --git a/libs/openzap/src/include/ss7_boost_client.h b/libs/openzap/src/include/ss7_boost_client.h index 079893c7de..c7ad5493ee 100644 --- a/libs/openzap/src/include/ss7_boost_client.h +++ b/libs/openzap/src/include/ss7_boost_client.h @@ -44,7 +44,7 @@ #include #include #include -#ifdef SS7BC_USE_SCTP +#ifdef HAVE_NETINET_SCTP_H #include #endif #include @@ -77,13 +77,13 @@ typedef t_sigboost ss7bc_event_t; typedef uint32_t ss7bc_event_id_t; -typedef struct smg_ip_cfg +typedef struct ss7bc_ip_cfg { char local_ip[25]; int local_port; char remote_ip[25]; int remote_port; -}smg_ip_cfg_t; +}ss7bc_ip_cfg_t; struct ss7bc_connection { zap_socket_t socket; @@ -99,7 +99,7 @@ struct ss7bc_connection { unsigned int rxseq; unsigned int txwindow; unsigned int rxseq_reset; - smg_ip_cfg_t cfg; + ss7bc_ip_cfg_t cfg; }; typedef enum { @@ -111,7 +111,7 @@ typedef struct ss7bc_connection ss7bc_connection_t; /* disable nagle's algorythm */ static inline void sctp_no_nagle(int socket) { -#ifdef SS7BC_USE_SCTP +#ifdef HAVE_NETINET_SCTP_H int flag = 1; setsockopt(socket, IPPROTO_SCTP, SCTP_NODELAY, (char *) &flag, sizeof(int)); #endif @@ -123,8 +123,9 @@ 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); 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, char *calling, char *called, int setup_id); -char *ss7bc_event_id_name(uint32_t event_id); +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); +int ss7bc_exec_command(ss7bc_connection_t *mcon, int span, int chan, int id, int cmd, int cause); #endif diff --git a/libs/openzap/src/include/zap_ss7_boost.h b/libs/openzap/src/include/zap_ss7_boost.h index 9e0d19e655..e3c7901c45 100644 --- a/libs/openzap/src/include/zap_ss7_boost.h +++ b/libs/openzap/src/include/zap_ss7_boost.h @@ -33,21 +33,19 @@ #ifndef ZAP_SS7_BOOST_H #define ZAP_SS7_BOOST_H +#include "ss7_boost_client.h" #include "openzap.h" typedef enum { ZAP_SS7_BOOST_RUNNING = (1 << 0) -} zap_isdn_flag_t; +} zap_ss7_boost_flag_t; -struct zap_ss7_boost_data { - const char *local_ip; - int local_port; - const char *remote_ip; - int remote_port; +typedef struct zap_ss7_boost_data { + ss7bc_connection_t mcon; + ss7bc_connection_t pcon; zio_signal_cb_t signal_cb; uint32_t flags; -}; -typedef struct zap_ss7_boost_data zap_ss7_boost_data_t; +} zap_ss7_boost_data_t; zap_status_t zap_ss7_boost_start(zap_span_t *span); zap_status_t zap_ss7_boost_init(void); diff --git a/libs/openzap/src/include/zap_types.h b/libs/openzap/src/include/zap_types.h index 3465eca470..d1db4ed5e1 100644 --- a/libs/openzap/src/include/zap_types.h +++ b/libs/openzap/src/include/zap_types.h @@ -336,8 +336,9 @@ typedef struct zap_channel zap_channel_t; typedef struct zap_event zap_event_t; typedef struct zap_sigmsg zap_sigmsg_t; typedef struct zap_span zap_span_t; +typedef struct zap_caller_data zap_caller_data_t; -#define ZIO_CHANNEL_REQUEST_ARGS (zap_span_t *span, zap_direction_t direction, zap_channel_t **zchan) +#define ZIO_CHANNEL_REQUEST_ARGS (zap_span_t *span, zap_direction_t direction, const zap_caller_data_t *caller_data, zap_channel_t **zchan) #define ZIO_CHANNEL_OUTGOING_CALL_ARGS (zap_channel_t *zchan) #define ZIO_SPAN_POLL_EVENT_ARGS (zap_span_t *span, uint32_t ms) #define ZIO_SPAN_NEXT_EVENT_ARGS (zap_span_t *span, zap_event_t **event) diff --git a/libs/openzap/src/ss7_boost_client.c b/libs/openzap/src/ss7_boost_client.c index 058d52d306..254d10c3bf 100644 --- a/libs/openzap/src/ss7_boost_client.c +++ b/libs/openzap/src/ss7_boost_client.c @@ -43,7 +43,7 @@ extern int gethostbyname_r (__const char *__restrict __name, struct ss7bc_map { uint32_t event_id; - char *name; + const char *name; }; static struct ss7bc_map ss7bc_table[] = { @@ -72,7 +72,7 @@ static int create_conn_socket(ss7bc_connection_t *mcon, char *local_ip, int loca memset(&mcon->remote_hp, 0, sizeof(mcon->remote_hp)); memset(&mcon->local_hp, 0, sizeof(mcon->local_hp)); -#ifdef SS7BC_USE_SCTP +#ifdef HAVE_NETINET_SCTP_H mcon->socket = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); #else mcon->socket = socket(AF_INET, SOCK_DGRAM, 0); @@ -96,7 +96,7 @@ static int create_conn_socket(ss7bc_connection_t *mcon, char *local_ip, int loca memcpy((char *) &mcon->local_addr.sin_addr.s_addr, mcon->local_hp.h_addr_list[0], mcon->local_hp.h_length); mcon->local_addr.sin_port = htons(local_port); -#ifdef SS7BC_USE_SCTP +#ifdef HAVE_NETINET_SCTP_H setsockopt(mcon->socket, IPPROTO_SCTP, SCTP_NODELAY, (char *)&flag, sizeof(int)); #endif @@ -107,7 +107,7 @@ static int create_conn_socket(ss7bc_connection_t *mcon, char *local_ip, int loca close(mcon->socket); mcon->socket = -1; } else { -#ifdef SS7BC_USE_SCTP +#ifdef HAVE_NETINET_SCTP_H rc=listen(mcon->socket,100); if (rc) { close(mcon->socket); @@ -123,9 +123,11 @@ static int create_conn_socket(ss7bc_connection_t *mcon, char *local_ip, int loca int ss7bc_connection_close(ss7bc_connection_t *mcon) { - close(mcon->socket); - mcon->socket = -1; + if (mcon->socket > -1) { + close(mcon->socket); + } memset(mcon, 0, sizeof(*mcon)); + mcon->socket = -1; return 0; } @@ -136,6 +138,41 @@ int ss7bc_connection_open(ss7bc_connection_t *mcon, char *local_ip, int local_po return mcon->socket; } + +int ss7bc_exec_command(ss7bc_connection_t *mcon, int span, int chan, int id, int cmd, int cause) +{ + ss7bc_event_t oevent; + int retry = 5; + + ss7bc_event_init(&oevent, cmd, chan, span); + oevent.release_cause = cause; + + if (id >= 0) { + oevent.call_setup_id = id; + } + isup_exec_cmd_retry: + if (ss7bc_connection_write(mcon, &oevent) <= 0){ + + --retry; + if (retry <= 0) { + zap_log(ZAP_LOG_WARNING, + "Critical System Error: Failed to tx on ISUP socket: %s\n", + strerror(errno)); + return -1; + } else { + zap_log(ZAP_LOG_WARNING, + "System Warning: Failed to tx on ISUP socket: %s :retry %i\n", + strerror(errno),retry); + } + + goto isup_exec_cmd_retry; + } + + return 0; +} + + + ss7bc_event_t *ss7bc_connection_read(ss7bc_connection_t *mcon, int iteration) { unsigned int fromlen = sizeof(struct sockaddr_in); @@ -360,7 +397,7 @@ int ss7bc_connection_write(ss7bc_connection_t *mcon, ss7bc_event_t *event) return err; } -void ss7bc_call_init(ss7bc_event_t *event, char *calling, char *called, int setup_id) +void ss7bc_call_init(ss7bc_event_t *event, const char *calling, const char *called, int setup_id) { memset(event, 0, sizeof(ss7bc_event_t)); event->event_id = SIGBOOST_EVENT_CALL_START; @@ -387,10 +424,10 @@ void ss7bc_event_init(ss7bc_event_t *event, ss7bc_event_id_t event_id, int chan, event->span = span; } -char *ss7bc_event_id_name(uint32_t event_id) +const char *ss7bc_event_id_name(uint32_t event_id) { unsigned int x; - char *ret = NULL; + const char *ret = NULL; for (x = 0 ; x < sizeof(ss7bc_table)/sizeof(struct ss7bc_map); x++) { if (ss7bc_table[x].event_id == event_id) { diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c index f128037ba3..0c9af51e67 100644 --- a/libs/openzap/src/zap_io.c +++ b/libs/openzap/src/zap_io.c @@ -37,6 +37,7 @@ #endif #include "openzap.h" #include "zap_isdn.h" +#include "zap_ss7_boost.h" #include #ifdef WIN32 #include @@ -342,7 +343,7 @@ zap_status_t zap_span_close_all(void) span = &globals.spans[i]; if (zap_test_flag(span, ZAP_SPAN_CONFIGURED)) { for(j = 0; j < span->chan_count; j++) { - zap_channel_destroy(&span->channels[i]); + zap_channel_destroy(&span->channels[j]); } } } @@ -679,7 +680,7 @@ zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t sta return ok ? ZAP_SUCCESS : ZAP_FAIL; } -zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, zap_channel_t **zchan) +zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, const zap_caller_data_t *caller_data, zap_channel_t **zchan) { zap_status_t status = ZAP_FAIL; zap_channel_t *check; @@ -690,7 +691,7 @@ zap_status_t zap_channel_open_any(uint32_t span_id, zap_direction_t direction, z zap_mutex_lock(globals.mutex); if (span_id && globals.spans[span_id].channel_request) { - status = globals.spans[span_id].channel_request(&globals.spans[span_id], direction, zchan); + status = globals.spans[span_id].channel_request(&globals.spans[span_id], direction, caller_data, zchan); goto done; } @@ -1949,6 +1950,7 @@ zap_status_t zap_global_init(void) time_init(); zap_isdn_init(); + zap_ss7_boost_init(); memset(&interfaces, 0, sizeof(interfaces)); globals.interface_hash = create_hashtable(16, zap_hash_hashfromstring, zap_hash_equalkeys); diff --git a/libs/openzap/src/zap_ss7_boost.c b/libs/openzap/src/zap_ss7_boost.c index bf195e1c9d..1c51822afe 100644 --- a/libs/openzap/src/zap_ss7_boost.c +++ b/libs/openzap/src/zap_ss7_boost.c @@ -35,30 +35,493 @@ #include "ss7_boost_client.h" #include "zap_ss7_boost.h" +typedef uint16_t ss7_boost_request_id_t; + +typedef enum { + BST_FREE, + BST_WAITING, + BST_READY, + BST_FAIL +} ss7_boost_request_status_t; + +typedef struct { + ss7_boost_request_status_t status; + ss7bc_event_t event; + zap_span_t *span; + zap_channel_t *zchan; +} ss7_boost_request_t; + +static ss7_boost_request_id_t current_request = 0; + +static ss7_boost_request_t OUTBOUND_REQUESTS[ZAP_MAX_CHANNELS_SPAN] = {{ 0 }}; + +static zap_mutex_t *request_mutex = NULL; +static zap_mutex_t *signal_mutex = NULL; + +static ss7_boost_request_id_t next_request_id(void) +{ + ss7_boost_request_id_t r; + + zap_mutex_lock(request_mutex); + if (current_request == ZAP_MAX_CHANNELS_SPAN) { + current_request = 0; + } + r = current_request++; + zap_mutex_unlock(request_mutex); + + return r + 1; +} + +static zap_channel_t *find_zchan(zap_span_t *span, ss7bc_event_t *event) +{ + int i; + zap_channel_t *zchan = NULL; + + 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]; + break; + } + } + + return zchan; +} static ZIO_CHANNEL_REQUEST_FUNCTION(ss7_boost_channel_request) { + zap_ss7_boost_data_t *ss7_boost_data = span->signal_data; zap_status_t status = ZAP_SUCCESS; + ss7_boost_request_id_t r = next_request_id(); + ss7bc_event_t event = {0}; + int sanity = 60000; + + ss7bc_call_init(&event, caller_data->cid_num, caller_data->ani, r); + OUTBOUND_REQUESTS[r].status = BST_WAITING; + OUTBOUND_REQUESTS[r].span = span; + + if (ss7bc_connection_write(&ss7_boost_data->mcon, &event) <= 0) { + zap_log(ZAP_LOG_CRIT, "Failed to tx on ISUP socket [%s]\n", strerror(errno)); + status = ZAP_FAIL; + goto done; + } + + while(OUTBOUND_REQUESTS[r].status == BST_WAITING) { + zap_sleep(1); + if (!--sanity) { + status = ZAP_FAIL; + goto done; + } + } + + if (OUTBOUND_REQUESTS[r].status == BST_READY) { + *zchan = OUTBOUND_REQUESTS[r].zchan; + } + + done: + + OUTBOUND_REQUESTS[r].status = BST_FREE; + return status; } - static ZIO_CHANNEL_OUTGOING_CALL_FUNCTION(ss7_boost_outgoing_call) { zap_status_t status = ZAP_SUCCESS; - zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DIALING); return status; } +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; + + if ((zchan = find_zchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event))) { + 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); + } else { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DIALING); + OUTBOUND_REQUESTS[event->call_setup_id].zchan = zchan; + return; + } + } + + ss7bc_exec_command(mcon, + event->span, + event->chan, + event->call_setup_id, + SIGBOOST_EVENT_CALL_STOPPED, + 0); + OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL; + +} + +static void handle_call_start_nack(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; + + ss7bc_exec_command(mcon, + event->span, + event->chan, + event->call_setup_id, + SIGBOOST_EVENT_CALL_START_NACK_ACK, + 0); +} + +static void handle_call_stop(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) +{ + zap_channel_t *zchan; + + if ((zchan = find_zchan(span, event))) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_TERMINATING); + } else { + ss7bc_exec_command(mcon, + event->span, + event->chan, + 0, + SIGBOOST_EVENT_CALL_STOPPED, + 0); + } +} + +static void handle_call_answer(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) +{ + zap_channel_t *zchan; + + if ((zchan = find_zchan(span, event))) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_UP); + } else { + ss7bc_exec_command(mcon, + event->span, + event->chan, + 0, + SIGBOOST_EVENT_CALL_STOPPED, + 0); + } +} + +static void handle_call_start(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) +{ + zap_channel_t *zchan; + + if ((zchan = find_zchan(span, event))) { + ss7bc_exec_command(mcon, + event->span, + event->chan, + 0, + SIGBOOST_EVENT_CALL_START_ACK, + 0); + + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING); + } else { + ss7bc_exec_command(mcon, + event->span, + event->chan, + 0, + SIGBOOST_EVENT_CALL_START_NACK, + 0); + } +} + + +static void handle_heartbeat(ss7bc_connection_t *mcon, ss7bc_event_t *event) +{ + int err = ss7bc_connection_write(mcon, event); + + if (err <= 0) { + zap_log(ZAP_LOG_CRIT, "Failed to tx on ISUP socket [%s]: %s\n", strerror(errno)); + } + + return; +} + +static void handle_restart_ack(ss7bc_connection_t *mcon, ss7bc_event_t *event) +{ + mcon->rxseq_reset = 0; +} + +static int parse_ss7_event(zap_span_t *span, ss7bc_connection_t *mcon, ss7bc_event_t *event) +{ + zap_mutex_lock(signal_mutex); + + zap_log(ZAP_LOG_DEBUG, + "RX 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, + event->chan+1, + event->release_cause, + event->call_setup_id, + event->fseqno, + (event->called_number_digits_count ? (char *) event->called_number_digits : "N/A"), + (event->calling_number_digits_count ? (char *) event->calling_number_digits : "N/A") + ); + + + switch(event->event_id) { + + case SIGBOOST_EVENT_CALL_START: + handle_call_start(span, mcon, event); + break; + case SIGBOOST_EVENT_CALL_STOPPED: + handle_call_stop(span, mcon, event); + break; + case SIGBOOST_EVENT_CALL_START_ACK: + handle_call_start_ack(mcon, event); + break; + case SIGBOOST_EVENT_CALL_START_NACK: + handle_call_start_nack(mcon, event); + break; + case SIGBOOST_EVENT_CALL_ANSWERED: + handle_call_answer(span, mcon, event); + break; + 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); + break; + case SIGBOOST_EVENT_INSERT_CHECK_LOOP: + //handle_call_loop_start(event); + break; + case SIGBOOST_EVENT_REMOVE_CHECK_LOOP: + //handle_call_stop(event); + break; + case SIGBOOST_EVENT_SYSTEM_RESTART_ACK: + handle_restart_ack(mcon,event); + break; + case SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE: + //handle_gap_abate(event); + break; + default: + zap_log(ZAP_LOG_WARNING, "No handler implemented for [%s]\n", ss7bc_event_id_name(event->event_id)); + break; + } + + zap_mutex_unlock(signal_mutex); + + return 0; +} + +static __inline__ void state_advance(zap_channel_t *zchan) +{ + + zap_ss7_boost_data_t *ss7_boost_data = zchan->span->signal_data; + ss7bc_connection_t *mcon = &ss7_boost_data->mcon; + zap_sigmsg_t sig; + zap_status_t status; + + zap_log(ZAP_LOG_ERROR, "%d:%d STATE [%s]\n", + zchan->span_id, zchan->chan_id, zap_channel_state2str(zchan->state)); + + memset(&sig, 0, sizeof(sig)); + sig.chan_id = zchan->chan_id; + sig.span_id = zchan->span_id; + sig.channel = zchan; + + switch (zchan->state) { + case ZAP_CHANNEL_STATE_DOWN: + { + zap_channel_done(zchan); + } + break; + case ZAP_CHANNEL_STATE_PROGRESS: + { + if (zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) { + sig.event_id = ZAP_SIGEVENT_PROGRESS; + if ((status = ss7_boost_data->signal_cb(&sig) != ZAP_SUCCESS)) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); + } + } else { + //send progress + } + } + break; + case ZAP_CHANNEL_STATE_RING: + { + if (!zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) { + sig.event_id = ZAP_SIGEVENT_START; + if ((status = ss7_boost_data->signal_cb(&sig) != ZAP_SUCCESS)) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); + } + } + + } + break; + case ZAP_CHANNEL_STATE_RESTART: + { + if (zchan->last_state > ZAP_CHANNEL_STATE_HANGUP) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); + } + } + break; + case ZAP_CHANNEL_STATE_PROGRESS_MEDIA: + { + if (zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) { + sig.event_id = ZAP_SIGEVENT_PROGRESS_MEDIA; + if ((status = ss7_boost_data->signal_cb(&sig) != ZAP_SUCCESS)) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); + } + } else { + // send alerting + } + } + break; + case ZAP_CHANNEL_STATE_UP: + { + if (zap_test_flag(zchan, ZAP_CHANNEL_OUTBOUND)) { + sig.event_id = ZAP_SIGEVENT_UP; + if ((status = ss7_boost_data->signal_cb(&sig) != ZAP_SUCCESS)) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); + } + } else { + // send connect + } + } + break; + case ZAP_CHANNEL_STATE_DIALING: + { + } + break; + case ZAP_CHANNEL_STATE_HANGUP: + { + ss7bc_exec_command(mcon, + zchan->physical_span_id-1, + zchan->physical_chan_id-1, + 0, + SIGBOOST_EVENT_CALL_STOPPED, + 0); + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); + + } + break; + case ZAP_CHANNEL_STATE_TERMINATING: + { + sig.event_id = ZAP_SIGEVENT_STOP; + status = ss7_boost_data->signal_cb(&sig); + } + default: + break; + } +} + + +static __inline__ void check_state(zap_span_t *span) +{ + + + if (zap_test_flag(span, ZAP_SPAN_STATE_CHANGE)) { + uint32_t j; + for(j = 1; j <= span->chan_count; j++) { + if (zap_test_flag((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE)) { + zap_mutex_lock(signal_mutex); + state_advance(&span->channels[j]); + zap_mutex_unlock(signal_mutex); + zap_clear_flag_locked((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE); + } + } + zap_clear_flag_locked(span, ZAP_SPAN_STATE_CHANGE); + } +} + + 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; + + ss7_boost_data->pcon = ss7_boost_data->mcon; + + if (ss7bc_connection_open(&ss7_boost_data->mcon, + ss7_boost_data->mcon.cfg.local_ip, + ss7_boost_data->mcon.cfg.local_port, + ss7_boost_data->mcon.cfg.remote_ip, + ss7_boost_data->mcon.cfg.remote_port) < 0) { + zap_log(ZAP_LOG_DEBUG, "Error: Opening MCON Socket [%d] %s\n", ss7_boost_data->mcon.socket, strerror(errno)); + goto end; + } + + if (ss7bc_connection_open(&ss7_boost_data->pcon, + ss7_boost_data->pcon.cfg.local_ip, + ++ss7_boost_data->pcon.cfg.local_port, + ss7_boost_data->pcon.cfg.remote_ip, + ss7_boost_data->pcon.cfg.remote_port) < 0) { + zap_log(ZAP_LOG_DEBUG, "Error: Opening PCON Socket [%d] %s\n", ss7_boost_data->pcon.socket, strerror(errno)); + goto end; + } + + mcon = &ss7_boost_data->mcon; + pcon = &ss7_boost_data->pcon; + + mcon->rxseq_reset = 1; + + ss7bc_exec_command(mcon, + 0, + 0, + -1, + SIGBOOST_EVENT_SYSTEM_RESTART, + 0); + while (zap_running() && zap_test_flag(ss7_boost_data, ZAP_SS7_BOOST_RUNNING)) { - break; + fd_set rfds, efds; + struct timeval tv = { 0, 100000 }; + int max, activity, i = 0; + ss7bc_event_t *event = NULL; + + FD_ZERO(&rfds); + FD_ZERO(&efds); + FD_SET(mcon->socket, &rfds); + FD_SET(mcon->socket, &efds); + FD_SET(pcon->socket, &rfds); + FD_SET(pcon->socket, &efds); + + max = ((pcon->socket > mcon->socket) ? pcon->socket : mcon->socket) + 1; + + if ((activity = select(max, &rfds, NULL, &efds, &tv)) < 0) { + goto error; + } + + if (!activity) { + continue; + } + + if (FD_ISSET(pcon->socket, &efds) || FD_ISSET(mcon->socket, &efds)) { + goto error; + } + + if (FD_ISSET(pcon->socket, &rfds)) { + if ((event = ss7bc_connection_readp(pcon, i))) { + parse_ss7_event(span, pcon, event); + } + } + + if (FD_ISSET(mcon->socket, &rfds)) { + if ((event = ss7bc_connection_read(mcon, i))) { + parse_ss7_event(span, mcon, event); + } + } + + check_state(span); + } + goto end; + + error: + zap_log(ZAP_LOG_CRIT, "Socket Error!\n"); + + end: + + ss7bc_connection_close(&ss7_boost_data->mcon); + ss7bc_connection_close(&ss7_boost_data->pcon); + zap_clear_flag(ss7_boost_data, ZAP_SS7_BOOST_RUNNING); zap_log(ZAP_LOG_DEBUG, "SS7_BOOST thread ended.\n"); @@ -67,6 +530,9 @@ static void *zap_ss7_boost_run(zap_thread_t *me, void *obj) zap_status_t zap_ss7_boost_init(void) { + zap_mutex_create(&request_mutex); + zap_mutex_create(&signal_mutex); + return ZAP_SUCCESS; } @@ -84,14 +550,18 @@ zap_status_t zap_ss7_boost_configure_span(zap_span_t *span, { zap_ss7_boost_data_t *ss7_boost_data = NULL; + if (!local_ip && local_port && remote_ip && remote_port && sig_cb) { + return ZAP_FAIL; + } + ss7_boost_data = malloc(sizeof(*ss7_boost_data)); assert(ss7_boost_data); memset(ss7_boost_data, 0, sizeof(*ss7_boost_data)); - ss7_boost_data->local_ip = local_ip; - ss7_boost_data->local_port = local_port; - ss7_boost_data->remote_ip = remote_ip; - ss7_boost_data->remote_port = remote_port; + zap_set_string(ss7_boost_data->mcon.cfg.local_ip, local_ip); + ss7_boost_data->mcon.cfg.local_port = local_port; + 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; diff --git a/libs/openzap/src/zap_wanpipe.c b/libs/openzap/src/zap_wanpipe.c index b89b646a14..bbeb191b4a 100644 --- a/libs/openzap/src/zap_wanpipe.c +++ b/libs/openzap/src/zap_wanpipe.c @@ -358,13 +358,14 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, sockfd = tdmv_api_open_span_chan(spanno, x); if (sockfd != WP_INVALID_SOCKET && zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) { + wanpipe_tdm_api_t tdm_api; zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d\n", spanno, x, chan->span_id, chan->chan_id, sockfd); chan->physical_span_id = spanno; chan->physical_chan_id = x; chan->rate = 8000; if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) { - wanpipe_tdm_api_t tdm_api; + #if 1 if (type == ZAP_CHAN_TYPE_FXO) { @@ -390,8 +391,9 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE; wp_tdm_cmd_exec(chan, &tdm_api); + } - + if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO || type == ZAP_CHAN_TYPE_B) { tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_HW_CODING; wp_tdm_cmd_exec(chan, &tdm_api); if (tdm_api.wp_tdm_cmd.hw_tdm_coding) { @@ -400,6 +402,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, chan->native_codec = chan->effective_codec = ZAP_CODEC_ULAW; } } + if (!zap_strlen_zero(name)) { zap_copy_string(chan->chan_name, name, sizeof(chan->chan_name)); }