Sat Aug 6 00:39:23 2011

Asterisk developer's documentation


callerid.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief CallerID Generation support 
00022  *
00023  * \author Mark Spencer <markster@digium.com> 
00024  */
00025 
00026 #include "asterisk.h"
00027 
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 310633 $")
00029 
00030 #include <time.h>
00031 #include <string.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <math.h>
00036 #include <ctype.h>
00037 
00038 #include "asterisk/ulaw.h"
00039 #include "asterisk/alaw.h"
00040 #include "asterisk/frame.h"
00041 #include "asterisk/channel.h"
00042 #include "asterisk/callerid.h"
00043 #include "asterisk/logger.h"
00044 #include "asterisk/fskmodem.h"
00045 #include "asterisk/options.h"
00046 #include "asterisk/utils.h"
00047 
00048 struct callerid_state {
00049    fsk_data fskd;
00050    char rawdata[256];
00051    short oldstuff[160];
00052    int oldlen;
00053    int pos;
00054    int type;
00055    int cksum;
00056    char name[64];
00057    char number[64];
00058    int flags;
00059    int sawflag;
00060    int len;
00061 
00062    int skipflag; 
00063    unsigned short crc;
00064 };
00065 
00066 
00067 float cid_dr[4], cid_di[4];
00068 float clidsb = 8000.0 / 1200.0;
00069 float sasdr, sasdi;
00070 float casdr1, casdi1, casdr2, casdi2;
00071 
00072 #define CALLERID_SPACE  2200.0      /*!< 2200 hz for "0" */
00073 #define CALLERID_MARK   1200.0      /*!< 1200 hz for "1" */
00074 #define SAS_FREQ      440.0
00075 #define CAS_FREQ1    2130.0
00076 #define CAS_FREQ2    2750.0
00077 
00078 #define AST_CALLERID_UNKNOWN  "<unknown>"
00079 
00080 static inline void gen_tones(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2)
00081 {
00082    int x;
00083    float t;
00084    for (x=0;x<len;x++) {
00085       t = *cr1 * ddr1 - *ci1 * ddi1;
00086       *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
00087       *cr1 = t;
00088       t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
00089       *cr1 *= t;
00090       *ci1 *= t;  
00091 
00092       t = *cr2 * ddr2 - *ci2 * ddi2;
00093       *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
00094       *cr2 = t;
00095       t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
00096       *cr2 *= t;
00097       *ci2 *= t;  
00098       buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
00099    }
00100 }
00101 
00102 static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
00103 {
00104    int x;
00105    float t;
00106    for (x=0;x<len;x++) {
00107       t = *cr1 * ddr1 - *ci1 * ddi1;
00108       *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
00109       *cr1 = t;
00110       t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
00111       *cr1 *= t;
00112       *ci1 *= t;  
00113       buf[x] = AST_LIN2X(*cr1 * 8192.0);
00114    }
00115 }
00116 
00117 /*! \brief Initialize stuff for inverse FFT */
00118 void callerid_init(void)
00119 {
00120    cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
00121    cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
00122    cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
00123    cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
00124    sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
00125    sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
00126    casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
00127    casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
00128    casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
00129    casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
00130 }
00131 
00132 struct callerid_state *callerid_new(int cid_signalling)
00133 {
00134    struct callerid_state *cid;
00135 
00136    if ((cid = ast_calloc(1, sizeof(*cid)))) {
00137       cid->fskd.spb = 7.0;             /* 1200 baud */
00138       /* cid->fskd.hdlc = 0; */        /* Async */
00139       cid->fskd.nbit = 8;              /* 8 bits */
00140       cid->fskd.nstop = 1.0;           /* 1 stop bit */
00141       /* cid->fskd.paridad = 0; */     /* No parity */
00142       cid->fskd.bw = 1;                /* Filter 800 Hz */
00143       if (cid_signalling == 2) {       /* v23 signalling */
00144          cid->fskd.f_mark_idx =  4; /* 1300 Hz */
00145          cid->fskd.f_space_idx = 5; /* 2100 Hz */
00146       } else {                         /* Bell 202 signalling as default */
00147          cid->fskd.f_mark_idx =  2; /* 1200 Hz */
00148          cid->fskd.f_space_idx = 3; /* 2200 Hz */
00149       }
00150       /* cid->fskd.pcola = 0; */       /* No clue */
00151       /* cid->fskd.cont = 0.0; */      /* Digital PLL reset */
00152       /* cid->fskd.x0 = 0.0; */
00153       /* cid->fskd.state = 0; */
00154       cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
00155       /* cid->pos = 0; */
00156    }
00157 
00158    return cid;
00159 }
00160 
00161 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
00162 {
00163    *flags = cid->flags;
00164    if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NAME))
00165       *name = NULL;
00166    else
00167       *name = cid->name;
00168    if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
00169       *number = NULL;
00170    else
00171       *number = cid->number;
00172 }
00173 
00174 void callerid_get_dtmf(char *cidstring, char *number, int *flags)
00175 {
00176    int i;
00177    int code;
00178 
00179    /* "Clear" the number-buffer. */
00180    number[0] = 0;
00181 
00182    if (strlen(cidstring) < 2) {
00183       ast_log(LOG_DEBUG, "No cid detected\n");
00184       *flags = CID_UNKNOWN_NUMBER;
00185       return;
00186    }
00187    
00188    /* Detect protocol and special types */
00189    if (cidstring[0] == 'B') {
00190       /* Handle special codes */
00191       code = atoi(&cidstring[1]);
00192       if (code == 0)
00193          *flags = CID_UNKNOWN_NUMBER;
00194       else if (code == 10) 
00195          *flags = CID_PRIVATE_NUMBER;
00196       else
00197          ast_log(LOG_DEBUG, "Unknown DTMF code %d\n", code);
00198    } else if (cidstring[0] == 'D' && cidstring[2] == '#') {
00199       /* .DK special code */
00200       if (cidstring[1] == '1')
00201          *flags = CID_PRIVATE_NUMBER;
00202       if (cidstring[1] == '2' || cidstring[1] == '3')
00203          *flags = CID_UNKNOWN_NUMBER;
00204    } else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
00205       /* "Standard" callerid */
00206       for (i = 1; i < strlen(cidstring); i++ ) {
00207          if (cidstring[i] == 'C' || cidstring[i] == '#')
00208             break;
00209          if (isdigit(cidstring[i]))
00210             number[i-1] = cidstring[i];
00211          else
00212             ast_log(LOG_DEBUG, "Unknown CID digit '%c'\n",
00213                cidstring[i]);
00214       }
00215       number[i-1] = 0;
00216    } else if (isdigit(cidstring[0])) {
00217       /* It begins with a digit, so we parse it as a number and hope
00218        * for the best */
00219       ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
00220          "parsing might be unreliable\n");
00221       for (i = 0; i < strlen(cidstring); i++) {
00222          if (isdigit(cidstring[i]))
00223             number[i] = cidstring[i];
00224          else
00225             break;
00226       }
00227       number[i] = 0;
00228    } else {
00229       ast_log(LOG_DEBUG, "Unknown CID protocol, start digit '%c'\n", 
00230          cidstring[0]);
00231       *flags = CID_UNKNOWN_NUMBER;
00232    }
00233 }
00234 
00235 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
00236 {
00237    int pos = 0;
00238    int saslen=2400;
00239    float cr1 = 1.0;
00240    float ci1 = 0.0;
00241    float cr2 = 1.0;
00242    float ci2 = 0.0;
00243    if (sendsas) {
00244       if (len < saslen)
00245          return -1;
00246       gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
00247       len -= saslen;
00248       pos += saslen;
00249       cr2 = cr1;
00250       ci2 = ci1;
00251    }
00252    gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
00253    return 0;
00254 }
00255 
00256 static unsigned short calc_crc(unsigned short crc, unsigned char data)
00257 {
00258    unsigned int i, j, org, dst;
00259    org = data;
00260    dst = 0;
00261 
00262    for (i=0; i < CHAR_BIT; i++) {
00263       org <<= 1;
00264       dst >>= 1;
00265       if (org & 0x100) {
00266          dst |= 0x80;
00267       }
00268    }
00269    data = (unsigned char)dst;
00270    crc ^= (unsigned int)data << (16 - CHAR_BIT);
00271    for ( j=0; j<CHAR_BIT; j++ ) {
00272       if ( crc & 0x8000U )
00273          crc = (crc << 1) ^ 0x1021U ;
00274       else
00275          crc <<= 1 ;
00276    }
00277       return crc;
00278 }
00279 
00280 int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
00281 {
00282    int mylen = len;
00283    int olen;
00284    int b = 'X';
00285    int b2 ;
00286    int res;
00287    int x;
00288    short *buf;
00289    short *obuf;
00290 
00291    if (!(buf = ast_calloc(1, 2 * len + cid->oldlen))) {
00292       return -1;
00293    }
00294 
00295    obuf = buf;
00296    memcpy(buf, cid->oldstuff, cid->oldlen);
00297    mylen += cid->oldlen/2;
00298 
00299    for (x=0;x<len;x++) 
00300       buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
00301 
00302    while (mylen >= 160) {
00303       b = b2 = 0;
00304       olen = mylen;
00305       res = fsk_serie(&cid->fskd, buf, &mylen, &b);
00306 
00307       if (mylen < 0) {
00308          ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
00309          free(obuf);
00310          return -1;
00311       }
00312 
00313       buf += (olen - mylen);
00314 
00315       if (res < 0) {
00316          ast_log(LOG_NOTICE, "fsk_serie failed\n");
00317          free(obuf);
00318          return -1;
00319       }
00320 
00321       if (res == 1) {
00322 
00323          b2 = b ;
00324          b  = b & 0x7f ;
00325 
00326          /* crc checksum calculation */
00327          if ( cid->sawflag > 1 ) {
00328             cid->crc = calc_crc(cid->crc, (unsigned char)b2);
00329          }
00330 
00331          /* Ignore invalid bytes */
00332          if (b > 0xff) {
00333             continue;
00334          }
00335 
00336          /* skip DLE if needed */
00337          if ( cid->sawflag > 0 ) {
00338             if ( cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10 ) {
00339                cid->skipflag = 1 ;
00340                continue ;
00341             }
00342          }
00343          if ( cid->skipflag == 1 ) {
00344             cid->skipflag = 0 ;
00345          }
00346 
00347          /* caller id retrieval */
00348          switch(cid->sawflag) {
00349             case 0: /* DLE */
00350                if (b == 0x10) {
00351                   cid->sawflag = 1;
00352                   cid->skipflag = 0;
00353                   cid->crc = 0;
00354                }
00355                break;
00356             case 1: /* SOH */
00357                if (b == 0x01) {
00358                   cid->sawflag = 2;
00359                }
00360                break ;
00361             case 2: /* HEADER */
00362                if (b == 0x07) {
00363                   cid->sawflag = 3;
00364                }
00365                break;
00366             case 3: /* STX */
00367                if (b == 0x02) {
00368                   cid->sawflag = 4;
00369                }
00370                break;
00371             case 4: /* SERVICE TYPE */
00372                if (b == 0x40) {
00373                   cid->sawflag = 5;
00374                }
00375                break;
00376             case 5: /* Frame Length */
00377                cid->sawflag = 6;
00378                break;   
00379             case 6: /* NUMBER TYPE */
00380                cid->sawflag = 7;
00381                cid->pos = 0;
00382                cid->rawdata[cid->pos++] = b;
00383                break;
00384             case 7:  /* NUMBER LENGTH */
00385                cid->sawflag = 8;
00386                cid->len = b;
00387                if ( (cid->len+2) >= sizeof( cid->rawdata ) ) {
00388                   ast_log(LOG_WARNING, "too long caller id string\n" ) ;
00389                   free(obuf);
00390                   return -1;
00391                }
00392                cid->rawdata[cid->pos++] = b;
00393                break;
00394             case 8:  /* Retrieve message */
00395                cid->rawdata[cid->pos++] = b;
00396                cid->len--;
00397                if (cid->len<=0) {
00398                   cid->rawdata[cid->pos] = '\0';
00399                   cid->sawflag = 9;
00400                }
00401                break;
00402             case 9:  /* ETX */
00403                cid->sawflag = 10;
00404                break;
00405             case 10: /* CRC Checksum 1 */
00406                cid->sawflag = 11;
00407                break;
00408             case 11: /* CRC Checksum 2 */
00409                cid->sawflag = 12;
00410                if ( cid->crc != 0 ) {
00411                   ast_log(LOG_WARNING, "crc checksum error\n" ) ;
00412                   free(obuf);
00413                   return -1;
00414                } 
00415                /* extract caller id data */
00416                for (x=0; x<cid->pos; ) {
00417                   switch (cid->rawdata[x++]) {
00418                   case 0x02: /* caller id  number */
00419                      cid->number[0] = '\0';
00420                      cid->name[0] = '\0';
00421                      cid->flags = 0;
00422                      res = cid->rawdata[x++];
00423                      ast_copy_string(cid->number, &cid->rawdata[x], res+1 );
00424                      x += res;
00425                      break;
00426                   case 0x21: /* additional information */
00427                      /* length */
00428                      x++; 
00429                      /* number type */
00430                                        switch (cid->rawdata[x]) { 
00431                      case 0x00: /* unknown */
00432                      case 0x01: /* international number */
00433                      case 0x02: /* domestic number */
00434                      case 0x03: /* network */
00435                      case 0x04: /* local call */
00436                      case 0x06: /* short dial number */
00437                      case 0x07: /* reserved */
00438                      default:   /* reserved */
00439                         if (option_debug > 1)
00440                            ast_log(LOG_DEBUG, "cid info:#1=%X\n", cid->rawdata[x]);
00441                         break ;
00442                      }
00443                      x++; 
00444                      /* numbering plan octed 4 */
00445                      x++; 
00446                      /* numbering plan octed 5 */
00447                      switch (cid->rawdata[x]) { 
00448                      case 0x00: /* unknown */
00449                      case 0x01: /* recommendation E.164 ISDN */
00450                      case 0x03: /* recommendation X.121 */
00451                      case 0x04: /* telex dial plan */
00452                      case 0x08: /* domestic dial plan */
00453                      case 0x09: /* private dial plan */
00454                      case 0x05: /* reserved */
00455                      default:   /* reserved */
00456                         if (option_debug > 1)
00457                            ast_log(LOG_DEBUG, "cid info:#2=%X\n", cid->rawdata[x]);
00458                         break ;
00459                      }
00460                      x++; 
00461                      break ;
00462                   case 0x04: /* no callerid reason */
00463                      /* length */
00464                      x++; 
00465                      /* no callerid reason code */
00466                      switch (cid->rawdata[x]) {
00467                      case 'P': /* caller id denied by user */
00468                      case 'O': /* service not available */
00469                      case 'C': /* pay phone */
00470                      case 'S': /* service congested */
00471                                     cid->flags |= CID_UNKNOWN_NUMBER;
00472                         if (option_debug > 1)
00473                            ast_log(LOG_DEBUG, "no cid reason:%c\n",cid->rawdata[x]);
00474                         break ;
00475                      }
00476                      x++; 
00477                      break ;
00478                   case 0x09: /* dialed number */
00479                      /* length */
00480                      res = cid->rawdata[x++];
00481                      /* dialed number */
00482                      x += res;
00483                      break ;
00484                   case 0x22: /* dialed number additional information */
00485                      /* length */
00486                      x++;
00487                      /* number type */
00488                      switch (cid->rawdata[x]) {
00489                      case 0x00: /* unknown */
00490                      case 0x01: /* international number */
00491                      case 0x02: /* domestic number */
00492                      case 0x03: /* network */
00493                      case 0x04: /* local call */
00494                      case 0x06: /* short dial number */
00495                      case 0x07: /* reserved */
00496                      default:   /* reserved */
00497                         if (option_debug > 1)
00498                            ast_log(LOG_NOTICE, "did info:#1=%X\n", cid->rawdata[x]);
00499                         break ;
00500                      }
00501                      x++;
00502                      /* numbering plan octed 4 */
00503                      x++;
00504                                        /* numbering plan octed 5 */
00505                      switch (cid->rawdata[x]) {
00506                      case 0x00: /* unknown */
00507                      case 0x01: /* recommendation E.164 ISDN */
00508                      case 0x03: /* recommendation X.121 */
00509                      case 0x04: /* telex dial plan */
00510                      case 0x08: /* domestic dial plan */
00511                      case 0x09: /* private dial plan */
00512                      case 0x05: /* reserved */
00513                      default:   /* reserved */
00514                         if (option_debug > 1)
00515                            ast_log(LOG_DEBUG, "did info:#2=%X\n", cid->rawdata[x]);
00516                         break ;
00517                      }
00518                      x++;
00519                      break ;
00520                   }
00521                }
00522                free(obuf);
00523                return 1;
00524                break;
00525             default:
00526                ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag);
00527          }
00528       }
00529    }
00530    if (mylen) {
00531       memcpy(cid->oldstuff, buf, mylen * 2);
00532       cid->oldlen = mylen * 2;
00533    } else
00534       cid->oldlen = 0;
00535    free(obuf);
00536    return 0;
00537 }
00538 
00539 
00540 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
00541 {
00542    int mylen = len;
00543    int olen;
00544    int b = 'X';
00545    int res;
00546    int x;
00547    short *buf;
00548    short *obuf;
00549 
00550    if (!(buf = ast_calloc(1, 2 * len + cid->oldlen))) {
00551       return -1;
00552    }
00553 
00554    obuf = buf;
00555    memcpy(buf, cid->oldstuff, cid->oldlen);
00556    mylen += cid->oldlen/2;
00557 
00558    for (x=0;x<len;x++) 
00559       buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
00560    while(mylen >= 160) {
00561       olen = mylen;
00562       res = fsk_serie(&cid->fskd, buf, &mylen, &b);
00563       if (mylen < 0) {
00564          ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
00565          free(obuf);
00566          return -1;
00567       }
00568       buf += (olen - mylen);
00569       if (res < 0) {
00570          ast_log(LOG_NOTICE, "fsk_serie failed\n");
00571          free(obuf);
00572          return -1;
00573       }
00574       if (res == 1) {
00575          if (b > 0xff) {
00576             if (cid->sawflag != 5) {
00577                /* Ignore invalid bytes */
00578                continue;
00579             }
00580             /*
00581              * We can tollerate an error on the checksum character since the
00582              * checksum character is the last character in the message and
00583              * it validates the message.
00584              *
00585              * Remove character error flags.
00586              * Bit 8 : Parity error
00587              * Bit 9 : Framing error
00588              */
00589             b &= 0xff;
00590          }
00591          switch(cid->sawflag) {
00592          case 0: /* Look for flag */
00593             if (b == 'U')
00594                cid->sawflag = 2;
00595             break;
00596          case 2: /* Get lead-in */
00597             if ((b == 0x04) || (b == 0x80)) {
00598                cid->type = b;
00599                cid->sawflag = 3;
00600                cid->cksum = b;
00601             }
00602             break;
00603          case 3:  /* Get length */
00604             /* Not a lead in.  We're ready  */
00605             cid->sawflag = 4;
00606             cid->len = b;
00607             cid->pos = 0;
00608             cid->cksum += b;
00609             break;
00610          case 4: /* Retrieve message */
00611             if (cid->pos >= 128) {
00612                ast_log(LOG_WARNING, "Caller ID too long???\n");
00613                free(obuf);
00614                return -1;
00615             }
00616             cid->rawdata[cid->pos++] = b;
00617             cid->len--;
00618             cid->cksum += b;
00619             if (!cid->len) {
00620                cid->rawdata[cid->pos] = '\0';
00621                cid->sawflag = 5;
00622             }
00623             break;
00624          case 5: /* Check checksum */
00625             if (b != (256 - (cid->cksum & 0xff))) {
00626                ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
00627                /* Try again */
00628                cid->sawflag = 0;
00629                break;
00630             }
00631       
00632             cid->number[0] = '\0';
00633             cid->name[0] = '\0';
00634             /* If we get this far we're fine.  */
00635             if (cid->type == 0x80) {
00636                /* MDMF */
00637                /* Go through each element and process */
00638                for (x=0;x< cid->pos;) {
00639                   switch(cid->rawdata[x++]) {
00640                   case 1:
00641                      /* Date */
00642                      break;
00643                   case 2: /* Number */
00644                   case 3: /* Number (for Zebble) */
00645                   case 4: /* Number */
00646                      res = cid->rawdata[x];
00647                      if (res > 32) {
00648                         ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
00649                         res = 32; 
00650                      }
00651                      if (ast_strlen_zero(cid->number)) {
00652                         memcpy(cid->number, cid->rawdata + x + 1, res);
00653                         /* Null terminate */
00654                         cid->number[res] = '\0';
00655                      }
00656                      break;
00657                   case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
00658                      break;
00659                   case 7: /* Name */
00660                   case 8: /* Name */
00661                      res = cid->rawdata[x];
00662                      if (res > 32) {
00663                         ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
00664                         res = 32; 
00665                      }
00666                      memcpy(cid->name, cid->rawdata + x + 1, res);
00667                      cid->name[res] = '\0';
00668                      break;
00669                   case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting  */
00670                   case 19: /* UK: Network message system status (Number of messages waiting) */
00671                   case 22: /* Something French */
00672                      break;
00673                   default:
00674                      ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
00675                   }
00676                   res = cid->rawdata[x];
00677                   if (0 > res){  /* Negative offset in the CID Spill */
00678                      ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
00679                      /* Try again */
00680                      cid->sawflag = 0;
00681                      break;   /* Exit the loop */
00682                   }
00683                   x += cid->rawdata[x];
00684                   x++;
00685                }
00686             } else {
00687                /* SDMF */
00688                ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
00689             }
00690             /* Update flags */
00691             cid->flags = 0;
00692             if (!strcmp(cid->number, "P")) {
00693                strcpy(cid->number, "");
00694                cid->flags |= CID_PRIVATE_NUMBER;
00695             } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
00696                strcpy(cid->number, "");
00697                cid->flags |= CID_UNKNOWN_NUMBER;
00698             }
00699             if (!strcmp(cid->name, "P")) {
00700                strcpy(cid->name, "");
00701                cid->flags |= CID_PRIVATE_NAME;
00702             } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
00703                strcpy(cid->name, "");
00704                cid->flags |= CID_UNKNOWN_NAME;
00705             }
00706             free(obuf);
00707             return 1;
00708             break;
00709          default:
00710             ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
00711          }
00712       }
00713    }
00714    if (mylen) {
00715       memcpy(cid->oldstuff, buf, mylen * 2);
00716       cid->oldlen = mylen * 2;
00717    } else
00718       cid->oldlen = 0;
00719    free(obuf);
00720    return 0;
00721 }
00722 
00723 void callerid_free(struct callerid_state *cid)
00724 {
00725    free(cid);
00726 }
00727 
00728 static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
00729 {
00730    time_t t;
00731    struct tm tm;
00732    char *ptr;
00733    int res;
00734    int i,x;
00735    /* Get the time */
00736    time(&t);
00737    ast_localtime(&t, &tm, NULL);
00738    
00739    ptr = msg;
00740    
00741    /* Format time and message header */
00742    res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
00743             tm.tm_mday, tm.tm_hour, tm.tm_min);
00744    size -= res;
00745    ptr += res;
00746    if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
00747       /* Indicate number not known */
00748       res = snprintf(ptr, size, "\004\001O");
00749       size -= res;
00750       ptr += res;
00751    } else if (flags & CID_PRIVATE_NUMBER) {
00752       /* Indicate number is private */
00753       res = snprintf(ptr, size, "\004\001P");
00754       size -= res;
00755       ptr += res;
00756    } else {
00757       /* Send up to 16 digits of number MAX */
00758       i = strlen(number);
00759       if (i > 16) i = 16;
00760       res = snprintf(ptr, size, "\002%c", i);
00761       size -= res;
00762       ptr += res;
00763       for (x = 0; x < i; x++)
00764          ptr[x] = number[x];
00765       ptr[i] = '\0';
00766       ptr += i;
00767       size -= i;
00768    }
00769 
00770    if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
00771       /* Indicate name not known */
00772       res = snprintf(ptr, size, "\010\001O");
00773       size -= res;
00774       ptr += res;
00775    } else if (flags & CID_PRIVATE_NAME) {
00776       /* Indicate name is private */
00777       res = snprintf(ptr, size, "\010\001P");
00778       size -= res;
00779       ptr += res;
00780    } else {
00781       /* Send up to 16 digits of name MAX */
00782       i = strlen(name);
00783       if (i > 16) i = 16;
00784       res = snprintf(ptr, size, "\007%c", i);
00785       size -= res;
00786       ptr += res;
00787       for (x=0;x<i;x++)
00788          ptr[x] = name[x];
00789       ptr[i] = '\0';
00790       ptr += i;
00791       size -= i;
00792    }
00793    return (ptr - msg);
00794    
00795 }
00796 
00797 int ast_callerid_vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
00798 {
00799    unsigned char msg[256];
00800    int len=0;
00801    int sum;
00802    int x;
00803    int bytes = 0;
00804    float cr = 1.0;
00805    float ci = 0.0;
00806    float scont = 0.0;
00807    if (mdmf) {
00808       /* MDMF Message waiting */
00809       msg[len++] = 0x82;
00810       /* Length is 3 */
00811       msg[len++] = 3;
00812       /* IE is "Message Waiting Parameter" */
00813       msg[len++] = 0xb;
00814       /* Length of IE is one */
00815       msg[len++] = 1;
00816       /* Active or not */
00817       if (active)
00818          msg[len++] = 0xff;
00819       else
00820          msg[len++] = 0x00;
00821    } else {
00822       /* SDMF Message waiting */
00823       msg[len++] = 0x6;
00824       /* Length is 3 */
00825       msg[len++] = 3;
00826       if (active) {
00827          msg[len++] = 0x42;
00828          msg[len++] = 0x42;
00829          msg[len++] = 0x42;
00830       } else {
00831          msg[len++] = 0x6f;
00832          msg[len++] = 0x6f;
00833          msg[len++] = 0x6f;
00834       }
00835    }
00836    sum = 0;
00837    for (x=0; x<len; x++)
00838       sum += msg[x];
00839    sum = (256 - (sum & 255));
00840    msg[len++] = sum;
00841    /* Wait a half a second */
00842    for (x=0; x<4000; x++)
00843       PUT_BYTE(0x7f);
00844    /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
00845    for (x=0; x<30; x++)
00846       PUT_CLID(0x55);
00847    /* Send 170ms of callerid marks */
00848    for (x=0; x<170; x++)
00849       PUT_CLID_MARKMS;
00850    for (x=0; x<len; x++) {
00851       PUT_CLID(msg[x]);
00852    }
00853    /* Send 50 more ms of marks */
00854    for (x=0; x<50; x++)
00855       PUT_CLID_MARKMS;
00856    return bytes;
00857 }
00858 
00859 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec)
00860 {
00861    int bytes=0;
00862    int x, sum;
00863    int len;
00864 
00865    /* Initial carriers (real/imaginary) */
00866    float cr = 1.0;
00867    float ci = 0.0;
00868    float scont = 0.0;
00869    char msg[256];
00870    len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
00871    if (!callwaiting) {
00872       /* Wait a half a second */
00873       for (x=0; x<4000; x++)
00874          PUT_BYTE(0x7f);
00875       /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
00876       for (x=0; x<30; x++)
00877          PUT_CLID(0x55);
00878    }
00879    /* Send 150ms of callerid marks */
00880    for (x=0; x<150; x++)
00881       PUT_CLID_MARKMS;
00882    /* Send 0x80 indicating MDMF format */
00883    PUT_CLID(0x80);
00884    /* Put length of whole message */
00885    PUT_CLID(len);
00886    sum = 0x80 + strlen(msg);
00887    /* Put each character of message and update checksum */
00888    for (x=0; x<len; x++) {
00889       PUT_CLID(msg[x]);
00890       sum += msg[x];
00891    }
00892    /* Send 2's compliment of sum */
00893    PUT_CLID(256 - (sum & 255));
00894 
00895    /* Send 50 more ms of marks */
00896    for (x=0; x<50; x++)
00897       PUT_CLID_MARKMS;
00898    
00899    return bytes;
00900 }
00901 
00902 /*! \brief Clean up phone string
00903  * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
00904  * Basically, remove anything that could be invalid in a pattern.
00905  */
00906 void ast_shrink_phone_number(char *n)
00907 {
00908    int x, y=0;
00909    int bracketed = 0;
00910 
00911    for (x=0; n[x]; x++) {
00912       switch(n[x]) {
00913       case '[':
00914          bracketed++;
00915          n[y++] = n[x];
00916          break;
00917       case ']':
00918          bracketed--;
00919          n[y++] = n[x];
00920          break;
00921       case '-':
00922          if (bracketed)
00923             n[y++] = n[x];
00924          break;
00925       case '.':
00926          if (!n[x+1])
00927             n[y++] = n[x];
00928          break;
00929       default:
00930          if (!strchr("( )", n[x]))
00931             n[y++] = n[x];
00932       }
00933    }
00934    n[y] = '\0';
00935 }
00936 
00937 /*! \brief Checks if phone number consists of valid characters 
00938    \param exten   String that needs to be checked
00939    \param valid   Valid characters in string
00940    \return 1 if valid string, 0 if string contains invalid characters
00941 */
00942 static int ast_is_valid_string(const char *exten, const char *valid)
00943 {
00944    int x;
00945 
00946    if (ast_strlen_zero(exten))
00947       return 0;
00948    for (x=0; exten[x]; x++)
00949       if (!strchr(valid, exten[x]))
00950          return 0;
00951    return 1;
00952 }
00953 
00954 /*! \brief checks if string consists only of digits and * \# and + 
00955    \return 1 if string is valid AST phone number
00956    \return 0 if not
00957 */
00958 int ast_isphonenumber(const char *n)
00959 {
00960    return ast_is_valid_string(n, "0123456789*#+");
00961 }
00962 
00963 /*! \brief checks if string consists only of digits and ( ) - * \# and + 
00964    Pre-qualifies the string for ast_shrink_phone_number()
00965    \return 1 if string is valid AST shrinkable phone number
00966    \return 0 if not
00967 */
00968 int ast_is_shrinkable_phonenumber(const char *exten)
00969 {
00970    return ast_is_valid_string(exten, "0123456789*#+()-.");
00971 }
00972 
00973 /*!
00974  * \brief Destructively parse instr for caller id information 
00975  * \return always returns 0, as the code always returns something.
00976  * \note XXX 'name' is not parsed consistently e.g. we have
00977  * input                   location        name
00978  * " foo bar " <123>       123             ' foo bar ' (with spaces around)
00979  * " foo bar "             NULL            'foo bar' (without spaces around)
00980  * The parsing of leading and trailing space/quotes should be more consistent.
00981  */
00982 int ast_callerid_parse(char *instr, char **name, char **location)
00983 {
00984    char *ns, *ne, *ls, *le;
00985 
00986    /* Try "name" <location> format or name <location> format */
00987    if ((ls = strrchr(instr, '<')) && (le = strrchr(ls, '>'))) {
00988       *ls = *le = '\0'; /* location found, trim off the brackets */
00989       *location = ls + 1;  /* and this is the result */
00990       if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
00991          *ns = *ne = '\0'; /* trim off the quotes */
00992          *name = ns + 1;      /* and this is the name */
00993       } else if (ns) {
00994          /* An opening quote was found but no closing quote was. The closing
00995           * quote may actually be after the end of the bracketed number
00996           */
00997          if (strchr(le + 1, '\"')) {
00998             *ns = '\0';
00999             *name = ns + 1;
01000             ast_trim_blanks(*name);
01001          } else {
01002             *name = NULL;
01003          }
01004       } else { /* no quotes, trim off leading and trailing spaces */
01005          *name = ast_skip_blanks(instr);
01006          ast_trim_blanks(*name);
01007       }
01008    } else { /* no valid brackets */
01009       char tmp[256];
01010 
01011       ast_copy_string(tmp, instr, sizeof(tmp));
01012       ast_shrink_phone_number(tmp);
01013       if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
01014          *name = NULL;
01015          strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
01016          *location = instr;
01017       } else { /* Assume it's just a name. */
01018          *location = NULL;
01019          if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
01020             *ns = *ne = '\0'; /* trim off the quotes */
01021             *name = ns + 1;      /* and this is the name */
01022          } else { /* no quotes, trim off leading and trailing spaces */
01023             *name = ast_skip_blanks(instr);
01024             ast_trim_blanks(*name);
01025          }
01026       }
01027    }
01028    return 0;
01029 }
01030 
01031 static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, int codec)
01032 {
01033    if (ast_strlen_zero(name))
01034       name = NULL;
01035    if (ast_strlen_zero(number))
01036       number = NULL;
01037    return callerid_generate(buf, number, name, 0, callwaiting, codec);
01038 }
01039 
01040 int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec)
01041 {
01042    return __ast_callerid_generate(buf, name, number, 0, codec);
01043 }
01044 
01045 int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec)
01046 {
01047    return __ast_callerid_generate(buf, name, number, 1, codec);
01048 }
01049 
01050 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
01051 {
01052    if (!unknown)
01053       unknown = "<unknown>";
01054    if (name && num)
01055       snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
01056    else if (name) 
01057       ast_copy_string(buf, name, bufsiz);
01058    else if (num)
01059       ast_copy_string(buf, num, bufsiz);
01060    else
01061       ast_copy_string(buf, unknown, bufsiz);
01062    return buf;
01063 }
01064 
01065 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
01066 {
01067    char *tmp;
01068    char *l = NULL, *n = NULL;
01069 
01070    tmp = ast_strdupa(buf);
01071    ast_callerid_parse(tmp, &n, &l);
01072    if (n)
01073       ast_copy_string(name, n, namelen);
01074    else
01075       name[0] = '\0';
01076    if (l) {
01077       ast_shrink_phone_number(l);
01078       ast_copy_string(num, l, numlen);
01079    } else
01080       num[0] = '\0';
01081    return 0;
01082 }
01083 
01084 /*! \brief Translation table for Caller ID Presentation settings */
01085 static struct {
01086    int val;
01087    char *name;
01088    char *description;
01089 } pres_types[] = {
01090    {  AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
01091    {  AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
01092    {  AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
01093    {  AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
01094    {  AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
01095    {  AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
01096    {  AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
01097    {  AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
01098    {  AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
01099 };
01100 
01101 /*! \brief Convert caller ID text code to value 
01102    used in config file parsing
01103    \param data text string
01104    \return value AST_PRES_ from callerid.h 
01105 */
01106 int ast_parse_caller_presentation(const char *data)
01107 {
01108    int i;
01109 
01110    if (!data) {
01111       return -1;
01112    }
01113 
01114    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
01115       if (!strcasecmp(pres_types[i].name, data))
01116          return pres_types[i].val;
01117    }
01118 
01119    return -1;
01120 }
01121 
01122 /*! \brief Convert caller ID pres value to explanatory string 
01123    \param data value (see callerid.h AST_PRES_ ) 
01124    \return string for human presentation
01125 */
01126 const char *ast_describe_caller_presentation(int data)
01127 {
01128    int i;
01129 
01130    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
01131       if (pres_types[i].val == data)
01132          return pres_types[i].description;
01133    }
01134 
01135    return "unknown";
01136 }

Generated on Sat Aug 6 00:39:23 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7