Tue Nov 16 17:07:29 2010

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: 206867 $")
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          /* Ignore invalid bytes */
00576          if (b > 0xff)
00577             continue;
00578          switch(cid->sawflag) {
00579          case 0: /* Look for flag */
00580             if (b == 'U')
00581                cid->sawflag = 2;
00582             break;
00583          case 2: /* Get lead-in */
00584             if ((b == 0x04) || (b == 0x80)) {
00585                cid->type = b;
00586                cid->sawflag = 3;
00587                cid->cksum = b;
00588             }
00589             break;
00590          case 3:  /* Get length */
00591             /* Not a lead in.  We're ready  */
00592             cid->sawflag = 4;
00593             cid->len = b;
00594             cid->pos = 0;
00595             cid->cksum += b;
00596             break;
00597          case 4: /* Retrieve message */
00598             if (cid->pos >= 128) {
00599                ast_log(LOG_WARNING, "Caller ID too long???\n");
00600                free(obuf);
00601                return -1;
00602             }
00603             cid->rawdata[cid->pos++] = b;
00604             cid->len--;
00605             cid->cksum += b;
00606             if (!cid->len) {
00607                cid->rawdata[cid->pos] = '\0';
00608                cid->sawflag = 5;
00609             }
00610             break;
00611          case 5: /* Check checksum */
00612             if (b != (256 - (cid->cksum & 0xff))) {
00613                ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
00614                /* Try again */
00615                cid->sawflag = 0;
00616                break;
00617             }
00618       
00619             cid->number[0] = '\0';
00620             cid->name[0] = '\0';
00621             /* If we get this far we're fine.  */
00622             if (cid->type == 0x80) {
00623                /* MDMF */
00624                /* Go through each element and process */
00625                for (x=0;x< cid->pos;) {
00626                   switch(cid->rawdata[x++]) {
00627                   case 1:
00628                      /* Date */
00629                      break;
00630                   case 2: /* Number */
00631                   case 3: /* Number (for Zebble) */
00632                   case 4: /* Number */
00633                      res = cid->rawdata[x];
00634                      if (res > 32) {
00635                         ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
00636                         res = 32; 
00637                      }
00638                      if (ast_strlen_zero(cid->number)) {
00639                         memcpy(cid->number, cid->rawdata + x + 1, res);
00640                         /* Null terminate */
00641                         cid->number[res] = '\0';
00642                      }
00643                      break;
00644                   case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
00645                      break;
00646                   case 7: /* Name */
00647                   case 8: /* Name */
00648                      res = cid->rawdata[x];
00649                      if (res > 32) {
00650                         ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
00651                         res = 32; 
00652                      }
00653                      memcpy(cid->name, cid->rawdata + x + 1, res);
00654                      cid->name[res] = '\0';
00655                      break;
00656                   case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting  */
00657                   case 19: /* UK: Network message system status (Number of messages waiting) */
00658                   case 22: /* Something French */
00659                      break;
00660                   default:
00661                      ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
00662                   }
00663                   res = cid->rawdata[x];
00664                   if (0 > res){  /* Negative offset in the CID Spill */
00665                      ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
00666                      /* Try again */
00667                      cid->sawflag = 0;
00668                      break;   /* Exit the loop */
00669                   }
00670                   x += cid->rawdata[x];
00671                   x++;
00672                }
00673             } else {
00674                /* SDMF */
00675                ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
00676             }
00677             /* Update flags */
00678             cid->flags = 0;
00679             if (!strcmp(cid->number, "P")) {
00680                strcpy(cid->number, "");
00681                cid->flags |= CID_PRIVATE_NUMBER;
00682             } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
00683                strcpy(cid->number, "");
00684                cid->flags |= CID_UNKNOWN_NUMBER;
00685             }
00686             if (!strcmp(cid->name, "P")) {
00687                strcpy(cid->name, "");
00688                cid->flags |= CID_PRIVATE_NAME;
00689             } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
00690                strcpy(cid->name, "");
00691                cid->flags |= CID_UNKNOWN_NAME;
00692             }
00693             free(obuf);
00694             return 1;
00695             break;
00696          default:
00697             ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
00698          }
00699       }
00700    }
00701    if (mylen) {
00702       memcpy(cid->oldstuff, buf, mylen * 2);
00703       cid->oldlen = mylen * 2;
00704    } else
00705       cid->oldlen = 0;
00706    free(obuf);
00707    return 0;
00708 }
00709 
00710 void callerid_free(struct callerid_state *cid)
00711 {
00712    free(cid);
00713 }
00714 
00715 static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
00716 {
00717    time_t t;
00718    struct tm tm;
00719    char *ptr;
00720    int res;
00721    int i,x;
00722    /* Get the time */
00723    time(&t);
00724    ast_localtime(&t, &tm, NULL);
00725    
00726    ptr = msg;
00727    
00728    /* Format time and message header */
00729    res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
00730             tm.tm_mday, tm.tm_hour, tm.tm_min);
00731    size -= res;
00732    ptr += res;
00733    if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
00734       /* Indicate number not known */
00735       res = snprintf(ptr, size, "\004\001O");
00736       size -= res;
00737       ptr += res;
00738    } else if (flags & CID_PRIVATE_NUMBER) {
00739       /* Indicate number is private */
00740       res = snprintf(ptr, size, "\004\001P");
00741       size -= res;
00742       ptr += res;
00743    } else {
00744       /* Send up to 16 digits of number MAX */
00745       i = strlen(number);
00746       if (i > 16) i = 16;
00747       res = snprintf(ptr, size, "\002%c", i);
00748       size -= res;
00749       ptr += res;
00750       for (x = 0; x < i; x++)
00751          ptr[x] = number[x];
00752       ptr[i] = '\0';
00753       ptr += i;
00754       size -= i;
00755    }
00756 
00757    if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
00758       /* Indicate name not known */
00759       res = snprintf(ptr, size, "\010\001O");
00760       size -= res;
00761       ptr += res;
00762    } else if (flags & CID_PRIVATE_NAME) {
00763       /* Indicate name is private */
00764       res = snprintf(ptr, size, "\010\001P");
00765       size -= res;
00766       ptr += res;
00767    } else {
00768       /* Send up to 16 digits of name MAX */
00769       i = strlen(name);
00770       if (i > 16) i = 16;
00771       res = snprintf(ptr, size, "\007%c", i);
00772       size -= res;
00773       ptr += res;
00774       for (x=0;x<i;x++)
00775          ptr[x] = name[x];
00776       ptr[i] = '\0';
00777       ptr += i;
00778       size -= i;
00779    }
00780    return (ptr - msg);
00781    
00782 }
00783 
00784 int ast_callerid_vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
00785 {
00786    unsigned char msg[256];
00787    int len=0;
00788    int sum;
00789    int x;
00790    int bytes = 0;
00791    float cr = 1.0;
00792    float ci = 0.0;
00793    float scont = 0.0;
00794    if (mdmf) {
00795       /* MDMF Message waiting */
00796       msg[len++] = 0x82;
00797       /* Length is 3 */
00798       msg[len++] = 3;
00799       /* IE is "Message Waiting Parameter" */
00800       msg[len++] = 0xb;
00801       /* Length of IE is one */
00802       msg[len++] = 1;
00803       /* Active or not */
00804       if (active)
00805          msg[len++] = 0xff;
00806       else
00807          msg[len++] = 0x00;
00808    } else {
00809       /* SDMF Message waiting */
00810       msg[len++] = 0x6;
00811       /* Length is 3 */
00812       msg[len++] = 3;
00813       if (active) {
00814          msg[len++] = 0x42;
00815          msg[len++] = 0x42;
00816          msg[len++] = 0x42;
00817       } else {
00818          msg[len++] = 0x6f;
00819          msg[len++] = 0x6f;
00820          msg[len++] = 0x6f;
00821       }
00822    }
00823    sum = 0;
00824    for (x=0; x<len; x++)
00825       sum += msg[x];
00826    sum = (256 - (sum & 255));
00827    msg[len++] = sum;
00828    /* Wait a half a second */
00829    for (x=0; x<4000; x++)
00830       PUT_BYTE(0x7f);
00831    /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
00832    for (x=0; x<30; x++)
00833       PUT_CLID(0x55);
00834    /* Send 170ms of callerid marks */
00835    for (x=0; x<170; x++)
00836       PUT_CLID_MARKMS;
00837    for (x=0; x<len; x++) {
00838       PUT_CLID(msg[x]);
00839    }
00840    /* Send 50 more ms of marks */
00841    for (x=0; x<50; x++)
00842       PUT_CLID_MARKMS;
00843    return bytes;
00844 }
00845 
00846 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec)
00847 {
00848    int bytes=0;
00849    int x, sum;
00850    int len;
00851 
00852    /* Initial carriers (real/imaginary) */
00853    float cr = 1.0;
00854    float ci = 0.0;
00855    float scont = 0.0;
00856    char msg[256];
00857    len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
00858    if (!callwaiting) {
00859       /* Wait a half a second */
00860       for (x=0; x<4000; x++)
00861          PUT_BYTE(0x7f);
00862       /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
00863       for (x=0; x<30; x++)
00864          PUT_CLID(0x55);
00865    }
00866    /* Send 150ms of callerid marks */
00867    for (x=0; x<150; x++)
00868       PUT_CLID_MARKMS;
00869    /* Send 0x80 indicating MDMF format */
00870    PUT_CLID(0x80);
00871    /* Put length of whole message */
00872    PUT_CLID(len);
00873    sum = 0x80 + strlen(msg);
00874    /* Put each character of message and update checksum */
00875    for (x=0; x<len; x++) {
00876       PUT_CLID(msg[x]);
00877       sum += msg[x];
00878    }
00879    /* Send 2's compliment of sum */
00880    PUT_CLID(256 - (sum & 255));
00881 
00882    /* Send 50 more ms of marks */
00883    for (x=0; x<50; x++)
00884       PUT_CLID_MARKMS;
00885    
00886    return bytes;
00887 }
00888 
00889 /*! \brief Clean up phone string
00890  * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
00891  * Basically, remove anything that could be invalid in a pattern.
00892  */
00893 void ast_shrink_phone_number(char *n)
00894 {
00895    int x, y=0;
00896    int bracketed = 0;
00897 
00898    for (x=0; n[x]; x++) {
00899       switch(n[x]) {
00900       case '[':
00901          bracketed++;
00902          n[y++] = n[x];
00903          break;
00904       case ']':
00905          bracketed--;
00906          n[y++] = n[x];
00907          break;
00908       case '-':
00909          if (bracketed)
00910             n[y++] = n[x];
00911          break;
00912       case '.':
00913          if (!n[x+1])
00914             n[y++] = n[x];
00915          break;
00916       default:
00917          if (!strchr("( )", n[x]))
00918             n[y++] = n[x];
00919       }
00920    }
00921    n[y] = '\0';
00922 }
00923 
00924 /*! \brief Checks if phone number consists of valid characters 
00925    \param exten   String that needs to be checked
00926    \param valid   Valid characters in string
00927    \return 1 if valid string, 0 if string contains invalid characters
00928 */
00929 static int ast_is_valid_string(const char *exten, const char *valid)
00930 {
00931    int x;
00932 
00933    if (ast_strlen_zero(exten))
00934       return 0;
00935    for (x=0; exten[x]; x++)
00936       if (!strchr(valid, exten[x]))
00937          return 0;
00938    return 1;
00939 }
00940 
00941 /*! \brief checks if string consists only of digits and * \# and + 
00942    \return 1 if string is valid AST phone number
00943    \return 0 if not
00944 */
00945 int ast_isphonenumber(const char *n)
00946 {
00947    return ast_is_valid_string(n, "0123456789*#+");
00948 }
00949 
00950 /*! \brief checks if string consists only of digits and ( ) - * \# and + 
00951    Pre-qualifies the string for ast_shrink_phone_number()
00952    \return 1 if string is valid AST shrinkable phone number
00953    \return 0 if not
00954 */
00955 int ast_is_shrinkable_phonenumber(const char *exten)
00956 {
00957    return ast_is_valid_string(exten, "0123456789*#+()-.");
00958 }
00959 
00960 /*!
00961  * \brief Destructively parse instr for caller id information 
00962  * \return always returns 0, as the code always returns something.
00963  * \note XXX 'name' is not parsed consistently e.g. we have
00964  * input                   location        name
00965  * " foo bar " <123>       123             ' foo bar ' (with spaces around)
00966  * " foo bar "             NULL            'foo bar' (without spaces around)
00967  * The parsing of leading and trailing space/quotes should be more consistent.
00968  */
00969 int ast_callerid_parse(char *instr, char **name, char **location)
00970 {
00971    char *ns, *ne, *ls, *le;
00972 
00973    /* Try "name" <location> format or name <location> format */
00974    if ((ls = strrchr(instr, '<')) && (le = strrchr(ls, '>'))) {
00975       *ls = *le = '\0'; /* location found, trim off the brackets */
00976       *location = ls + 1;  /* and this is the result */
00977       if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
00978          *ns = *ne = '\0'; /* trim off the quotes */
00979          *name = ns + 1;      /* and this is the name */
00980       } else if (ns) {
00981          /* An opening quote was found but no closing quote was. The closing
00982           * quote may actually be after the end of the bracketed number
00983           */
00984          if (strchr(le + 1, '\"')) {
00985             *ns = '\0';
00986             *name = ns + 1;
00987             ast_trim_blanks(*name);
00988          }
00989       } else { /* no quotes, trim off leading and trailing spaces */
00990          *name = ast_skip_blanks(instr);
00991          ast_trim_blanks(*name);
00992       }
00993    } else { /* no valid brackets */
00994       char tmp[256];
00995 
00996       ast_copy_string(tmp, instr, sizeof(tmp));
00997       ast_shrink_phone_number(tmp);
00998       if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
00999          *name = NULL;
01000          strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
01001          *location = instr;
01002       } else { /* Assume it's just a name. */
01003          *location = NULL;
01004          if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
01005             *ns = *ne = '\0'; /* trim off the quotes */
01006             *name = ns + 1;      /* and this is the name */
01007          } else { /* no quotes, trim off leading and trailing spaces */
01008             *name = ast_skip_blanks(instr);
01009             ast_trim_blanks(*name);
01010          }
01011       }
01012    }
01013    return 0;
01014 }
01015 
01016 static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, int codec)
01017 {
01018    if (ast_strlen_zero(name))
01019       name = NULL;
01020    if (ast_strlen_zero(number))
01021       number = NULL;
01022    return callerid_generate(buf, number, name, 0, callwaiting, codec);
01023 }
01024 
01025 int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec)
01026 {
01027    return __ast_callerid_generate(buf, name, number, 0, codec);
01028 }
01029 
01030 int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec)
01031 {
01032    return __ast_callerid_generate(buf, name, number, 1, codec);
01033 }
01034 
01035 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
01036 {
01037    if (!unknown)
01038       unknown = "<unknown>";
01039    if (name && num)
01040       snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
01041    else if (name) 
01042       ast_copy_string(buf, name, bufsiz);
01043    else if (num)
01044       ast_copy_string(buf, num, bufsiz);
01045    else
01046       ast_copy_string(buf, unknown, bufsiz);
01047    return buf;
01048 }
01049 
01050 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
01051 {
01052    char *tmp;
01053    char *l = NULL, *n = NULL;
01054 
01055    tmp = ast_strdupa(buf);
01056    ast_callerid_parse(tmp, &n, &l);
01057    if (n)
01058       ast_copy_string(name, n, namelen);
01059    else
01060       name[0] = '\0';
01061    if (l) {
01062       ast_shrink_phone_number(l);
01063       ast_copy_string(num, l, numlen);
01064    } else
01065       num[0] = '\0';
01066    return 0;
01067 }
01068 
01069 /*! \brief Translation table for Caller ID Presentation settings */
01070 static struct {
01071    int val;
01072    char *name;
01073    char *description;
01074 } pres_types[] = {
01075    {  AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
01076    {  AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
01077    {  AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
01078    {  AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
01079    {  AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
01080    {  AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
01081    {  AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
01082    {  AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
01083    {  AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
01084 };
01085 
01086 /*! \brief Convert caller ID text code to value 
01087    used in config file parsing
01088    \param data text string
01089    \return value AST_PRES_ from callerid.h 
01090 */
01091 int ast_parse_caller_presentation(const char *data)
01092 {
01093    int i;
01094 
01095    if (!data) {
01096       return -1;
01097    }
01098 
01099    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
01100       if (!strcasecmp(pres_types[i].name, data))
01101          return pres_types[i].val;
01102    }
01103 
01104    return -1;
01105 }
01106 
01107 /*! \brief Convert caller ID pres value to explanatory string 
01108    \param data value (see callerid.h AST_PRES_ ) 
01109    \return string for human presentation
01110 */
01111 const char *ast_describe_caller_presentation(int data)
01112 {
01113    int i;
01114 
01115    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
01116       if (pres_types[i].val == data)
01117          return pres_types[i].description;
01118    }
01119 
01120    return "unknown";
01121 }

Generated on Tue Nov 16 17:07:29 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7