Mon Apr 30 07:36:30 2007

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

Generated on Mon Apr 30 07:36:30 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1