]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
expand configurability of mod_wanpipe
authorAnthony Minessale <anthony.minessale@gmail.com>
Sun, 12 Feb 2006 20:38:24 +0000 (20:38 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Sun, 12 Feb 2006 20:38:24 +0000 (20:38 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@593 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/endpoints/mod_wanpipe/mod_wanpipe.c

index 5dbfa9f0201f6436513ba01a14d8884ae1cab52d..d11969509fce8d272a7a3888309a94929f456b92 100644 (file)
@@ -75,15 +75,24 @@ typedef enum {
 static struct {
        int debug;
        int panic;
+       int bytes_per_frame;
+       char *dialplan;
+} globals;
+
+struct wanpipe_pri_span {
        int span;
        int dchan;
+       unsigned int bchans;
        int node;
        int pswitch;
-       int bytes_per_frame;
        char *dialplan;
-       struct sangoma_pri *spri;
-} globals;
+       unsigned int l1;
+       unsigned int dp;
+       struct sangoma_pri spri;
+};
 
+#define MAX_SPANS 128
+static struct wanpipe_pri_span *SPANS[MAX_SPANS];
 
 
 struct private_object {
@@ -146,6 +155,31 @@ static int str2switch(char *swtype)
        return -1;
 }
 
+
+static int str2l1(char *l1)
+{
+       if (!strcasecmp(l1, "alaw"))
+               return PRI_LAYER_1_ALAW;
+
+       return PRI_LAYER_1_ULAW;
+}
+
+static int str2dp(char *dp)
+{
+       if (!strcasecmp(dp, "international"))
+               return PRI_INTERNATIONAL_ISDN;
+       if (!strcasecmp(dp, "national"))
+               return PRI_NATIONAL_ISDN;
+       if (!strcasecmp(dp, "local"))
+               return PRI_LOCAL_ISDN;
+       if (!strcasecmp(dp, "private"))
+               return PRI_PRIVATE;             
+       if (!strcasecmp(dp, "unknown"))
+               return PRI_UNKNOWN;
+
+       return PRI_UNKNOWN;
+}
+
 static const switch_endpoint_interface wanpipe_endpoint_interface;
 
 static void set_global_dialplan(char *dialplan);
@@ -248,14 +282,13 @@ static switch_status wanpipe_on_hangup(switch_core_session *session)
        struct channel_map *chanmap;
 
        
-       chanmap = globals.spri->private;
-
        channel = switch_core_session_get_channel(session);
        assert(channel != NULL);
 
        tech_pvt = switch_core_session_get_private(session);
        assert(tech_pvt != NULL);
 
+       chanmap = tech_pvt->spri->private;
 
        sangoma_socket_close(&tech_pvt->socket);
 
@@ -318,61 +351,114 @@ static switch_status wanpipe_outgoing_channel(switch_core_session *session, swit
                if (outbound_profile) {
                        char name[128];
                        switch_caller_profile *caller_profile;
-                       
+                       struct sangoma_pri *spri;
+                       int span = 0, autospan = 0, autochan = 0;
+                       char *num, *p;
+                       int channo = 0;
+                       struct channel_map *chanmap = NULL;
+
                        caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+                       num = caller_profile->destination_number;
+                       if ((p = strchr(num, '/'))) {
+                               *p++ = '\0';
+                               if (*num != 'a') {
+                                       span = atoi(num);
+                               } else {
+                                       span = 1;
+                                       autospan = 1;
+                               }
+                               num = p;
+                               if ((p = strchr(num, '/'))) {
+                                       *p++ = '\0';
+                                       if (*num == 'a') {
+                                               autochan = 1;
+                                       } else if (*num == 'A') {
+                                               autochan = -1;
+                                       } else {
+                                               channo = atoi(num);
+                                       }
+                                       caller_profile->destination_number = p;
+                               }
+                               
+                       }
+                       
                        switch_channel_set_caller_profile(channel, caller_profile);
                        tech_pvt->caller_profile = caller_profile;
                        snprintf(name, sizeof(name), "WanPipe/%s-%04x", caller_profile->destination_number, rand() & 0xffff);
                        switch_channel_set_name(channel, name);
-                       if ((tech_pvt->call = pri_new_call(globals.spri->pri))) {
-                               struct pri_sr *sr;
-                               struct channel_map *chanmap;
-                               int channel = 0;
-                               int mtu_mru;
-                               wanpipe_tdm_api_t tdm_api;
 
-                               chanmap = globals.spri->private;
-                               for(channel = 1; channel < SANGOMA_MAX_CHAN_PER_SPAN; channel++) {
-                                       if (!chanmap->map[channel]) {
-                                               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Choosing channel %d\n", channel);
+                       do {
+                               if ((spri = &SPANS[span]->spri)) {
+                                       chanmap = spri->private;
+                                       if (channo == 0) {
+                                               if (autochan > 0) {
+                                                       for(channo = 1; channo < SANGOMA_MAX_CHAN_PER_SPAN; channo++) {
+                                                               if ((SPANS[span]->bchans & (1 << channo)) && !chanmap->map[channo]) {
+                                                                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Choosing channel %d\n", channo);
+                                                                       break;
+                                                               }
+                                                       }
+                                               } else if (autochan < 0) {
+                                                       for(channo = SANGOMA_MAX_CHAN_PER_SPAN; channo > 0; channo--) {
+                                                               if ((SPANS[span]->bchans & (1 << channo)) && !chanmap->map[channo]) {
+                                                                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Choosing channel %d\n", channo);
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+
+                                               if (channo <= 0 || channo == (SANGOMA_MAX_CHAN_PER_SPAN)) {
+                                                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Free Channels!\n");
+                                                       channo = 0;
+                                               }
+                                       }
+                                       if (channo) {
                                                break;
                                        }
                                }
-                               if (channel == (SANGOMA_MAX_CHAN_PER_SPAN)) {
-                                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Free Channels!\n");
-                                       switch_core_session_destroy(new_session);
-                    return SWITCH_STATUS_GENERR;
-                               }
+                       } while(autospan && span < MAX_SPANS && !spri && !channo);
+
+
+                       if (!spri || channo == 0 || channo == (SANGOMA_MAX_CHAN_PER_SPAN)) {
+                               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Free Channels!\n");
+                               switch_core_session_destroy(new_session);
+                               return SWITCH_STATUS_GENERR;
+                       }
+                       
+                       if (spri && (tech_pvt->call = pri_new_call(spri->pri))) {
+                               struct pri_sr *sr;
+                               int mtu_mru;
+                               wanpipe_tdm_api_t tdm_api;
 
                                sr = pri_sr_new();
-                               pri_sr_set_channel(sr, channel, 0, 0);
-                               pri_sr_set_bearer(sr, 0, PRI_LAYER_1_ULAW);
-                               pri_sr_set_called(sr, caller_profile->destination_number, PRI_NATIONAL_ISDN, 1);
+                               pri_sr_set_channel(sr, channo, 0, 0);
+                               pri_sr_set_bearer(sr, 0, SPANS[span]->l1);
+                               pri_sr_set_called(sr, caller_profile->destination_number, SPANS[span]->dp, 1);
                                pri_sr_set_caller(sr,
                                                                  caller_profile->caller_id_number,
                                                                  caller_profile->caller_id_name,
-                                                                 PRI_NATIONAL_ISDN,
+                                                                 SPANS[span]->dp,
                                                                  PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN);
                                pri_sr_set_redirecting(sr,
                                                                           caller_profile->caller_id_number,
-                                                                          PRI_NATIONAL_ISDN,
+                                                                          SPANS[span]->dp,
                                                                           PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN,
                                                                           PRI_REDIR_UNCONDITIONAL);
                                
-                               if (pri_setup(globals.spri->pri, tech_pvt->call , sr)) {
+                               if (pri_setup(spri->pri, tech_pvt->call , sr)) {
                                        switch_core_session_destroy(new_session);
                                        pri_sr_free(sr);
                                        return SWITCH_STATUS_GENERR;
                                }
-                               if ((tech_pvt->socket = sangoma_create_socket_intr(globals.spri->span, channel)) < 0) {
+                               if ((tech_pvt->socket = sangoma_create_socket_intr(spri->span, channo)) < 0) {
                                        switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't open fd!\n");
                                        switch_core_session_destroy(new_session);
                                        pri_sr_free(sr);
                     return SWITCH_STATUS_GENERR;
                                }
                                pri_sr_free(sr);
-                               chanmap->map[channel] = *new_session;
-                               tech_pvt->spri = globals.spri;
+                               chanmap->map[channo] = *new_session;
+                               tech_pvt->spri = spri;
 
                                mtu_mru = sangoma_tdm_get_usr_mtu_mru(tech_pvt->socket, &tdm_api);      
                                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "MTU is %d\n", mtu_mru);
@@ -535,12 +621,16 @@ static const switch_loadable_module_interface wanpipe_module_interface = {
 SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
 {
 
+       memset(SPANS, 0, sizeof(SPANS));
 
        if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OH OH no pool\n");
                return SWITCH_STATUS_TERM;
        }
 
+       /* start the pri's */
+       config_wanpipe(0);
+
        /* connect my internal structure to the blank pointer passed to me */
        *interface = &wanpipe_module_interface;
 
@@ -678,7 +768,7 @@ static int on_ring(struct sangoma_pri *spri, sangoma_pri_event_t event_type, pri
                        memset(tech_pvt, 0, sizeof(*tech_pvt));
                        channel = switch_core_session_get_channel(session);
                        switch_core_session_set_private(session, tech_pvt);
-                       sprintf(name, "w%dg%d", globals.span, event->ring.channel);
+                       sprintf(name, "w%dg%d", spri->span, event->ring.channel);
                        switch_channel_set_name(channel, name);
                } else {
                        switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
@@ -784,24 +874,34 @@ static void *pri_thread_run(switch_thread *thread, void *obj)
 
        spri->on_loop = check_flags;
        spri->private = &chanmap;
-       globals.spri = spri;
        sangoma_run_pri(spri);
 
        free(spri);
        return NULL;
 }
 
+static void pri_thread_launch(struct sangoma_pri *spri)
+{
+       switch_thread *thread;
+       switch_threadattr_t *thd_attr = NULL;
+       
+       switch_threadattr_create(&thd_attr, module_pool);
+       switch_threadattr_detach_set(thd_attr, 1);
+       switch_thread_create(&thread, thd_attr, pri_thread_run, spri, module_pool);
+
+}
 
 static int config_wanpipe(int reload)
 {
        switch_config cfg;
        char *var, *val;
        int count = 0;
-       struct sangoma_pri *spri;
        char *cf = "wanpipe.conf";
+       int current_span = 0;
 
        globals.bytes_per_frame = DEFAULT_BYTES_PER_FRAME;
 
+
        if (!switch_config_open_file(&cfg, cf)) {
                switch_console_printf(SWITCH_CHANNEL_CONSOLE, "open of %s failed\n", cf);
                return SWITCH_STATUS_TERM;
@@ -811,45 +911,98 @@ static int config_wanpipe(int reload)
                if (!strcasecmp(cfg.category, "settings")) {
                        if (!strcmp(var, "debug")) {
                                globals.debug = atoi(val);
-                       } else if (!strcmp(var, "span")) {
-                               globals.span = atoi(val);
-                       } else if (!strcmp(var, "dchan")) {
-                               globals.dchan = atoi(val);
-                       } else if (!strcmp(var, "node")) {
-                               globals.node = str2node(val);
-                       } else if (!strcmp(var, "switch")) {
-                               globals.pswitch = str2switch(val);
                        } else if (!strcmp(var, "bpf")) {
                                globals.bytes_per_frame = atoi(val);
-                       } else if (!strcmp(var, "dialplan")) {
-                               set_global_dialplan(val);
+                       }
+               } else if (!strcasecmp(cfg.category, "span")) {
+                       if (!strcmp(var, "span")) {
+                               current_span = atoi(val);
+                               if (current_span <= 0 || current_span > MAX_SPANS) {
+                                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid SPAN!\n");
+                                       current_span = 0;
+                                       continue;
+                               }
+                               if (!SPANS[current_span]) {
+                                       if (!(SPANS[current_span] = switch_core_alloc(module_pool, sizeof(*SPANS[current_span])))) {
+                                               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "MEMORY ERROR\n");
+                                               break;;
+                                       }
+                                       SPANS[current_span]->span = current_span;
+                               }
+                               
+                       } else {
+                               if (!current_span) {
+                                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid option %s when no span defined.\n", var);
+                                       continue;
+                               }
+                               
+                               if (!strcmp(var, "dchan")) {
+                                       SPANS[current_span]->dchan = atoi(val);
+                               } else if (!strcmp(var, "bchan")) {
+                                       char from[128];
+                                       char *to;
+                                       switch_copy_string(from, val, sizeof(from));
+                                       if ((to = strchr(from, '-'))) {
+                                               int fromi, toi, x = 0;
+                                               *to++ = '\0';
+                                               fromi = atoi(from);
+                                               toi = atoi(to);
+                                               if (fromi > 0 && toi > 0 && fromi < toi && fromi < MAX_SPANS && toi < MAX_SPANS) {
+                                                       for(x = fromi; x <= toi; x++) {
+                                                               SPANS[current_span]->bchans |= (1 << x);
+                                                       }
+                                               } else {
+                                                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid bchan range!\n");
+                                               }
+                                       } else {
+                                               int i = atoi(val);
+                                               if (i > 0 && i < 31) {
+                                                       SPANS[current_span]->bchans |= (1 << i);
+                                               } else {
+                                                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid bchan!\n");
+                                               }
+                                       }
+                               } else if (!strcmp(var, "node")) {
+                                       SPANS[current_span]->node = str2node(val);
+                               } else if (!strcmp(var, "switch")) {
+                                       SPANS[current_span]->pswitch = str2switch(val);
+                               } else if (!strcmp(var, "dp")) {
+                                       SPANS[current_span]->dp = str2dp(val);
+                               } else if (!strcmp(var, "l1")) {
+                                       SPANS[current_span]->l1 = str2l1(val);
+                               } else if (!strcmp(var, "dialplan")) {
+                                       set_global_dialplan(val);
+                               }
                        }
                }
        }
-
        switch_config_close_file(&cfg);
 
        if (!globals.dialplan) {
                set_global_dialplan("default");
        }
 
-       if ((spri = switch_core_alloc(module_pool, sizeof(*spri)))) {
-               memset(spri, 0, sizeof(*spri));
-               sangoma_init_pri(spri, globals.span, globals.dchan, 23, globals.pswitch, globals.node, globals.debug);
+       for(current_span = 1; current_span < MAX_SPANS; current_span++) {
+               if (SPANS[current_span]) {
+                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Launch span %d\n", current_span);
+                       if (!SPANS[current_span]->l1) {
+                               SPANS[current_span]->l1 = PRI_LAYER_1_ULAW;
+                       }
+                       sangoma_init_pri(&SPANS[current_span]->spri,
+                                                        current_span,
+                                                        SPANS[current_span]->dchan,
+                                                        SPANS[current_span]->pswitch,
+                                                        SPANS[current_span]->node,
+                                                        globals.debug);
+                       pri_thread_launch(&SPANS[current_span]->spri);
+               }
+       }
 
-               pri_thread_run(NULL, spri);
 
-       } else {
-               switch_console_printf(SWITCH_CHANNEL_CONSOLE, "error!\n");
-       }
 
        return count;
 
 }
 
 
-SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void)
-{
-       config_wanpipe(0);
-       return SWITCH_STATUS_TERM;
-}
+