]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Support for SIGBOOST Version 103
authorDavid Yat Sin <dyatsin@sangoma.com>
Fri, 26 Feb 2010 20:57:59 +0000 (20:57 +0000)
committerDavid Yat Sin <dyatsin@sangoma.com>
Fri, 26 Feb 2010 20:57:59 +0000 (20:57 +0000)
Allows passthrough for TON and NPI on outgoing calls via sigboost

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@1041 a93c3328-9c30-0410-af19-c9cd2b2d52af

libs/openzap/mod_openzap/mod_openzap.c
libs/openzap/src/include/openzap.h
libs/openzap/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c
libs/openzap/src/ozmod/ozmod_sangoma_boost/sigboost.h
libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
libs/openzap/src/zap_io.c

index f542908f33fdff12d5d37f21751165beeb52a63b..2961cd0804239d745d95492214a2e93d134b2ea6 100644 (file)
@@ -61,7 +61,7 @@ struct span_config {
        char dial_regex[256];
        char fail_dial_regex[256];
        char hold_music[256];
-       char type[256];
+       char type[256]; 
        analog_option_t analog_options;
 };
 
@@ -133,6 +133,43 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t
 void dump_chan(zap_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
 void dump_chan_xml(zap_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
 
+static void zap_set_npi(const char *npi_string, uint8_t *target)
+{
+       if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) {
+               *target = ZAP_NPI_ISDN;
+       } else if (!strcasecmp(npi_string, "data")) {
+               *target = ZAP_NPI_DATA;
+       } else if (!strcasecmp(npi_string, "telex")) {
+               *target = ZAP_NPI_TELEX;
+       } else if (!strcasecmp(npi_string, "national")) {
+               *target = ZAP_NPI_NATIONAL;
+       } else if (!strcasecmp(npi_string, "private")) {
+               *target = ZAP_NPI_PRIVATE;
+       } else if (!strcasecmp(npi_string, "reserved")) {
+               *target = ZAP_NPI_RESERVED;
+       } else if (!strcasecmp(npi_string, "unknown")) {
+               *target = ZAP_NPI_UNKNOWN;
+       } else {
+               zap_log(ZAP_LOG_WARNING, "Invalid NPI value (%s)\n", npi_string);
+               *target = ZAP_NPI_UNKNOWN;
+       }
+}
+
+static void zap_set_ton(const char *ton_string, uint8_t *target)
+{
+       if (!strcasecmp(ton_string, "national")) {
+               *target = ZAP_TON_NATIONAL;
+       } else if (!strcasecmp(ton_string, "international")) {
+               *target = ZAP_TON_INTERNATIONAL;
+       } else if (!strcasecmp(ton_string, "local")) {
+               *target = ZAP_TON_SUBSCRIBER_NUMBER;
+       } else if (!strcasecmp(ton_string, "unknown")) {
+               *target = ZAP_TON_UNKNOWN;
+       } else {
+               zap_log(ZAP_LOG_WARNING, "Invalid TON value (%s)\n", ton_string);
+               *target = ZAP_TON_UNKNOWN;
+       }
+}
 
 static switch_core_session_t *zap_channel_get_session(zap_channel_t *channel, int32_t id)
 {
@@ -1109,7 +1146,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
        int argc = 0;
        const char *var;
 
-
        if (!outbound_profile) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n");
                return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
@@ -1196,10 +1232,17 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
        } else {
                caller_data.ani.type = outbound_profile->destination_number_ton;
        }
-       
+
        caller_data.ani.plan = outbound_profile->destination_number_numplan;
 
+       /* blindly copy data from outbound_profile. They will be overwritten 
+        * by calling zap_caller_data if needed after */
+       caller_data.cid_num.type = outbound_profile->caller_ton;
+       caller_data.cid_num.plan = outbound_profile->caller_numplan;
 
+       caller_data.rdnis.type = outbound_profile->rdnis_ton;
+       caller_data.rdnis.plan = outbound_profile->rdnis_numplan;
+       
 #if 0
        if (!zstr(outbound_profile->rdnis)) {
                zap_set_string(caller_data.rdnis.digits, outbound_profile->rdnis);
@@ -1211,6 +1254,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
        
        if (chan_id) {
                status = zap_channel_open(span_id, chan_id, &zchan);
+               zap_set_caller_data(span_id, &caller_data);
        } else {
                status = zap_channel_open_any(span_id, direction, &caller_data, &zchan);
        }
@@ -2198,6 +2242,7 @@ static switch_status_t load_config(void)
                        uint32_t to = 0;
                        int q921loglevel = -1;
                        int q931loglevel = -1;
+                       
                        // quick debug
                        //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ID: '%s', Name:'%s'\n",id,name);
 
@@ -2389,6 +2434,12 @@ static switch_status_t load_config(void)
                        zap_status_t zstatus = ZAP_FAIL;
                        const char *context = "default";
                        const char *dialplan = "XML";
+                       const char *outbound_called_ton = "unknown";
+                       const char *outbound_called_npi = "unknown";
+                       const char *outbound_calling_ton = "unknown";
+                       const char *outbound_calling_npi = "unknown";
+                       const char *outbound_rdnis_ton = "unknown";
+                       const char *outbound_rdnis_npi = "unknown";
                        uint32_t span_id = 0;
                        zap_span_t *span = NULL;
                        const char *tonegroup = NULL;
@@ -2413,8 +2464,18 @@ static switch_status_t load_config(void)
                                        remote_port = atoi(val);
                                } else if (!strcasecmp(var, "context")) {
                                        context = val;
-                               } else if (!strcasecmp(var, "dialplan")) {
-                                       dialplan = val;
+                               } else if (!strcasecmp(var, "outbound-called-ton")) {
+                                       outbound_called_ton = val;
+                               } else if (!strcasecmp(var, "outbound-called-npi")) {
+                                       outbound_called_npi = val;
+                               } else if (!strcasecmp(var, "outbound-calling-ton")) {
+                                       outbound_calling_ton = val;
+                               } else if (!strcasecmp(var, "outbound-calling-npi")) {
+                                       outbound_calling_npi = val;
+                               } else if (!strcasecmp(var, "outbound-rdnis-ton")) {
+                                       outbound_rdnis_ton = val;
+                               } else if (!strcasecmp(var, "outbound-rdnis-npi")) {
+                                       outbound_rdnis_npi = val;
                                } 
                        }
                                
@@ -2449,6 +2510,14 @@ static switch_status_t load_config(void)
                                span_id = span->span_id;
                        }
 
+                       zap_set_npi(outbound_called_npi, &span->default_caller_data.ani.plan);
+                       zap_set_npi(outbound_calling_npi, &span->default_caller_data.cid_num.plan);
+                       zap_set_npi(outbound_rdnis_npi, &span->default_caller_data.rdnis.plan);
+
+                       zap_set_ton(outbound_called_ton, &span->default_caller_data.ani.type);
+                       zap_set_ton(outbound_calling_ton, &span->default_caller_data.cid_num.type);
+                       zap_set_ton(outbound_rdnis_ton, &span->default_caller_data.rdnis.type);
+
                        if (zap_configure_span("sangoma_boost", span, on_clear_channel_signal, 
                                                                   "local_ip", local_ip,
                                                                   "local_port", &local_port,
index 2a654f2406932aa43c7bc8adffa16337b42c093c..b7e75575c8ac48abeeb424728d89697fe5efb8f4 100644 (file)
@@ -438,9 +438,24 @@ typedef enum {
        ZAP_TON_NETWORK_SPECIFIC,
        ZAP_TON_SUBSCRIBER_NUMBER,
        ZAP_TON_ABBREVIATED_NUMBER,
-       ZAP_TON_RESERVED
+       ZAP_TON_RESERVED,
+       ZAP_TON_INVALID = 255
 } zap_ton_t;
 
+/**
+ * Numbering Plan Identification (NPI)
+ */
+typedef enum {
+       ZAP_NPI_UNKNOWN = 0,
+       ZAP_NPI_ISDN = 1,
+       ZAP_NPI_DATA = 3,
+       ZAP_NPI_TELEX = 4,
+       ZAP_NPI_NATIONAL = 8,
+       ZAP_NPI_PRIVATE = 9,
+       ZAP_NPI_RESERVED = 10,
+       ZAP_NPI_INVALID = 255
+} zap_npi_t;
+
 typedef struct {
        char digits[25];
        uint8_t type;
@@ -584,6 +599,7 @@ struct zap_span {
        size_t dtmf_hangup_len;
        int suggest_chan_id;
        zap_state_map_t *state_map;
+       zap_caller_data_t default_caller_data;
        struct zap_span *next;
 };
 
@@ -700,6 +716,8 @@ OZ_DECLARE(zap_status_t) zap_span_find_by_name(const char *name, zap_span_t **sp
 OZ_DECLARE(char *) zap_api_execute(const char *type, const char *cmd);
 OZ_DECLARE(int) zap_vasprintf(char **ret, const char *fmt, va_list ap);
 
+OZ_DECLARE(void) zap_set_caller_data(uint32_t span_id, zap_caller_data_t *caller_data);
+
 ZIO_CODEC_FUNCTION(zio_slin2ulaw);
 ZIO_CODEC_FUNCTION(zio_ulaw2slin);
 ZIO_CODEC_FUNCTION(zio_slin2alaw);
index b0953f2b4d699ac6c53d1d12fcda53fc7be1170e..ae79918b425358c53c0ad7e40c7b06fefb9649c0 100644 (file)
@@ -291,6 +291,7 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
                return ZAP_FAIL;
        }
 
+       /* sangomabc_call_init (event, calling, called, setup_id) */
        sangomabc_call_init(&event, caller_data->cid_num.digits, ani, r);
        //sangoma_bc_call_init will clear the trunk_group val so we need to set it again        
        event.trunk_group=tg;
@@ -317,13 +318,22 @@ static ZIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
        }
 
        zap_set_string(event.calling_name, caller_data->cid_name);
-       zap_set_string(event.isup_in_rdnis, caller_data->rdnis.digits);
+       zap_set_string(event.rdnis.digits, caller_data->rdnis.digits);
+
        if (strlen(caller_data->rdnis.digits)) {
-                       event.isup_in_rdnis_size = strlen(caller_data->rdnis.digits)+1;
+                       event.rdnis.digits_count = strlen(caller_data->rdnis.digits)+1;
+                       event.rdnis.ton = caller_data->rdnis.type;
+                       event.rdnis.npi = caller_data->rdnis.plan;
        }
 
-       event.calling_number_screening_ind = caller_data->screen;
-       event.calling_number_presentation = caller_data->pres;
+       event.calling.screening_ind = caller_data->screen;
+       event.calling.presentation_ind = caller_data->pres;
+
+       event.calling.ton = caller_data->cid_num.type;
+       event.calling.npi = caller_data->cid_num.plan;
+
+       event.called.ton = caller_data->ani.type;
+       event.called.npi = caller_data->ani.plan;
 
        OUTBOUND_REQUESTS[r].status = BST_WAITING;
        OUTBOUND_REQUESTS[r].span = span;
@@ -728,35 +738,42 @@ static void handle_call_start(zap_span_t *span, sangomabc_connection_t *mcon, sa
        }
        
        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.cid_num.digits, (char *)event->calling.digits);
+       zap_set_string(zchan->caller_data.cid_name, (char *)event->calling.digits);
+       zap_set_string(zchan->caller_data.ani.digits, (char *)event->calling.digits);
+       zap_set_string(zchan->caller_data.dnis.digits, (char *)event->called.digits);
+       zap_set_string(zchan->caller_data.rdnis.digits, (char *)event->rdnis.digits);
+
        if (strlen(event->calling_name)) {
                zap_set_string(zchan->caller_data.cid_name, (char *)event->calling_name);
        }
-       zap_set_string(zchan->caller_data.ani.digits, (char *)event->calling_number_digits);
-       zap_set_string(zchan->caller_data.dnis.digits, (char *)event->called_number_digits);
-       if (event->isup_in_rdnis_size) {
-               char* p;
-
-               //Set value of rdnis.digis in case prot daemon is still using older style RDNIS
-               if (atoi((char *)event->isup_in_rdnis) > 0) {
-                       zap_set_string(zchan->caller_data.rdnis.digits, (char *)event->isup_in_rdnis);
-               }
 
-               p = strstr((char*)event->isup_in_rdnis,"PRI001-ANI2-");
+       zchan->caller_data.cid_num.plan = event->calling.npi;
+       zchan->caller_data.cid_num.type = event->calling.ton;
+
+       zchan->caller_data.ani.plan = event->calling.npi;
+       zchan->caller_data.ani.type = event->calling.ton;
+
+       zchan->caller_data.dnis.plan = event->called.npi;
+       zchan->caller_data.dnis.type = event->called.ton;
+
+       zchan->caller_data.rdnis.plan = event->rdnis.npi;
+       zchan->caller_data.rdnis.type = event->rdnis.ton;
+
+       zchan->caller_data.screen = event->calling.screening_ind;
+       zchan->caller_data.pres = event->calling.presentation_ind;
+
+       if (event->custom_data_size) {
+               char* p = NULL;
+
+               p = strstr((char*)event->custom_data,"PRI001-ANI2-");
                if (p!=NULL) {
                        int ani2 = 0;
                        sscanf(p, "PRI001-ANI2-%d", &ani2);
                        snprintf(zchan->caller_data.aniII, 5, "%.2d", ani2);
                }       
-               p = strstr((char*)event->isup_in_rdnis,"RDNIS-");
-               if (p!=NULL) {
-                       sscanf(p, "RDNIS-%s", &zchan->caller_data.rdnis.digits[0]);
-               }
-               
        }
-       zchan->caller_data.screen = event->calling_number_screening_ind;
-       zchan->caller_data.pres = event->calling_number_presentation;
+
        zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING);
        return;
 
index 1b90930ffed30acf241244f4efc15c57392813d2..12810695368643c77445d2b2ebe1f47703a993e2 100644 (file)
 #ifndef _SIGBOOST_H_
 #define _SIGBOOST_H_
 
-#define SIGBOOST_VERSION 101
+#define SIGBOOST_VERSION 103
 
 #include <stdint.h>
 #include <sys/time.h>
 
+#ifdef HAVE_FREETDM
+#include <freetdm.h>
+#endif
+
 enum   e_sigboost_event_id_values
 {
        SIGBOOST_EVENT_CALL_START                       = 0x80, /*128*/
@@ -30,7 +34,22 @@ enum e_sigboost_event_id_values
        SIGBOOST_EVENT_CALL_STOPPED_ACK                 = 0x86, /*134*/
        SIGBOOST_EVENT_SYSTEM_RESTART                   = 0x87, /*135*/
        SIGBOOST_EVENT_SYSTEM_RESTART_ACK               = 0x88, /*136*/
-       SIGBOOST_EVENT_CALL_PROGRESS            = 0x50, /*decimal  80*/
+       /* CALL_RELEASED is aimed to fix a race condition that became obvious
+        * when the boost socket was replaced by direct function calls
+        * and the channel hunting was moved to freetdm, the problem is
+        * we can get CALL_STOPPED msg and reply with CALL_STOPPED_ACK
+        * but the signaling module will still (in PRI) send RELEASE and
+        * wait for RELEASE_COMPLETE from the isdn network before
+        * marking the channel as available, therefore freetdm should
+        * also not mark the channel as available until CALL_RELEASED
+        * is received, for socket mode we can continue working as usual
+        * with CALL_STOPPED being the last step because the hunting is
+        * done in the signaling module.
+       *
+       * CALL_RELEASED is only used in queue mode 
+        * */
+       SIGBOOST_EVENT_CALL_RELEASED                    = 0x51, /* 81 */
+       SIGBOOST_EVENT_CALL_PROGRESS                    = 0x50, /*decimal  80*/
        /* Following IDs are ss7boost to sangoma_mgd only. */
        SIGBOOST_EVENT_HEARTBEAT                        = 0x89, /*137*/
        SIGBOOST_EVENT_INSERT_CHECK_LOOP                = 0x8a, /*138*/
@@ -91,7 +110,12 @@ enum e_sigboost_progress_flags
 #define CORE_MAX_CHAN_PER_SPAN         32
 #define MAX_PENDING_CALLS      CORE_MAX_SPANS * CORE_MAX_CHAN_PER_SPAN
 /* 0..(MAX_PENDING_CALLS-1) is range of call_setup_id below */
-#define SIZE_RDNIS     900
+
+/* Should only be used by server */
+#define MAX_CALL_SETUP_ID   0xFFFF
+
+#define SIZE_CUSTOM    900
+#define SIZE_RDNIS  SIZE_CUSTOM
 
 
 #pragma pack(1)
@@ -100,7 +124,17 @@ typedef struct
 {
        uint8_t                 capability;
        uint8_t                 uil1p;
-}t_sigboost_bearer;
+} t_sigboost_bearer;
+
+typedef struct
+{
+       uint8_t                 digits_count;
+       char                    digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
+       uint8_t                 npi;
+       uint8_t                 ton;
+       uint8_t                 screening_ind;
+       uint8_t                 presentation_ind;
+}t_sigboost_digits;
 
 typedef struct
 {
@@ -115,21 +149,30 @@ typedef struct
        uint8_t                 chan;
        uint32_t                flags;
        /* struct timeval       tv; */ 
-       uint8_t                 called_number_digits_count;
-       char                    called_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
-       uint8_t                 calling_number_digits_count; /* it's an array */
-       char                    calling_number_digits [MAX_DIALED_DIGITS + 1]; /* it's a null terminated string */
+       t_sigboost_digits called;
+       t_sigboost_digits calling;
+       t_sigboost_digits rdnis;
        /* ref. Q.931 Table 4-11 and Q.951 Section 3 */
-       uint8_t                 calling_number_screening_ind;
-       uint8_t                 calling_number_presentation;
        char                    calling_name[MAX_DIALED_DIGITS + 1];
        t_sigboost_bearer       bearer;
        uint8_t                 hunt_group;
-       uint16_t                isup_in_rdnis_size;
-       char                    isup_in_rdnis [SIZE_RDNIS]; /* it's a null terminated string */
+       uint16_t                custom_data_size;
+       char                    custom_data[SIZE_CUSTOM]; /* it's a null terminated string */
+
 } t_sigboost_callstart;
 
-#define MIN_SIZE_CALLSTART_MSG  sizeof(t_sigboost_callstart) - SIZE_RDNIS
+#define called_number_digits_count             called.digits_count
+#define called_number_digits                   called.digits
+#define calling_number_digits_count            calling.digits_count
+#define calling_number_digits                  calling.digits
+#define calling_number_screening_ind   calling.screening_ind
+#define calling_number_presentation            calling.presentation_ind
+
+#define isup_in_rdnis_size                             custom_data_size
+#define isup_in_rdnis                                  custom_data
+
+
+#define MIN_SIZE_CALLSTART_MSG  sizeof(t_sigboost_callstart) - SIZE_CUSTOM
 
 typedef struct
 {
@@ -154,10 +197,10 @@ static inline int boost_full_event(int event_id)
         switch (event_id) {
         case SIGBOOST_EVENT_CALL_START:
         case SIGBOOST_EVENT_DIGIT_IN:
-               case SIGBOOST_EVENT_CALL_PROGRESS:
+       case SIGBOOST_EVENT_CALL_PROGRESS:
                 return 1;
         default:
-                return 0;
+                break;
         }
 
         return 0;
index 190edc2a8d691410d69c79aa734b3cc6fb9b0404..59d4155d33d2b03f6af739471e0cc0c798934146 100644 (file)
@@ -687,6 +687,9 @@ static ZIO_WRITE_FUNCTION(wanpipe_write)
 
        /* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
        memset(&hdrframe, 0, sizeof(hdrframe));
+       if (*datalen == 0) {
+               return ZAP_SUCCESS;
+       }
        bsent = sangoma_writemsg_tdm(zchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (unsigned short)(*datalen),0);
 
        /* should we be checking if bsent == *datalen here? */
index 92ec4419e89b3b88d35d10770b0e72bf16129010..e0768e145ea05d9f09ab7842201a777b1f3ba0e1 100644 (file)
@@ -176,6 +176,45 @@ static void default_logger(const char *file, const char *func, int line, int lev
 
 }
 
+OZ_DECLARE(void) zap_set_caller_data(uint32_t span_id, zap_caller_data_t *caller_data)
+{
+       zap_span_t *span = NULL;
+       if (!span_id) {
+               zap_log(ZAP_LOG_CRIT, "Error: trying to set caller data, but no span id?\n");
+               return;
+       }
+
+       zap_span_find(span_id, &span);
+       if (!span) {
+       zap_log(ZAP_LOG_CRIT, "Error: trying to set caller data, but could not find span\n");
+               return;
+       }
+
+       if (caller_data->cid_num.plan == ZAP_NPI_INVALID) {
+               caller_data->cid_num.plan = span->default_caller_data.cid_num.plan;
+       }
+
+       if (caller_data->cid_num.type == ZAP_TON_INVALID) {
+               caller_data->cid_num.type = span->default_caller_data.cid_num.type;
+       }
+
+       if (caller_data->ani.plan == ZAP_NPI_INVALID) {
+               caller_data->ani.plan = span->default_caller_data.ani.plan;
+       }
+
+       if (caller_data->ani.type == ZAP_TON_INVALID) {
+               caller_data->ani.type = span->default_caller_data.ani.type;
+       }
+
+       if (caller_data->rdnis.plan == ZAP_NPI_INVALID) {
+               caller_data->rdnis.plan = span->default_caller_data.rdnis.plan;
+       }
+
+       if (caller_data->rdnis.type == ZAP_NPI_INVALID) {
+               caller_data->rdnis.type = span->default_caller_data.rdnis.type;
+       }
+}
+
 OZ_DECLARE_DATA zap_logger_t zap_log = null_logger;
 
 OZ_DECLARE(void) zap_global_set_logger(zap_logger_t logger)
@@ -967,7 +1006,9 @@ OZ_DECLARE(zap_status_t) zap_channel_open_any(uint32_t span_id, zap_direction_t
                        *zchan = NULL;
                        return ZAP_FAIL;
                }
-               
+
+               zap_set_caller_data(span_id, caller_data);
+
                if (span->channel_request && !span->suggest_chan_id) {
                        return span->channel_request(span, 0, direction, caller_data, zchan);
                }