]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
boost up
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 29 Feb 2008 00:21:04 +0000 (00:21 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 29 Feb 2008 00:21:04 +0000 (00:21 +0000)
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@416 a93c3328-9c30-0410-af19-c9cd2b2d52af

libs/freetdm/Makefile.in
libs/freetdm/configure.ac
libs/freetdm/mod_openzap/mod_openzap.c
libs/freetdm/src/include/openzap.h
libs/freetdm/src/include/ss7_boost_client.h
libs/freetdm/src/include/zap_ss7_boost.h
libs/freetdm/src/include/zap_types.h
libs/freetdm/src/ss7_boost_client.c
libs/freetdm/src/zap_io.c
libs/freetdm/src/zap_ss7_boost.c
libs/freetdm/src/zap_wanpipe.c

index 50b22e5c05c71a1e0bb0712515d13213d531496a..03454e667791d774de9e8b8033d3ab9bb384af9e 100644 (file)
@@ -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 \
index cd73f2ddbadcfac938d2106f9de20150e00b329d..ffe599eb37e268f876e66b31ee68729b78583c46 100644 (file)
@@ -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"])
index 437e3204c84d78e323cced3de665a0e5e8782b1f..fcd635434e2434a8568850c5b9bea82f8c808b6c 100644 (file)
@@ -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);
 
index 4c48e2baab5f0964417ea621738fbc2b6c74c20f..67693b0c771f1c84fc47ad9eb5b83d6eb5996c88 100644 (file)
 #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);
index 079893c7de5fdc905e9729104017d66c54b35c81..c7ad5493ee928989294b24bab747117b16a6eec9 100644 (file)
@@ -44,7 +44,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
-#ifdef SS7BC_USE_SCTP
+#ifdef HAVE_NETINET_SCTP_H
 #include <netinet/sctp.h>
 #endif
 #include <arpa/inet.h>
 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
 
index 9e0d19e6558ba9736ce7cbd033f4e78ff250e5ee..e3c7901c4542a1dfed6ebdfe0891c740efdc5395 100644 (file)
 
 #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);
index 3465eca470bf6ecf7055b4da9670f30d5b04158c..d1db4ed5e1752cf87be4e2413ee1cc5ac3d28be4 100644 (file)
@@ -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)
index 058d52d3060d5ec3d4cf957cb900ddd2f9b64d77..254d10c3bf37434467b7a312046062778a915bc3 100644 (file)
@@ -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) {
index f128037ba3ff537324ba1d70f67484b3ea49dd19..0c9af51e6715b30438f74adf36f9bdb90b463503 100644 (file)
@@ -37,6 +37,7 @@
 #endif
 #include "openzap.h"
 #include "zap_isdn.h"
+#include "zap_ss7_boost.h"
 #include <stdarg.h>
 #ifdef WIN32
 #include <io.h>
@@ -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);
index bf195e1c9da109bdbe1d165f2948c86e271961f4..1c51822afee310c5dd607e6efcc95a92c77d8b96 100644 (file)
 #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;
index b89b646a148595056aaf7d8823a894efd8c3a1ac..bbeb191b4ae374629d84851411d55dc52f23ee07 100644 (file)
@@ -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));
                        }