Sat Aug 6 00:39:37 2011

Asterisk developer's documentation


app_sms.c File Reference

SMS application - ETSI ES 201 912 protocol 1 implimentation. More...

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"

Go to the source code of this file.

Data Structures

struct  sms_s

Defines

#define is16bit(dcs)   (((dcs)&0xC0)?0:(((dcs)&12)==8))
#define is7bit(dcs)   (((dcs)&0xC0)?(!((dcs)&4)):(!((dcs)&12)))
#define is8bit(dcs)   (((dcs)&0xC0)?(((dcs)&4)):(((dcs)&12)==4))
#define MAXSAMPLES   (800)
#define SAMPLE2LEN   sizeof(*buf)
#define SMSLEN   160

Typedefs

typedef sms_s sms_t

Functions

static void __reg_module (void)
static void __unreg_module (void)
static char * isodate (time_t t)
 static, return a date/time in ISO format
static int load_module (void)
static void numcpy (char *d, char *s)
 copy number, skipping non digits apart from leading +
static unsigned char packaddress (unsigned char *o, char *i)
 store an address at o, and return number of bytes used
static void packdate (unsigned char *o, time_t w)
 pack a date and return
static int packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
 general pack, with length and data, returns number of bytes of target used
static int packsms16 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
 takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 16 bit UCS-2 character codes The return value is the number of bytes packed in to o, which is internally limited to 140 o can be null, in which case this is used to validate or count only if the input contains invalid characters then the return value is -1
static int packsms7 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
 takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using SMS 7 bit character codes
static int packsms8 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
 takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 8 bit character codes
static struct dirent * readdirqueue (DIR *d, char *queue)
 read dir skipping dot files...
static void * sms_alloc (struct ast_channel *chan, void *params)
static void sms_debug (char *dir, unsigned char *msg)
static int sms_exec (struct ast_channel *chan, void *data)
static int sms_generate (struct ast_channel *chan, void *data, int len, int samples)
static unsigned char sms_handleincoming (sms_t *h)
 handle the incoming message
static void sms_log (sms_t *h, char status)
 Log the output, and remove file.
static void sms_messagerx (sms_t *h)
static void sms_messagetx (sms_t *h)
static void sms_nextoutgoing (sms_t *h)
 find and fill in next message, or send a REL if none waiting
static void sms_process (sms_t *h, int samples, signed short *data)
static void sms_readfile (sms_t *h, char *fn)
 parse and delete a file
static void sms_release (struct ast_channel *chan, void *data)
static void sms_writefile (sms_t *h)
 white a received text message to a file
static int unload_module (void)
static unsigned char unpackaddress (char *o, unsigned char *i)
 unpack an address from i, return byte length, unpack to o
static time_t unpackdate (unsigned char *i)
 unpack a date and return
static int unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
 general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length
static void unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
 unpacks bytes (16 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set
static void unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
 unpacks bytes (7 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set
static void unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
 unpacks bytes (8 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set
static long utf8decode (unsigned char **pp)
 reads next UCS character from null terminated UTF-8 string and advanced pointer

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "SMS/PSTN handler" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, }
static char * app = "SMS"
static const struct ast_module_infoast_module_info = &__mod_info
static const unsigned short defaultalphabet []
static char * descrip
static const unsigned short escapes []
static char log_file [255]
static volatile unsigned char message_ref
static volatile unsigned int seq
static struct ast_generator smsgen
static char spool_dir [255]
static char * synopsis = "Communicates with SMS service centres and SMS capable analogue phones"
static signed short wave []


Detailed Description

SMS application - ETSI ES 201 912 protocol 1 implimentation.

Author:
Adrian Kennard

Definition in file app_sms.c.


Define Documentation

#define is16bit ( dcs   )     (((dcs)&0xC0)?0:(((dcs)&12)==8))

Definition at line 182 of file app_sms.c.

Referenced by sms_readfile().

#define is7bit ( dcs   )     (((dcs)&0xC0)?(!((dcs)&4)):(!((dcs)&12)))

Definition at line 180 of file app_sms.c.

Referenced by packsms(), sms_readfile(), and unpacksms().

#define is8bit ( dcs   )     (((dcs)&0xC0)?(((dcs)&4)):(((dcs)&12)==4))

Definition at line 181 of file app_sms.c.

Referenced by packsms(), sms_readfile(), and unpacksms().

#define MAXSAMPLES   (800)

Referenced by sms_generate().

#define SAMPLE2LEN   sizeof(*buf)

Referenced by sms_generate().

#define SMSLEN   160

Definition at line 122 of file app_sms.c.

Referenced by packsms7(), and sms_readfile().


Typedef Documentation

typedef struct sms_s sms_t


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1544 of file app_sms.c.

static void __unreg_module ( void   )  [static]

Definition at line 1544 of file app_sms.c.

static char* isodate ( time_t  t  )  [static]

static, return a date/time in ISO format

Definition at line 210 of file app_sms.c.

Referenced by sms_log(), and sms_writefile().

00211 {
00212    static char date[20];
00213    strftime (date, sizeof (date), "%Y-%m-%dT%H:%M:%S", localtime (&t));
00214    return date;
00215 }

static int load_module ( void   )  [static]

Definition at line 1530 of file app_sms.c.

References ast_config_AST_LOG_DIR, ast_config_AST_SPOOL_DIR, AST_LIN2A, ast_register_application(), and sms_exec().

01531 {
01532 #ifdef OUTALAW
01533    {
01534       int p;
01535       for (p = 0; p < 80; p++)
01536          wavea[p] = AST_LIN2A (wave[p]);
01537    }
01538 #endif
01539    snprintf (log_file, sizeof (log_file), "%s/sms", ast_config_AST_LOG_DIR);
01540    snprintf (spool_dir, sizeof (spool_dir), "%s/sms", ast_config_AST_SPOOL_DIR);
01541    return ast_register_application (app, sms_exec, synopsis, descrip);
01542 }

static void numcpy ( char *  d,
char *  s 
) [static]

copy number, skipping non digits apart from leading +

Definition at line 197 of file app_sms.c.

Referenced by sms_readfile().

00198 {
00199    if (*s == '+')
00200       *d++ = *s++;
00201    while (*s) {
00202       if (isdigit (*s))
00203             *d++ = *s;
00204       s++;
00205    }
00206    *d = 0;
00207 }

static unsigned char packaddress ( unsigned char *  o,
char *  i 
) [static]

store an address at o, and return number of bytes used

Definition at line 610 of file app_sms.c.

Referenced by sms_nextoutgoing().

00611 {
00612    unsigned char p = 2;
00613    o[0] = 0;
00614    if (*i == '+') {
00615       i++;
00616       o[1] = 0x91;
00617    } else
00618       o[1] = 0x81;
00619    while (*i)
00620       if (isdigit (*i)) {
00621          if (o[0] & 1)
00622             o[p++] |= ((*i & 0xF) << 4);
00623          else
00624             o[p] = (*i & 0xF);
00625          o[0]++;
00626          i++;
00627       } else
00628          i++;
00629    if (o[0] & 1)
00630       o[p++] |= 0xF0;           /* pad */
00631    return p;
00632 }

static void packdate ( unsigned char *  o,
time_t  w 
) [static]

pack a date and return

Definition at line 435 of file app_sms.c.

References t.

Referenced by sms_nextoutgoing().

00436 {
00437    struct tm *t = localtime (&w);
00438 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
00439    int z = -t->tm_gmtoff / 60 / 15;
00440 #else
00441    int z = timezone / 60 / 15;
00442 #endif
00443    *o++ = ((t->tm_year % 10) << 4) + (t->tm_year % 100) / 10;
00444    *o++ = (((t->tm_mon + 1) % 10) << 4) + (t->tm_mon + 1) / 10;
00445    *o++ = ((t->tm_mday % 10) << 4) + t->tm_mday / 10;
00446    *o++ = ((t->tm_hour % 10) << 4) + t->tm_hour / 10;
00447    *o++ = ((t->tm_min % 10) << 4) + t->tm_min / 10;
00448    *o++ = ((t->tm_sec % 10) << 4) + t->tm_sec / 10;
00449    if (z < 0)
00450       *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
00451    else
00452       *o++ = ((z % 10) << 4) + z / 10;
00453 }

static int packsms ( unsigned char  dcs,
unsigned char *  base,
unsigned int  udhl,
unsigned char *  udh,
int  udl,
unsigned short *  ud 
) [static]

general pack, with length and data, returns number of bytes of target used

Definition at line 404 of file app_sms.c.

References is7bit, is8bit, packsms16(), packsms7(), and packsms8().

Referenced by sms_nextoutgoing().

00405 {
00406    unsigned char *p = base;
00407    if (udl) {
00408       int l = 0;
00409       if (is7bit (dcs)) {      /* 7 bit */
00410          l = packsms7 (p + 1, udhl, udh, udl, ud);
00411          if (l < 0)
00412             l = 0;
00413          *p++ = l;
00414          p += (l * 7 + 7) / 8;
00415       } else if (is8bit (dcs)) {                       /* 8 bit */
00416          l = packsms8 (p + 1, udhl, udh, udl, ud);
00417          if (l < 0)
00418             l = 0;
00419          *p++ = l;
00420          p += l;
00421       } else {        /* UCS-2 */
00422          l = packsms16 (p + 1, udhl, udh, udl, ud);
00423          if (l < 0)
00424             l = 0;
00425          *p++ = l;
00426          p += l;
00427       }
00428    } else
00429       *p++ = 0;           /* no user data */
00430    return p - base;
00431 }

static int packsms16 ( unsigned char *  o,
int  udhl,
unsigned char *  udh,
int  udl,
unsigned short *  ud 
) [static]

takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 16 bit UCS-2 character codes The return value is the number of bytes packed in to o, which is internally limited to 140 o can be null, in which case this is used to validate or count only if the input contains invalid characters then the return value is -1

Definition at line 373 of file app_sms.c.

Referenced by packsms(), and sms_readfile().

00374 {
00375    unsigned char p = 0;
00376    /* header - no encoding */
00377    if (udhl) {
00378       if (o)
00379          o[p++] = udhl;
00380       while (udhl--) {
00381          if (o)
00382             o[p++] = *udh++;
00383          if (p >= 140)
00384             return p;
00385       }
00386    }
00387    while (udl--) {
00388       long u;
00389       u = *ud++;
00390       if (o)
00391          o[p++] = (u >> 8);
00392       if (p >= 140)
00393          return p - 1;          /* could not fit last character */
00394       if (o)
00395          o[p++] = u;
00396       if (p >= 140)
00397          return p;
00398    }
00399    return p;
00400 }

static int packsms7 ( unsigned char *  o,
int  udhl,
unsigned char *  udh,
int  udl,
unsigned short *  ud 
) [static]

takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using SMS 7 bit character codes

Definition at line 267 of file app_sms.c.

References SMSLEN.

Referenced by packsms(), and sms_readfile().

00268 {
00269     unsigned char p = 0, b = 0, n = 0;
00270 
00271    if (udhl) {                            /* header */
00272       if (o)
00273          o[p++] = udhl;
00274       b = 1;
00275       n = 1;
00276       while (udhl--) {
00277          if (o)
00278             o[p++] = *udh++;
00279          b += 8;
00280          while (b >= 7) {
00281             b -= 7;
00282             n++;
00283          }
00284          if (n >= SMSLEN)
00285             return n;
00286       }
00287       if (b) {
00288          b = 7 - b;
00289          if (++n >= SMSLEN)
00290             return n;
00291          }; /* filling to septet boundary */
00292       }
00293       if (o)
00294          o[p] = 0;
00295       /* message */
00296       while (udl--) {
00297          long u;
00298          unsigned char v;
00299          u = *ud++;
00300          for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
00301          if (v == 128 && u && n + 1 < SMSLEN) {
00302             for (v = 0; v < 128 && escapes[v] != u; v++);
00303             if (v < 128) { /* escaped sequence */
00304             if (o)
00305                o[p] |= (27 << b);
00306             b += 7;
00307             if (b >= 8) {
00308                b -= 8;
00309                p++;
00310                if (o)
00311                   o[p] = (27 >> (7 - b));
00312             }
00313             n++;
00314          }
00315       }
00316       if (v == 128)
00317          return -1;             /* invalid character */
00318       if (o)
00319          o[p] |= (v << b);
00320       b += 7;
00321       if (b >= 8) {
00322          b -= 8;
00323          p++;
00324          if (o)
00325             o[p] = (v >> (7 - b));
00326       }
00327       if (++n >= SMSLEN)
00328          return n;
00329    }
00330    return n;
00331 }

static int packsms8 ( unsigned char *  o,
int  udhl,
unsigned char *  udh,
int  udl,
unsigned short *  ud 
) [static]

takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 8 bit character codes

Definition at line 337 of file app_sms.c.

Referenced by packsms(), and sms_readfile().

00338 {
00339    unsigned char p = 0;
00340 
00341    /* header - no encoding */
00342    if (udhl) {
00343       if (o)
00344          o[p++] = udhl;
00345       while (udhl--) {
00346          if (o)
00347             o[p++] = *udh++;
00348          if (p >= 140)
00349             return p;
00350       }
00351    }
00352    while (udl--) {
00353       long u;
00354       u = *ud++;
00355       if (u < 0 || u > 0xFF)
00356          return -1;             /* not valid */
00357       if (o)
00358          o[p++] = u;
00359       if (p >= 140)
00360          return p;
00361    }
00362    return p;
00363 }

static struct dirent* readdirqueue ( DIR *  d,
char *  queue 
) [static]

read dir skipping dot files...

Definition at line 945 of file app_sms.c.

References f.

Referenced by sms_nextoutgoing().

00946 {
00947    struct dirent *f;
00948    do {
00949       f = readdir (d);
00950    } while (f && (*f->d_name == '.' || strncmp (f->d_name, queue, strlen (queue)) || f->d_name[strlen (queue)] != '.'));
00951    return f;
00952 }

static void* sms_alloc ( struct ast_channel chan,
void *  params 
) [static]

Definition at line 184 of file app_sms.c.

00185 {
00186    return params;
00187 }

static void sms_debug ( char *  dir,
unsigned char *  msg 
) [static]

Definition at line 1090 of file app_sms.c.

References ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.

Referenced by sms_messagerx(), and sms_messagetx().

01091 {
01092    char txt[259 * 3 + 1],
01093     *p = txt;                  /* always long enough */
01094    int n = msg[1] + 3,
01095       q = 0;
01096    while (q < n && q < 30) {
01097       sprintf (p, " %02X", msg[q++]);
01098       p += 3;
01099    }
01100    if (q < n)
01101       sprintf (p, "...");
01102    if (option_verbose > 2)
01103       ast_verbose (VERBOSE_PREFIX_3 "SMS %s%s\n", dir, txt);
01104 }

static int sms_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 1359 of file app_sms.c.

References answer, ast_copy_string(), ast_log(), ast_module_user_add, ast_module_user_remove, ast_channel::cid, ast_callerid::cid_num, sms_s::cli, sms_s::dcs, f, sms_s::ipc0, sms_s::ipc1, LOG_ERROR, sms_s::oa, sms_s::pid, sms_s::queue, sms_s::scts, sms_s::smsc, and sms_s::srr.

Referenced by load_module().

01360 {
01361    int res = -1;
01362    struct ast_module_user *u;
01363    struct ast_frame *f;
01364    sms_t h = { 0 };
01365    
01366    u = ast_module_user_add(chan);
01367 
01368    h.ipc0 = h.ipc1 = 20;        /* phase for cosine */
01369    h.dcs = 0xF1;               /* default */
01370    if (!data) {
01371       ast_log (LOG_ERROR, "Requires queue name at least\n");
01372       ast_module_user_remove(u);
01373       return -1;
01374    }
01375 
01376    if (chan->cid.cid_num)
01377       ast_copy_string (h.cli, chan->cid.cid_num, sizeof (h.cli));
01378 
01379    {
01380       unsigned char *p;
01381       unsigned char *d = data,
01382          answer = 0;
01383       if (!*d || *d == '|') {
01384          ast_log (LOG_ERROR, "Requires queue name\n");
01385          ast_module_user_remove(u);
01386          return -1;
01387       }
01388       for (p = d; *p && *p != '|'; p++);
01389       if (p - d >= sizeof (h.queue)) {
01390          ast_log (LOG_ERROR, "Queue name too long\n");
01391          ast_module_user_remove(u);
01392          return -1;
01393       }
01394       strncpy(h.queue, (char *)d, p - d);
01395       if (*p == '|')
01396          p++;
01397       d = p;
01398       for (p = (unsigned char *)h.queue; *p; p++)
01399          if (!isalnum (*p))
01400             *p = '-';           /* make very safe for filenames */
01401       while (*d && *d != '|') {
01402          switch (*d) {
01403          case 'a':             /* we have to send the initial FSK sequence */
01404             answer = 1;
01405             break;
01406          case 's':             /* we are acting as a service centre talking to a phone */
01407             h.smsc = 1;
01408             break;
01409             /* the following apply if there is an arg3/4 and apply to the created message file */
01410          case 'r':
01411             h.srr = 1;
01412             break;
01413          case 'o':
01414             h.dcs |= 4;       /* octets */
01415             break;
01416          case '1':
01417          case '2':
01418          case '3':
01419          case '4':
01420          case '5':
01421          case '6':
01422          case '7':             /* set the pid for saved local message */
01423             h.pid = 0x40 + (*d & 0xF);
01424             break;
01425          }
01426          d++;
01427       }
01428       if (*d == '|') {
01429          /* submitting a message, not taking call. */
01430          /* deprecated, use smsq instead */
01431          d++;
01432          h.scts = time (0);
01433          for (p = d; *p && *p != '|'; p++);
01434          if (*p)
01435             *p++ = 0;
01436          if (strlen ((char *)d) >= sizeof (h.oa)) {
01437             ast_log (LOG_ERROR, "Address too long %s\n", d);
01438             return 0;
01439          }
01440          if (h.smsc) {
01441             ast_copy_string (h.oa, (char *)d, sizeof (h.oa));
01442          } else {
01443             ast_copy_string (h.da, (char *)d, sizeof (h.da));
01444          }
01445          if (!h.smsc)
01446             ast_copy_string (h.oa, h.cli, sizeof (h.oa));
01447          d = p;
01448          h.udl = 0;
01449          while (*p && h.udl < SMSLEN)
01450             h.ud[h.udl++] = utf8decode(&p);
01451          if (is7bit (h.dcs) && packsms7 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01452             ast_log (LOG_WARNING, "Invalid 7 bit GSM data\n");
01453          if (is8bit (h.dcs) && packsms8 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01454             ast_log (LOG_WARNING, "Invalid 8 bit data\n");
01455          if (is16bit (h.dcs) && packsms16 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01456             ast_log (LOG_WARNING, "Invalid 16 bit data\n");
01457          h.rx = 0;              /* sent message */
01458          h.mr = -1;
01459          sms_writefile (&h);
01460          ast_module_user_remove(u);
01461          return 0;
01462       }
01463 
01464       if (answer) {
01465          /* set up SMS_EST initial message */
01466          h.omsg[0] = 0x93;
01467          h.omsg[1] = 0;
01468          sms_messagetx (&h);
01469       }
01470    }
01471 
01472    if (chan->_state != AST_STATE_UP)
01473       ast_answer (chan);
01474 
01475 #ifdef OUTALAW
01476    res = ast_set_write_format (chan, AST_FORMAT_ALAW);
01477 #else
01478    res = ast_set_write_format (chan, AST_FORMAT_SLINEAR);
01479 #endif
01480    if (res >= 0)
01481       res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
01482    if (res < 0) {
01483       ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
01484       ast_module_user_remove(u);
01485       return -1;
01486    }
01487 
01488    if (ast_activate_generator (chan, &smsgen, &h) < 0) {
01489       ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
01490       ast_module_user_remove(u);
01491       return -1;
01492    }
01493 
01494    /* Do our thing here */
01495    while (ast_waitfor (chan, -1) > -1 && !h.hangup)
01496    {
01497       f = ast_read (chan);
01498       if (!f)
01499          break;
01500       if (f->frametype == AST_FRAME_VOICE) {
01501          sms_process (&h, f->samples, f->data);
01502       }
01503 
01504       ast_frfree (f);
01505    }
01506 
01507    sms_log (&h, '?');           /* log incomplete message */
01508 
01509    /* 
01510     * The SMS generator data is on the stack.  We _MUST_ make sure the generator
01511     * is stopped before returning from this function.
01512     */
01513    ast_deactivate_generator(chan);
01514 
01515    ast_module_user_remove(u);
01516    return (h.err);
01517 }

static int sms_generate ( struct ast_channel chan,
void *  data,
int  len,
int  samples 
) [static]

Definition at line 1176 of file app_sms.c.

References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), f, LOG_WARNING, MAXSAMPLES, sms_s::obitp, sms_s::obyte, sms_s::obyten, sms_s::obytep, sms_s::omsg, sms_s::opause, sms_s::ophase, sms_s::ophasep, sms_s::osync, and SAMPLE2LEN.

01177 {
01178    struct ast_frame f = { 0 };
01179 #define MAXSAMPLES (800)
01180 #ifdef OUTALAW
01181    unsigned char *buf;
01182 #else
01183    short *buf;
01184 #endif
01185 #define SAMPLE2LEN sizeof(*buf)
01186    sms_t *h = data;
01187    int i;
01188 
01189    if (samples > MAXSAMPLES) {
01190       ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
01191           MAXSAMPLES, samples);
01192       samples = MAXSAMPLES;
01193    }
01194    len = samples * SAMPLE2LEN + AST_FRIENDLY_OFFSET;
01195    buf = alloca(len);
01196 
01197    f.frametype = AST_FRAME_VOICE;
01198 #ifdef OUTALAW
01199    f.subclass = AST_FORMAT_ALAW;
01200 #else
01201    f.subclass = AST_FORMAT_SLINEAR;
01202 #endif
01203    f.datalen = samples * SAMPLE2LEN;
01204    f.offset = AST_FRIENDLY_OFFSET;
01205    f.mallocd = 0;
01206    f.data = buf;
01207    f.samples = samples;
01208    f.src = "app_sms";
01209    /* create a buffer containing the digital sms pattern */
01210    for (i = 0; i < samples; i++) {
01211 #ifdef OUTALAW
01212       buf[i] = wavea[0];
01213 #else
01214       buf[i] = wave[0];
01215 #endif
01216       if (h->opause)
01217          h->opause--;
01218       else if (h->obyten || h->osync) {                         /* sending data */
01219 #ifdef OUTALAW
01220          buf[i] = wavea[h->ophase];
01221 #else
01222          buf[i] = wave[h->ophase];
01223 #endif
01224          if ((h->ophase += ((h->obyte & 1) ? 13 : 21)) >= 80)
01225             h->ophase -= 80;
01226          if ((h->ophasep += 12) >= 80) {                     /* next bit */
01227             h->ophasep -= 80;
01228             if (h->osync)
01229                h->osync--;    /* sending sync bits */
01230             else {
01231                h->obyte >>= 1;
01232                h->obitp++;
01233                if (h->obitp == 1)
01234                   h->obyte = 0; /* start bit; */
01235                else if (h->obitp == 2)
01236                   h->obyte = h->omsg[h->obytep];
01237                else if (h->obitp == 10) {
01238                   h->obyte = 1; /* stop bit */
01239                   h->obitp = 0;
01240                   h->obytep++;
01241                   if (h->obytep == h->obyten) {
01242                      h->obytep = h->obyten = 0; /* sent */
01243                      h->osync = 10;   /* trailing marks */
01244                   }
01245                }
01246             }
01247          }
01248       }
01249    }
01250    if (ast_write (chan, &f) < 0) {
01251       ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror (errno));
01252       return -1;
01253    }
01254    return 0;
01255 #undef SAMPLE2LEN
01256 #undef MAXSAMPLES
01257 }

static unsigned char sms_handleincoming ( sms_t h  )  [static]

handle the incoming message

Definition at line 955 of file app_sms.c.

References ast_copy_string(), ast_log(), sms_s::cli, sms_s::da, sms_s::dcs, sms_s::imsg, LOG_WARNING, sms_s::mr, sms_s::oa, sms_s::pid, sms_s::rp, sms_s::rx, sms_s::scts, sms_writefile(), sms_s::smsc, sms_s::srr, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, unpackaddress(), unpackdate(), unpacksms(), and sms_s::vp.

Referenced by sms_messagerx().

00956 {
00957    unsigned char p = 3;
00958    if (h->smsc) {                          /* SMSC */
00959       if ((h->imsg[2] & 3) == 1) {           /* SMS-SUBMIT */
00960          h->udhl = h->udl = 0;
00961          h->vp = 0;
00962          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
00963          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
00964          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
00965          ast_copy_string (h->oa, h->cli, sizeof (h->oa));
00966          h->scts = time (0);
00967          h->mr = h->imsg[p++];
00968          p += unpackaddress (h->da, h->imsg + p);
00969          h->pid = h->imsg[p++];
00970          h->dcs = h->imsg[p++];
00971          if ((h->imsg[2] & 0x18) == 0x10) {                     /* relative VP */
00972             if (h->imsg[p] < 144)
00973                h->vp = (h->imsg[p] + 1) * 5;
00974             else if (h->imsg[p] < 168)
00975                h->vp = 720 + (h->imsg[p] - 143) * 30;
00976             else if (h->imsg[p] < 197)
00977                h->vp = (h->imsg[p] - 166) * 1440;
00978             else
00979                h->vp = (h->imsg[p] - 192) * 10080;
00980             p++;
00981          } else if (h->imsg[2] & 0x18)
00982             p += 7;            /* ignore enhanced / absolute VP */
00983          p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
00984          h->rx = 1;            /* received message */
00985          sms_writefile (h);     /* write the file */
00986          if (p != h->imsg[1] + 2) {
00987             ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
00988             return 0xFF;        /* duh! */
00989          }
00990       } else {
00991          ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
00992          return 0xFF;
00993       }
00994    } else {                          /* client */
00995       if (!(h->imsg[2] & 3)) {                         /* SMS-DELIVER */
00996          *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
00997          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
00998          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
00999          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01000          h->mr = -1;
01001          p += unpackaddress (h->oa, h->imsg + p);
01002          h->pid = h->imsg[p++];
01003          h->dcs = h->imsg[p++];
01004          h->scts = unpackdate (h->imsg + p);
01005          p += 7;
01006          p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01007          h->rx = 1;            /* received message */
01008          sms_writefile (h);     /* write the file */
01009          if (p != h->imsg[1] + 2) {
01010             ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01011             return 0xFF;        /* duh! */
01012          }
01013       } else {
01014          ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
01015          return 0xFF;
01016       }
01017    }
01018    return 0;                    /* no error */
01019 }

static void sms_log ( sms_t h,
char  status 
) [static]

Log the output, and remove file.

Definition at line 635 of file app_sms.c.

References sms_s::da, isodate(), sms_s::mr, sms_s::oa, sms_s::queue, sms_s::rx, sms_s::smsc, sms_s::ud, and sms_s::udl.

Referenced by sms_messagerx().

00636 {
00637    if (*h->oa || *h->da) {
00638       int o = open (log_file, O_CREAT | O_APPEND | O_WRONLY, 0666);
00639       if (o >= 0) {
00640          char line[1000], mrs[3] = "", *p;
00641          unsigned char n;
00642 
00643          if (h->mr >= 0)
00644             snprintf (mrs, sizeof (mrs), "%02X", h->mr);
00645          snprintf (line, sizeof (line), "%s %c%c%c%s %s %s %s ",
00646              isodate (time (0)), status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue, *h->oa ? h->oa : "-",
00647              *h->da ? h->da : "-");
00648          p = line + strlen (line);
00649          for (n = 0; n < h->udl; n++)
00650             if (h->ud[n] == '\\') {
00651                *p++ = '\\';
00652                *p++ = '\\';
00653             } else if (h->ud[n] == '\n') {
00654                *p++ = '\\';
00655                *p++ = 'n';
00656             } else if (h->ud[n] == '\r') {
00657                *p++ = '\\';
00658                *p++ = 'r';
00659             } else if (h->ud[n] < 32 || h->ud[n] == 127)
00660                *p++ = 191;
00661             else
00662                *p++ = h->ud[n];
00663          *p++ = '\n';
00664          *p = 0;
00665          if (write (o, line, strlen (line)) < 0) {
00666             ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00667          }
00668          close (o);
00669       }
00670       *h->oa = *h->da = h->udl = 0;
00671    }
00672 }

static void sms_messagerx ( sms_t h  )  [static]

Definition at line 1106 of file app_sms.c.

References sms_s::err, sms_s::hangup, sms_s::imsg, sms_s::omsg, sms_debug(), sms_handleincoming(), sms_log(), sms_messagetx(), and sms_nextoutgoing().

Referenced by sms_process().

01107 {
01108    sms_debug ("RX", h->imsg);
01109    /* testing */
01110    switch (h->imsg[0]) {
01111    case 0x91:                 /* SMS_DATA */
01112       {
01113          unsigned char cause = sms_handleincoming (h);
01114          if (!cause) {
01115             sms_log (h, 'Y');
01116             h->omsg[0] = 0x95;  /* SMS_ACK */
01117             h->omsg[1] = 0x02;
01118             h->omsg[2] = 0x00;  /* deliver report */
01119             h->omsg[3] = 0x00;  /* no parameters */
01120          } else {                    /* NACK */
01121             sms_log (h, 'N');
01122             h->omsg[0] = 0x96;  /* SMS_NACK */
01123             h->omsg[1] = 3;
01124             h->omsg[2] = 0;     /* delivery report */
01125             h->omsg[3] = cause; /* cause */
01126             h->omsg[4] = 0;     /* no parameters */
01127          }
01128          sms_messagetx (h);
01129       }
01130       break;
01131    case 0x92:                 /* SMS_ERROR */
01132       h->err = 1;
01133       sms_messagetx (h);        /* send whatever we sent again */
01134       break;
01135    case 0x93:                 /* SMS_EST */
01136       sms_nextoutgoing (h);
01137       break;
01138    case 0x94:                 /* SMS_REL */
01139       h->hangup = 1;          /* hangup */
01140       break;
01141    case 0x95:                 /* SMS_ACK */
01142       sms_log (h, 'Y');
01143       sms_nextoutgoing (h);
01144       break;
01145    case 0x96:                 /* SMS_NACK */
01146       h->err = 1;
01147       sms_log (h, 'N');
01148       sms_nextoutgoing (h);
01149       break;
01150    default:                  /* Unknown */
01151       h->omsg[0] = 0x92;        /* SMS_ERROR */
01152       h->omsg[1] = 1;
01153       h->omsg[2] = 3;           /* unknown message type; */
01154       sms_messagetx (h);
01155       break;
01156    }
01157 }

static void sms_messagetx ( sms_t h  )  [static]

Definition at line 1159 of file app_sms.c.

References sms_s::obitp, sms_s::obyte, sms_s::obyten, sms_s::obytep, sms_s::omsg, sms_s::opause, sms_s::osync, and sms_debug().

Referenced by sms_messagerx(), sms_nextoutgoing(), and sms_process().

01160 {
01161    unsigned char c = 0, p;
01162    for (p = 0; p < h->omsg[1] + 2; p++)
01163       c += h->omsg[p];
01164    h->omsg[h->omsg[1] + 2] = 0 - c;
01165    sms_debug ("TX", h->omsg);
01166    h->obyte = 1;
01167    h->opause = 200;
01168    if (h->omsg[0] == 0x93)
01169       h->opause = 2400;       /* initial message delay 300ms (for BT) */
01170    h->obytep = 0;
01171    h->obitp = 0;
01172    h->osync = 80;
01173    h->obyten = h->omsg[1] + 3;
01174 }

static void sms_nextoutgoing ( sms_t h  )  [static]

find and fill in next message, or send a REL if none waiting

Definition at line 1026 of file app_sms.c.

References ast_copy_string(), sms_s::da, sms_s::dcs, f, sms_s::mr, sms_s::oa, sms_s::omsg, packaddress(), packdate(), packsms(), sms_s::pid, sms_s::queue, readdirqueue(), sms_s::rp, sms_s::rx, sms_s::scts, sms_messagetx(), sms_readfile(), sms_s::smsc, sms_s::srr, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, and sms_s::vp.

Referenced by sms_messagerx().

01027 {          
01028    char fn[100 + NAME_MAX] = "";
01029    DIR *d;
01030    char more = 0;
01031    ast_copy_string (fn, spool_dir, sizeof (fn));
01032    mkdir (fn, 0777);          /* ensure it exists */
01033    h->rx = 0;                  /* outgoing message */
01034    snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? "mttx" : "motx");
01035    mkdir (fn, 0777);          /* ensure it exists */
01036    d = opendir (fn);
01037    if (d) {
01038       struct dirent *f = readdirqueue (d, h->queue);
01039       if (f) {
01040          snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", f->d_name);
01041          sms_readfile (h, fn);
01042          if (readdirqueue (d, h->queue))
01043             more = 1;           /* more to send */
01044       }
01045       closedir (d);
01046    }
01047    if (*h->da || *h->oa) {                          /* message to send */
01048       unsigned char p = 2;
01049       h->omsg[0] = 0x91;        /* SMS_DATA */
01050       if (h->smsc) {        /* deliver */
01051          h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
01052          p += packaddress (h->omsg + p, h->oa);
01053          h->omsg[p++] = h->pid;
01054          h->omsg[p++] = h->dcs;
01055          packdate (h->omsg + p, h->scts);
01056          p += 7;
01057          p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01058       } else {        /* submit */
01059          h->omsg[p++] =
01060             0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
01061          if (h->mr < 0)
01062             h->mr = message_ref++;
01063          h->omsg[p++] = h->mr;
01064          p += packaddress (h->omsg + p, h->da);
01065          h->omsg[p++] = h->pid;
01066          h->omsg[p++] = h->dcs;
01067          if (h->vp) {       /* relative VP */
01068             if (h->vp < 720)
01069                h->omsg[p++] = (h->vp + 4) / 5 - 1;
01070             else if (h->vp < 1440)
01071                h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
01072             else if (h->vp < 43200)
01073                h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
01074             else if (h->vp < 635040)
01075                h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
01076             else
01077                h->omsg[p++] = 255;     /* max */
01078          }
01079          p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01080       }
01081       h->omsg[1] = p - 2;
01082       sms_messagetx (h);
01083    } else {           /* no message */
01084       h->omsg[0] = 0x94;        /* SMS_REL */
01085       h->omsg[1] = 0;
01086       sms_messagetx (h);
01087    }
01088 }

static void sms_process ( sms_t h,
int  samples,
signed short *  data 
) [static]

Definition at line 1259 of file app_sms.c.

References ast_log(), sms_s::err, sms_s::hangup, sms_s::ibitc, sms_s::ibith, sms_s::ibitl, sms_s::ibitn, sms_s::ibitt, sms_s::ibytec, sms_s::ibytep, sms_s::ibytev, sms_s::idle, sms_s::ierr, sms_s::imag, sms_s::imc0, sms_s::imc1, sms_s::ims0, sms_s::ims1, sms_s::imsg, sms_s::ipc0, sms_s::ipc1, sms_s::iphasep, sms_s::ips0, sms_s::ips1, LOG_EVENT, m1, sms_s::obyten, sms_s::omsg, sms_s::osync, sms_messagerx(), and sms_messagetx().

01260 {
01261    if (h->obyten || h->osync)
01262       return;                  /* sending */
01263    while (samples--) {
01264       unsigned long long m0, m1;
01265       if (abs (*data) > h->imag)
01266          h->imag = abs (*data);
01267       else
01268          h->imag = h->imag * 7 / 8;
01269       if (h->imag > 500) {
01270          h->idle = 0;
01271          h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
01272          h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
01273          h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
01274          h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
01275          m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
01276          m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
01277          if ((h->ips0 += 21) >= 80)
01278             h->ips0 -= 80;
01279          if ((h->ipc0 += 21) >= 80)
01280             h->ipc0 -= 80;
01281          if ((h->ips1 += 13) >= 80)
01282             h->ips1 -= 80;
01283          if ((h->ipc1 += 13) >= 80)
01284             h->ipc1 -= 80;
01285          {
01286             char bit;
01287             h->ibith <<= 1;
01288             if (m1 > m0)
01289                h->ibith |= 1;
01290             if (h->ibith & 8)
01291                h->ibitt--;
01292             if (h->ibith & 1)
01293                h->ibitt++;
01294             bit = ((h->ibitt > 1) ? 1 : 0);
01295             if (bit != h->ibitl)
01296                h->ibitc = 1;
01297             else
01298                h->ibitc++;
01299             h->ibitl = bit;
01300             if (!h->ibitn && h->ibitc == 4 && !bit) {
01301                h->ibitn = 1;
01302                h->iphasep = 0;
01303             }
01304             if (bit && h->ibitc == 200) {                 /* sync, restart message */
01305                h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01306             }
01307             if (h->ibitn) {
01308                h->iphasep += 12;
01309                if (h->iphasep >= 80) {              /* next bit */
01310                   h->iphasep -= 80;
01311                   if (h->ibitn++ == 9) {            /* end of byte */
01312                      if (!bit)  /* bad stop bit */
01313                         h->ierr = 0xFF; /* unknown error */
01314                      else {
01315                         if (h->ibytep < sizeof (h->imsg)) {
01316                            h->imsg[h->ibytep] = h->ibytev;
01317                            h->ibytec += h->ibytev;
01318                            h->ibytep++;
01319                         } else if (h->ibytep == sizeof (h->imsg))
01320                            h->ierr = 2; /* bad message length */
01321                         if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
01322                            if (!h->ibytec)
01323                               sms_messagerx (h);
01324                            else
01325                               h->ierr = 1;      /* bad checksum */
01326                         }
01327                      }
01328                      h->ibitn = 0;
01329                   }
01330                   h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
01331                }
01332             }
01333          }
01334       } else {        /* lost carrier */
01335          if (h->idle++ == 80000) {      /* nothing happening */
01336             ast_log (LOG_EVENT, "No data, hanging up\n");
01337             h->hangup = 1;
01338             h->err = 1;
01339          }
01340          if (h->ierr) {                    /* error */
01341             h->err = 1;
01342             h->omsg[0] = 0x92;  /* error */
01343             h->omsg[1] = 1;
01344             h->omsg[2] = h->ierr;
01345             sms_messagetx (h);  /* send error */
01346          }
01347          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01348       }
01349       data++;
01350    }
01351 }

static void sms_readfile ( sms_t h,
char *  fn 
) [static]

parse and delete a file

Definition at line 675 of file app_sms.c.

References ast_log(), ast_mktime(), sms_s::da, sms_s::dcs, is16bit, is7bit, is8bit, LOG_EVENT, LOG_WARNING, sms_s::mr, numcpy(), sms_s::oa, packsms16(), packsms7(), packsms8(), sms_s::pid, sms_s::rp, sms_s::rx, S, s, sms_s::scts, SMSLEN, sms_s::srr, t, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, utf8decode(), and sms_s::vp.

Referenced by sms_nextoutgoing().

00676 {
00677    char line[1000];
00678    FILE *s;
00679    char dcsset = 0;            /* if DSC set */
00680    ast_log (LOG_EVENT, "Sending %s\n", fn);
00681    h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
00682    h->mr = -1;
00683    h->dcs = 0xF1;             /* normal messages class 1 */
00684    h->scts = time (0);
00685    s = fopen (fn, "r");
00686    if (s)
00687    {
00688       if (unlink (fn))
00689       {                        /* concurrent access, we lost */
00690          fclose (s);
00691          return;
00692       }
00693       while (fgets (line, sizeof (line), s))
00694       {                        /* process line in file */
00695          char *p;
00696          void *pp = &p;
00697          for (p = line; *p && *p != '\n' && *p != '\r'; p++);
00698          *p = 0;               /* strip eoln */
00699          p = line;
00700          if (!*p || *p == ';')
00701             continue;           /* blank line or comment, ignore */
00702          while (isalnum (*p))
00703          {
00704             *p = tolower (*p);
00705             p++;
00706          }
00707          while (isspace (*p))
00708             *p++ = 0;
00709          if (*p == '=')
00710          {
00711             *p++ = 0;
00712             if (!strcmp (line, "ud"))
00713             {                  /* parse message (UTF-8) */
00714                unsigned char o = 0;
00715                while (*p && o < SMSLEN)
00716                   h->ud[o++] = utf8decode(pp);
00717                h->udl = o;
00718                if (*p)
00719                   ast_log (LOG_WARNING, "UD too long in %s\n", fn);
00720             } else
00721             {
00722                while (isspace (*p))
00723                   p++;
00724                if (!strcmp (line, "oa") && strlen (p) < sizeof (h->oa))
00725                   numcpy (h->oa, p);
00726                else if (!strcmp (line, "da") && strlen (p) < sizeof (h->oa))
00727                   numcpy (h->da, p);
00728                else if (!strcmp (line, "pid"))
00729                   h->pid = atoi (p);
00730                else if (!strcmp (line, "dcs"))
00731                {
00732                   h->dcs = atoi (p);
00733                   dcsset = 1;
00734                } else if (!strcmp (line, "mr"))
00735                   h->mr = atoi (p);
00736                else if (!strcmp (line, "srr"))
00737                   h->srr = (atoi (p) ? 1 : 0);
00738                else if (!strcmp (line, "vp"))
00739                   h->vp = atoi (p);
00740                else if (!strcmp (line, "rp"))
00741                   h->rp = (atoi (p) ? 1 : 0);
00742                else if (!strcmp (line, "scts"))
00743                {               /* get date/time */
00744                   int Y,
00745                     m,
00746                     d,
00747                     H,
00748                     M,
00749                     S;
00750                   if (sscanf (p, "%30d-%30d-%30dT%30d:%30d:%30d", &Y, &m, &d, &H, &M, &S) == 6)
00751                   {
00752                      struct tm t;
00753                      t.tm_year = Y - 1900;
00754                      t.tm_mon = m - 1;
00755                      t.tm_mday = d;
00756                      t.tm_hour = H;
00757                      t.tm_min = M;
00758                      t.tm_sec = S;
00759                      t.tm_isdst = -1;
00760                      h->scts = ast_mktime(&t, NULL);
00761                      if (h->scts == (time_t) - 1)
00762                         ast_log (LOG_WARNING, "Bad date/timein %s: %s", fn, p);
00763                   }
00764                } else
00765                   ast_log (LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
00766             }
00767          } else if (*p == '#')
00768          {                     /* raw hex format */
00769             *p++ = 0;
00770             if (*p == '#')
00771             {
00772                p++;
00773                if (!strcmp (line, "ud"))
00774                {               /* user data */
00775                   int o = 0;
00776                   while (*p && o < SMSLEN)
00777                   {
00778                      if (isxdigit (*p) && isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3]))
00779                      {
00780                         h->ud[o++] =
00781                            (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 12) +
00782                            (((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
00783                            (((isalpha (p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha (p[3]) ? 9 : 0) + (p[3] & 0xF));
00784                         p += 4;
00785                      } else
00786                         break;
00787                   }
00788                   h->udl = o;
00789                   if (*p)
00790                      ast_log (LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
00791                } else
00792                   ast_log (LOG_WARNING, "Only ud can use ## format, %s\n", fn);
00793             } else if (!strcmp (line, "ud"))
00794             {                  /* user data */
00795                int o = 0;
00796                while (*p && o < SMSLEN)
00797                {
00798                   if (isxdigit (*p) && isxdigit (p[1]))
00799                   {
00800                      h->ud[o++] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
00801                      p += 2;
00802                   } else
00803                      break;
00804                }
00805                h->udl = o;
00806                if (*p)
00807                   ast_log (LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
00808             } else if (!strcmp (line, "udh"))
00809             {                  /* user data header */
00810                unsigned char o = 0;
00811                h->udhi = 1;
00812                while (*p && o < SMSLEN)
00813                {
00814                   if (isxdigit (*p) && isxdigit (p[1]))
00815                   {
00816                      h->udh[o] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
00817                      o++;
00818                      p += 2;
00819                   } else
00820                      break;
00821                }
00822                h->udhl = o;
00823                if (*p)
00824                   ast_log (LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
00825             } else
00826                ast_log (LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
00827          } else
00828             ast_log (LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
00829       }
00830       fclose (s);
00831       if (!dcsset && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00832       {
00833          if (packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00834          {
00835             if (packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00836                ast_log (LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
00837             else
00838             {
00839                h->dcs = 0x08; /* default to 16 bit */
00840                ast_log (LOG_WARNING, "Sending in 16 bit format (%s)\n", fn);
00841             }
00842          } else
00843          {
00844             h->dcs = 0xF5;    /* default to 8 bit */
00845             ast_log (LOG_WARNING, "Sending in 8 bit format (%s)\n", fn);
00846          }
00847       }
00848       if (is7bit (h->dcs) && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00849          ast_log (LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
00850       if (is8bit (h->dcs) && packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00851          ast_log (LOG_WARNING, "Invalid 8 bit data %s\n", fn);
00852       if (is16bit (h->dcs) && packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00853          ast_log (LOG_WARNING, "Invalid 16 bit data %s\n", fn);
00854    }
00855 }

static void sms_release ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 189 of file app_sms.c.

00190 {
00191    return;
00192 }

static void sms_writefile ( sms_t h  )  [static]

white a received text message to a file

Definition at line 858 of file app_sms.c.

References ast_copy_string(), sms_s::da, isodate(), sms_s::oa, sms_s::queue, sms_s::rx, sms_s::scts, sms_s::smsc, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, and sms_s::udl.

Referenced by sms_handleincoming().

00859 {
00860    char fn[200] = "", fn2[200] = "";
00861    FILE *o;
00862    ast_copy_string (fn, spool_dir, sizeof (fn));
00863    mkdir (fn, 0777);       /* ensure it exists */
00864    snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
00865    mkdir (fn, 0777);       /* ensure it exists */
00866    ast_copy_string (fn2, fn, sizeof (fn2));
00867    snprintf (fn2 + strlen (fn2), sizeof (fn2) - strlen (fn2), "/%s.%s-%d", h->queue, isodate (h->scts), seq++);
00868    snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/.%s", fn2 + strlen (fn) + 1);
00869    o = fopen (fn, "w");
00870    if (o) {
00871       if (*h->oa)
00872          fprintf (o, "oa=%s\n", h->oa);
00873       if (*h->da)
00874          fprintf (o, "da=%s\n", h->da);
00875       if (h->udhi) {
00876          unsigned int p;
00877          fprintf (o, "udh#");
00878          for (p = 0; p < h->udhl; p++)
00879             fprintf (o, "%02X", h->udh[p]);
00880          fprintf (o, "\n");
00881       }
00882       if (h->udl) {
00883          unsigned int p;
00884          for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00885          if (p < h->udl)
00886             fputc (';', o);     /* cannot use ud=, but include as a comment for human readable */
00887          fprintf (o, "ud=");
00888          for (p = 0; p < h->udl; p++) {
00889             unsigned short v = h->ud[p];
00890             if (v < 32)
00891                fputc (191, o);
00892             else if (v < 0x80)
00893                fputc (v, o);
00894             else if (v < 0x800)
00895             {
00896                fputc (0xC0 + (v >> 6), o);
00897                fputc (0x80 + (v & 0x3F), o);
00898             } else
00899             {
00900                fputc (0xE0 + (v >> 12), o);
00901                fputc (0x80 + ((v >> 6) & 0x3F), o);
00902                fputc (0x80 + (v & 0x3F), o);
00903             }
00904          }
00905          fprintf (o, "\n");
00906          for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00907          if (p < h->udl) {
00908             for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
00909             if (p == h->udl) {                   /* can write in ucs-1 hex */
00910                fprintf (o, "ud#");
00911                for (p = 0; p < h->udl; p++)
00912                   fprintf (o, "%02X", h->ud[p]);
00913                fprintf (o, "\n");
00914             } else {                 /* write in UCS-2 */
00915                fprintf (o, "ud##");
00916                for (p = 0; p < h->udl; p++)
00917                   fprintf (o, "%04X", h->ud[p]);
00918                fprintf (o, "\n");
00919             }
00920          }
00921       }
00922       if (h->scts)
00923          fprintf (o, "scts=%s\n", isodate (h->scts));
00924       if (h->pid)
00925          fprintf (o, "pid=%d\n", h->pid);
00926       if (h->dcs != 0xF1)
00927          fprintf (o, "dcs=%d\n", h->dcs);
00928       if (h->vp)
00929          fprintf (o, "vp=%d\n", h->vp);
00930       if (h->srr)
00931          fprintf (o, "srr=1\n");
00932       if (h->mr >= 0)
00933          fprintf (o, "mr=%d\n", h->mr);
00934       if (h->rp)
00935          fprintf (o, "rp=1\n");
00936       fclose (o);
00937       if (rename (fn, fn2))
00938          unlink (fn);
00939       else
00940          ast_log (LOG_EVENT, "Received to %s\n", fn2);
00941    }
00942 }

static int unload_module ( void   )  [static]

Definition at line 1519 of file app_sms.c.

References ast_module_user_hangup_all, and ast_unregister_application().

01520 {
01521    int res;
01522 
01523    res = ast_unregister_application (app);
01524    
01525    ast_module_user_hangup_all();
01526 
01527    return res; 
01528 }

static unsigned char unpackaddress ( char *  o,
unsigned char *  i 
) [static]

unpack an address from i, return byte length, unpack to o

Definition at line 593 of file app_sms.c.

Referenced by sms_handleincoming().

00594 {
00595    unsigned char l = i[0],
00596       p;
00597    if (i[1] == 0x91)
00598       *o++ = '+';
00599    for (p = 0; p < l; p++) {
00600       if (p & 1)
00601          *o++ = (i[2 + p / 2] >> 4) + '0';
00602       else
00603          *o++ = (i[2 + p / 2] & 0xF) + '0';
00604    }
00605    *o = 0;
00606    return (l + 5) / 2;
00607 }

static time_t unpackdate ( unsigned char *  i  )  [static]

unpack a date and return

Definition at line 456 of file app_sms.c.

References ast_mktime().

Referenced by sms_handleincoming().

00457 {
00458    struct tm t;
00459    t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
00460    t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
00461    t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
00462    t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
00463    t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
00464    t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
00465    t.tm_isdst = 0;
00466    if (i[6] & 0x08)
00467       t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00468    else
00469       t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00470    return ast_mktime(&t, NULL);
00471 }

static int unpacksms ( unsigned char  dcs,
unsigned char *  i,
unsigned char *  udh,
int *  udhl,
unsigned short *  ud,
int *  udl,
char  udhi 
) [static]

general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length

Definition at line 579 of file app_sms.c.

References is7bit, is8bit, unpacksms16(), unpacksms7(), and unpacksms8().

Referenced by sms_handleincoming().

00580 {
00581    int l = *i++;
00582    if (is7bit (dcs)) {
00583       unpacksms7 (i, l, udh, udhl, ud, udl, udhi);
00584       l = (l * 7 + 7) / 8;    /* adjust length to return */
00585    } else if (is8bit (dcs))
00586       unpacksms8 (i, l, udh, udhl, ud, udl, udhi);
00587    else
00588       unpacksms16 (i, l, udh, udhl, ud, udl, udhi);
00589    return l + 1;
00590 }

static void unpacksms16 ( unsigned char *  i,
unsigned char  l,
unsigned char *  udh,
int *  udhl,
unsigned short *  ud,
int *  udl,
char  udhi 
) [static]

unpacks bytes (16 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set

Definition at line 552 of file app_sms.c.

Referenced by unpacksms().

00553 {
00554    unsigned short *o = ud;
00555    *udhl = 0;
00556    if (udhi) {
00557       int n = *i;
00558       *udhl = n;
00559       if (n) {
00560          i++;
00561          l--;
00562          while (l && n) {
00563             l--;
00564             n--;
00565             *udh++ = *i++;
00566          }
00567       }
00568    }
00569    while (l--) {
00570       int v = *i++;
00571       if (l--)
00572          v = (v << 8) + *i++;
00573       *o++ = v;
00574    }
00575    *udl = (o - ud);
00576 }

static void unpacksms7 ( unsigned char *  i,
unsigned char  l,
unsigned char *  udh,
int *  udhl,
unsigned short *  ud,
int *  udl,
char  udhi 
) [static]

unpacks bytes (7 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set

Definition at line 476 of file app_sms.c.

Referenced by unpacksms().

00477 {
00478    unsigned char b = 0, p = 0;
00479    unsigned short *o = ud;
00480    *udhl = 0;
00481    if (udhi && l) {      /* header */
00482       int h = i[p];
00483       *udhl = h;
00484       if (h) {
00485          b = 1;
00486          p++;
00487          l--;
00488          while (h-- && l) {
00489             *udh++ = i[p++];
00490             b += 8;
00491             while (b >= 7) {
00492                b -= 7;
00493                l--;
00494                if (!l)
00495                   break;
00496             }
00497          }
00498          /* adjust for fill, septets */
00499          if (b) {
00500             b = 7 - b;
00501             l--;
00502          }
00503       }
00504    }
00505    while (l--) {
00506       unsigned char v;
00507       if (b < 2)
00508          v = ((i[p] >> b) & 0x7F);
00509       else
00510          v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
00511       b += 7;
00512       if (b >= 8) {
00513          b -= 8;
00514          p++;
00515       }
00516       if (o > ud && o[-1] == 0x00A0 && escapes[v])
00517          o[-1] = escapes[v];
00518       else
00519          *o++ = defaultalphabet[v];
00520    }
00521    *udl = (o - ud);
00522 }

static void unpacksms8 ( unsigned char *  i,
unsigned char  l,
unsigned char *  udh,
int *  udhl,
unsigned short *  ud,
int *  udl,
char  udhi 
) [static]

unpacks bytes (8 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set

Definition at line 527 of file app_sms.c.

Referenced by unpacksms().

00528 {
00529    unsigned short *o = ud;
00530    *udhl = 0;
00531    if (udhi) {
00532       int n = *i;
00533       *udhl = n;
00534       if (n) {
00535          i++;
00536          l--;
00537          while (l && n) {
00538             l--;
00539             n--;
00540             *udh++ = *i++;
00541          }
00542       }
00543    }
00544    while (l--)
00545       *o++ = *i++;     /* not to UTF-8 as explicitely 8 bit coding in DCS */
00546    *udl = (o - ud);
00547 }

static long utf8decode ( unsigned char **  pp  )  [static]

reads next UCS character from null terminated UTF-8 string and advanced pointer

Definition at line 220 of file app_sms.c.

Referenced by sms_readfile().

00221 {
00222    unsigned char *p = *pp;
00223    if (!*p)
00224       return 0;                 /* null termination of string */
00225    (*pp)++;
00226    if (*p < 0xC0)
00227       return *p;                /* ascii or continuation character */
00228    if (*p < 0xE0) {
00229       if (*p < 0xC2 || (p[1] & 0xC0) != 0x80)
00230          return *p;             /* not valid UTF-8 */
00231       (*pp)++;
00232       return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
00233       }
00234    if (*p < 0xF0) {
00235       if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80)
00236           return *p;             /* not valid UTF-8 */
00237       (*pp) += 2;
00238       return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
00239    }
00240    if (*p < 0xF8) {
00241       if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80)
00242          return *p;             /* not valid UTF-8 */
00243       (*pp) += 3;
00244       return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
00245    }
00246    if (*p < 0xFC) {
00247       if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00248          || (p[4] & 0xC0) != 0x80)
00249          return *p;             /* not valid UTF-8 */
00250       (*pp) += 4;
00251       return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
00252    }
00253    if (*p < 0xFE) {
00254       if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00255          || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80)
00256          return *p;             /* not valid UTF-8 */
00257       (*pp) += 5;
00258       return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
00259    }
00260    return *p;                   /* not sensible */
00261 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "SMS/PSTN handler" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 1544 of file app_sms.c.

char* app = "SMS" [static]

Definition at line 64 of file app_sms.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1544 of file app_sms.c.

const unsigned short defaultalphabet[] [static]

Definition at line 98 of file app_sms.c.

char* descrip [static]

Definition at line 68 of file app_sms.c.

const unsigned short escapes[] [static]

Definition at line 111 of file app_sms.c.

char log_file[255] [static]

Definition at line 61 of file app_sms.c.

volatile unsigned char message_ref [static]

Definition at line 58 of file app_sms.c.

volatile unsigned int seq [static]

Definition at line 59 of file app_sms.c.

Referenced by ast_udptl_write(), handle_link_data(), handle_remote_data(), and udptl_build_packet().

struct ast_generator smsgen [static]

Initial value:

 {
   alloc:sms_alloc,
   release:sms_release,
   generate:sms_generate,
}

Definition at line 1353 of file app_sms.c.

char spool_dir[255] [static]

Definition at line 62 of file app_sms.c.

char* synopsis = "Communicates with SMS service centres and SMS capable analogue phones" [static]

Definition at line 66 of file app_sms.c.

signed short wave[] [static]

Definition at line 83 of file app_sms.c.

Referenced by festival_exec().


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