include "logger.h" and errno.h from asterisk.h - usage shows that they
[asterisk/asterisk.git] / channels / chan_zap.c
index 9428a43..633d7b9 100644 (file)
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include <stdio.h>
-#include <string.h>
 #ifdef __NetBSD__
 #include <pthread.h>
 #include <signal.h>
 #else
 #include <sys/signal.h>
 #endif
-#include <errno.h>
-#include <stdlib.h>
-#if !defined(SOLARIS) && !defined(__FreeBSD__)
-#include <stdint.h>
-#endif
-#include <unistd.h>
 #include <sys/ioctl.h>
 #include <math.h>
 #include <ctype.h>
@@ -80,7 +72,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/lock.h"
 #include "asterisk/channel.h"
 #include "asterisk/config.h"
-#include "asterisk/logger.h"
 #include "asterisk/module.h"
 #include "asterisk/pbx.h"
 #include "asterisk/options.h"
@@ -665,6 +656,11 @@ static struct zt_pvt {
        struct zt_ss7 *ss7;
        struct isup_call *ss7call;
        char charge_number[50];
+       char gen_add_number[50];
+       unsigned char gen_add_num_plan;
+       unsigned char gen_add_nai;
+       unsigned char gen_add_pres_ind;
+       unsigned char gen_add_type;
        int transcap;
        int cic;                                                        /*!< CIC associated with channel */
        unsigned int dpc;                                               /*!< CIC's DPC */
@@ -1073,7 +1069,13 @@ static int zt_open(char *fn)
                }
        }
        bs = READ_SIZE;
-       if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) return -1;
+       if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs) == -1) {
+               ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
+               x = errno;
+               close(fd);
+               errno = x;
+               return -1;
+       }
        return fd;
 }
 
@@ -2243,6 +2245,9 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                char ss7_calling_nai;
                int calling_nai_strip;
                const char *charge_str = NULL;
+#if 0
+               const char *gen_address = NULL;
+#endif
 
                c = strchr(dest, '/');
                if (c)
@@ -2310,8 +2315,14 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
                if (charge_str)
                        isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
-
-
+               
+#if 0
+               /* Set the generic address if it is set */
+               gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
+               if (gen_address)
+                       isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
+#endif
+               
                isup_iam(p->ss7->ss7, p->ss7call);
                ast_setstate(ast, AST_STATE_DIALING);
                ss7_rel(p->ss7);
@@ -2347,7 +2358,6 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                        }
                }
 
-
                if (strlen(c) < p->stripmsd) {
                        ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
                        ast_mutex_unlock(&p->lock);
@@ -2428,6 +2438,56 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                                pridialplan = PRI_LOCAL_ISDN;
                        }
                }
+               while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
+                       switch (c[p->stripmsd]) {
+                       case 'U':
+                               pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'I':
+                               pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'N':
+                               pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'L':
+                               pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'S':
+                               pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'A':
+                               pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'R':
+                               pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
+                               break;
+                       case 'u':
+                               pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
+                               break;
+                       case 'e':
+                               pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
+                               break;
+                       case 'x':
+                               pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
+                               break;
+                       case 'f':
+                               pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
+                               break;
+                       case 'n':
+                               pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
+                               break;
+                       case 'p':
+                               pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
+                               break;
+                       case 'r':
+                               pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
+                               break;
+                       default:
+                               if (isalpha(*c))
+                                       ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", *c > 'Z' ? "NPI" : "TON", *c);
+                       }
+                       c++;
+               }
                pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
 
                ldp_strip = 0;
@@ -2447,6 +2507,58 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
                                prilocaldialplan = PRI_LOCAL_ISDN;
                        }
                }
+               if (l != NULL) {
+                       while (*l > '9' && *l != '*' && *l != '#') {
+                               switch (*l) {
+                               case 'U':
+                                       prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'I':
+                                       prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'N':
+                                       prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'L':
+                                       prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'S':
+                                       prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'A':
+                                       prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'R':
+                                       prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
+                                       break;
+                               case 'u':
+                                       prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'e':
+                                       prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'x':
+                                       prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'f':
+                                       prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'n':
+                                       prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'p':
+                                       prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
+                                       break;
+                               case 'r':
+                                       prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
+                                       break;
+                               default:
+                                       if (isalpha(*l))
+                                               ast_log(LOG_WARNING, "Unrecognized prilocaldialplan %s modifier: %c\n", *c > 'Z' ? "NPI" : "TON", *c);
+                               }
+                               l++;
+                       }
+               }
                pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
                        p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
                if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
@@ -5604,7 +5716,7 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
                                i->dsp = NULL;
                        if (i->dsp) {
                                i->dsp_features = features & ~DSP_PROGRESS_TALK;
-#ifdef HAVE_PRI
+#if defined(HAVE_PRI) || defined(HAVE_SS7)
                                /* We cannot do progress detection until receives PROGRESS message */
                                if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_SS7))) {
                                        /* Remember requested DSP features, don't treat
@@ -7163,8 +7275,10 @@ static void *do_monitor(void *data)
                /* Lock the interface list */
                ast_mutex_lock(&iflock);
                if (!pfds || (lastalloc != ifcount)) {
-                       if (pfds)
+                       if (pfds) {
                                ast_free(pfds);
+                               pfds = NULL;
+                       }
                        if (ifcount) {
                                if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
                                        ast_mutex_unlock(&iflock);
@@ -7475,7 +7589,7 @@ static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
 
 #ifdef HAVE_SS7
 
-static unsigned int parse_pointcode(char *pcstring)
+static unsigned int parse_pointcode(const char *pcstring)
 {
        unsigned int code1, code2, code3;
        int numvals;
@@ -8430,6 +8544,38 @@ static int ss7_find_cic(struct zt_ss7 *linkset, int cic)
        return winner;
 }
 
+static void ss7_handle_cqm(struct zt_ss7 *linkset, int startcic, int endcic)
+{
+       unsigned char status[32];
+       struct zt_pvt *p = NULL;
+       int i, offset;
+
+       for (i = 0; i < linkset->numchans; i++) {
+               if (linkset->pvts[i] && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))) {
+                       p = linkset->pvts[i];
+                       offset = p->cic - startcic;
+                       status[offset] = 0;
+                       if (p->locallyblocked)
+                               status[offset] |= (1 << 0) | (1 << 4);
+                       if (p->remotelyblocked)
+                               status[offset] |= (1 << 1) | (1 << 5);
+                       if (p->ss7call) {
+                               if (p->outgoing)
+                                       status[offset] |= (1 << 3);
+                               else
+                                       status[offset] |= (1 << 2);
+                       } else
+                               status[offset] |= 0x3 << 2;
+               }
+       }
+
+       if (p)
+               isup_cqr(linkset->ss7, startcic, endcic, p->dpc, status);
+       else
+               ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
+       
+}
+
 static inline void ss7_block_cics(struct zt_ss7 *linkset, int startcic, int endcic, unsigned char state[], int block)
 {
        int i;
@@ -8529,6 +8675,11 @@ static void ss7_start_call(struct zt_pvt *p, struct zt_ss7 *linkset)
                /* Clear this after we set it */
                p->charge_number[0] = 0;
        }
+       if (!ast_strlen_zero(p->gen_add_number)) {
+               pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
+               /* Clear this after we set it */
+               p->gen_add_number[0] = 0;
+       }
 
 }
 
@@ -8643,10 +8794,15 @@ static void *ss7_linkset(void *data)
                                }
                        }
 
-                       if (pollers[i].revents & POLLIN)
+                       if (pollers[i].revents & POLLIN) {
+                               ast_mutex_lock(&linkset->lock);
                                res = ss7_read(ss7, pollers[i].fd);
+                               ast_mutex_unlock(&linkset->lock);
+                       }
                        if (pollers[i].revents & POLLOUT) {
+                               ast_mutex_lock(&linkset->lock);
                                res = ss7_write(ss7, pollers[i].fd);
+                               ast_mutex_unlock(&linkset->lock);
                                if (res < 0) {
                                        ast_log(LOG_ERROR, "Error in write %s", strerror(errno));
                                }
@@ -8699,6 +8855,10 @@ static void *ss7_linkset(void *data)
                                                ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
                                                zap_queue_frame(p, &f, linkset);
                                                p->progress = 1;
+                                               if (p->dsp && p->dsp_features) {
+                                                       ast_dsp_set_features(p->dsp, p->dsp_features);
+                                                       p->dsp_features = 0;
+                                               }
                                        }
                                        break;
                                default:
@@ -8734,6 +8894,10 @@ static void *ss7_linkset(void *data)
                                isup_gra(ss7, e->grs.startcic, e->grs.endcic, p->dpc);
                                ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, NULL, 0);
                                break;
+                       case ISUP_EVENT_CQM:
+                               ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
+                               ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic);
+                               break;
                        case ISUP_EVENT_GRA:
                                ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
                                ss7_inservice(linkset, e->gra.startcic, e->gra.endcic);
@@ -8782,15 +8946,20 @@ static void *ss7_linkset(void *data)
                                        st = strchr(p->exten, '#');
                                        if (st)
                                                *st = '\0';
-                               } else
-                                       p->exten[0] = '\0';
+                                       } else
+                                               p->exten[0] = '\0';
 
-                               /* Need to fill these fields */
                                p->cid_ani[0] = '\0';
                                p->cid_name[0] = '\0';
                                p->cid_ani2 = e->iam.oli_ani2;
                                p->cid_ton = 0;
                                ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
+
+                               ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
+                               p->gen_add_type = e->iam.gen_add_type;
+                               p->gen_add_nai = e->iam.gen_add_nai;
+                               p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
+                               p->gen_add_num_plan = e->iam.gen_add_num_plan;
                                        
                                /* Set DNID */
                                if (!ast_strlen_zero(e->iam.called_party_num))
@@ -8978,6 +9147,10 @@ static void *ss7_linkset(void *data)
                                        p = linkset->pvts[chanpos];
                                        ast_mutex_lock(&p->lock);
                                        p->subs[SUB_REAL].needanswer = 1;
+                                       if (p->dsp && p->dsp_features) {
+                                               ast_dsp_set_features(p->dsp, p->dsp_features);
+                                               p->dsp_features = 0;
+                                       }
                                        zt_enable_ec(p);
                                        ast_mutex_unlock(&p->lock);
                                }
@@ -11719,7 +11892,7 @@ static int linkset_addsigchan(int sigchan)
                        return -1;
                }
 
-               ss7_add_link(link->ss7, link->fds[curfd]);
+               ss7_add_link(link->ss7, SS7_TRANSPORT_ZAP, link->fds[curfd]);
                link->numsigchans++;
 
                memset(&si, 0, sizeof(si));
@@ -12088,7 +12261,7 @@ static int build_channels(struct zt_chan_conf conf, int iscrv, const char *value
 static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int reload, int skipchannels)
 {
        struct zt_pvt *tmp;
-       char *ringc; /* temporary string for parsing the dring number. */
+       const char *ringc; /* temporary string for parsing the dring number. */
        int y;
        int found_pseudo = 0;
         char zapchan[MAX_CHANLIST_LEN] = {};
@@ -12627,9 +12800,9 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                                }
                        } else if (!strcasecmp(v->name, "pritimer")) {
 #ifdef PRI_GETSET_TIMERS
-                               char *timerc, *c;
+                               char tmp[20], *timerc, *c = tmp;
                                int timer, timeridx;
-                               c = v->value;
+                               ast_copy_string(tmp, v->value, sizeof(tmp));
                                timerc = strsep(&c, ",");
                                if (timerc) {
                                        timer = atoi(c);
@@ -13170,8 +13343,10 @@ static int zt_sendtext(struct ast_channel *c, const char *text)
                        continue;
                }
                  /* if got exception */
-               if (fds[0].revents & POLLPRI)
+               if (fds[0].revents & POLLPRI) {
+                       ast_free(mybuf);
                        return -1;
+               }
                if (!(fds[0].revents & POLLOUT)) {
                        ast_debug(1, "write fd not ready on channel %d\n", p->channel);
                        continue;