Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:15 2009

## Asterisk developer's documentation

# app_sms.c File Reference

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

`#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.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"`

Include dependency graph for app_sms.c:

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 struct sms_s | sms_t

## Functions

char * | description (void)
| Provides a description of the module.
static char * | isodate (time_t t)
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module (void)
| Initialize the module.
static void | numcpy (char *d, char *s)
static unsigned char | packaddress (unsigned char *o, char *i)
static void | packdate (unsigned char *o, time_t w)
static int | packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
static int | packsms16 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
static int | packsms7 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
static int | packsms8 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
static struct dirent * | readdirqueue (DIR *d, char *queue)
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)
static void | sms_log (sms_t *h, char status)
static void | sms_messagerx (sms_t *h)
static void | sms_messagetx (sms_t *h)
static void | sms_nextoutgoing (sms_t *h)
static void | sms_process (sms_t *h, int samples, signed short *data)
static void | sms_readfile (sms_t *h, char *fn)
static void | sms_release (struct ast_channel *chan, void *data)
static void | sms_writefile (sms_t *h)
int | unload_module (void)
| Cleanup all module structures, sockets, etc.
static unsigned char | unpackaddress (char *o, unsigned char *i)
static time_t | unpackdate (unsigned char *i)
static int | unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
static void | unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
static void | unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
static void | unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
int | usecount (void)
| Provides a usecount.
static long | utf8decode (unsigned char **pp)

## Variables

static char * | app = "SMS"
static const unsigned short | defaultalphabet []
static char * | descrip
static const unsigned short | escapes []
| LOCAL_USER_DECL
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]
| STANDARD_LOCAL_USER
static char * | synopsis = "Communicates with SMS service centres and SMS capable analogue phones"
static char * | tdesc = "SMS/PSTN handler"
static signed short | wave []

## Detailed Description

SMS application - ETSI ES 201 912 protocol 1 implimentation.

Definition in file app_sms.c.

## Define Documentation

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

Definition at line 186 of file app_sms.c.

Referenced by sms_exec(), and sms_readfile().

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

Definition at line 184 of file app_sms.c.

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

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

Definition at line 185 of file app_sms.c.

Referenced by packsms(), sms_exec(), 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 126 of file app_sms.c.

Referenced by packsms7(), sms_exec(), and sms_readfile().

## Typedef Documentation

typedef struct sms_s sms_t

## Function Documentation

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 1539 of file app_sms.c.

References tdesc.

    01540 {
    01541    return tdesc;
    01542 }

static char* isodate | ( | time_t | t | ) | `[static]`

Definition at line 214 of file app_sms.c.

Referenced by sms_log(), and sms_writefile().

    00215 {
    00216    static char date[20];
    00217    strftime (date, sizeof (date), "%Y-%m-%dT%H:%M:%S", localtime (&t));
    00218    return date;
    00219 }

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 1551 of file app_sms.c.

References ASTERISK_GPL_KEY.

    01552 {
    01553    return ASTERISK_GPL_KEY;
    01554 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
  int Always 0.

TE STUFF END

Definition at line 1525 of file app_sms.c.

References app, ast_config_AST_LOG_DIR, ast_config_AST_SPOOL_DIR, AST_LIN2A, ast_register_application(), descrip, log_file, sms_exec(), spool_dir, synopsis, and wave.

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

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

Definition at line 201 of file app_sms.c.

Referenced by sms_readfile().

    00202 {
    00203    if (*s == '+')
    00204       *d++ = *s++;
    00205    while (*s) {
    00206       if (isdigit (*s))
    00207             *d++ = *s;
    00208       s++;
    00209    }
    00210    *d = 0;
    00211 }

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

Definition at line 614 of file app_sms.c.

Referenced by sms_nextoutgoing().

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

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

Definition at line 439 of file app_sms.c.

References t.

Referenced by sms_nextoutgoing().

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

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

Definition at line 408 of file app_sms.c.

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

Referenced by sms_nextoutgoing().

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

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

Definition at line 377 of file app_sms.c.

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

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

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

Definition at line 271 of file app_sms.c.

References n, and SMSLEN.

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

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

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

Definition at line 341 of file app_sms.c.

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

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

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

Definition at line 946 of file app_sms.c.

Referenced by sms_nextoutgoing().

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

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

Definition at line 188 of file app_sms.c.

    00189 {
    00190    return params;
    00191 }

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

Definition at line 1092 of file app_sms.c.

References ast_verbose(), n, option_verbose, and VERBOSE_PREFIX_3.

Referenced by sms_messagerx(), and sms_messagetx().

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

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

Definition at line 1360 of file app_sms.c.

References ast_channel::_state, answer, ast_activate_generator(), ast_answer(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_set_read_format(), ast_set_write_format(), AST_STATE_UP, ast_waitfor(), ast_channel::cid, ast_callerid::cid_num, sms_s::cli, sms_s::da, ast_frame::data, sms_s::dcs, sms_s::err, ast_frame::frametype, sms_s::hangup, sms_s::ipc0, sms_s::ipc1, is16bit, is7bit, is8bit, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_WARNING, sms_s::mr, ast_channel::name, sms_s::oa, sms_s::omsg, packsms16(), packsms7(), packsms8(), sms_s::pid, sms_s::queue, sms_s::rx, ast_frame::samples, sms_s::scts, sms_log(), sms_messagetx(), sms_process(), sms_writefile(), sms_s::smsc, SMSLEN, sms_s::srr, sms_s::ud, sms_s::udh, sms_s::udhl, sms_s::udl, and utf8decode().

Referenced by load_module().

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

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

Definition at line 1178 of file app_sms.c.

References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, MAXSAMPLES, ast_channel::name, sms_s::obitp, sms_s::obyte, sms_s::obyten, sms_s::obytep, ast_frame::offset, sms_s::omsg, sms_s::opause, sms_s::ophase, sms_s::ophasep, sms_s::osync, SAMPLE2LEN, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

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

static unsigned char sms_handleincoming | ( | sms_t * | h | ) | `[static]`

Definition at line 956 of file app_sms.c.

References 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().

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

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

Definition at line 639 of file app_sms.c.

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

Referenced by sms_exec(), and sms_messagerx().

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

static void sms_messagerx | ( | sms_t * | h | ) | `[static]`

Definition at line 1108 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().

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

static void sms_messagetx | ( | sms_t * | h | ) | `[static]`

Definition at line 1161 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_exec(), sms_messagerx(), sms_nextoutgoing(), and sms_process().

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

static void sms_nextoutgoing | ( | sms_t * | h | ) | `[static]`

Definition at line 1028 of file app_sms.c.

References sms_s::da, sms_s::dcs, 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().

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

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

Definition at line 1260 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().

Referenced by sms_exec().

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

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

Definition at line 677 of file app_sms.c.

References ast_log(), 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, sms_s::scts, SMSLEN, sms_s::srr, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, utf8decode(), and sms_s::vp.

Referenced by sms_nextoutgoing().

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

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

Definition at line 193 of file app_sms.c.

    00194 {
    00195    return;
    00196 }

static void sms_writefile | ( | sms_t * | h | ) | `[static]`

Definition at line 859 of file app_sms.c.

References ast_log(), sms_s::da, sms_s::dcs, isodate(), LOG_EVENT, sms_s::mr, sms_s::oa, sms_s::pid, sms_s::queue, sms_s::rp, sms_s::rx, sms_s::scts, 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_exec(), and sms_handleincoming().

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

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
  Zero on success, or non-zero on error.

Definition at line 1514 of file app_sms.c.

References app, ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

    01515 {
    01516    int res;
    01517
    01518    res = ast_unregister_application (app);
    01519
    01520    STANDARD_HANGUP_LOCALUSERS;
    01521
    01522    return res;
    01523 }

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

Definition at line 597 of file app_sms.c.

Referenced by sms_handleincoming().

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

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

Definition at line 460 of file app_sms.c.

Referenced by sms_handleincoming().

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

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

Definition at line 583 of file app_sms.c.

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

Referenced by sms_handleincoming().

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

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

Definition at line 556 of file app_sms.c.

References n.

Referenced by unpacksms().

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

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

Definition at line 480 of file app_sms.c.

Referenced by unpacksms().

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

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

Definition at line 531 of file app_sms.c.

References n.

Referenced by unpacksms().

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

int usecount | ( | void |  | ) |

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
  The module's usecount.

Definition at line 1544 of file app_sms.c.

References STANDARD_USECOUNT.

    01545 {
    01546    int res;
    01547    STANDARD_USECOUNT (res);
    01548    return res;
    01549 }

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

Definition at line 224 of file app_sms.c.

Referenced by sms_exec(), and sms_readfile().

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

## Variable Documentation

char* app = "SMS"`[static]`

Definition at line 65 of file app_sms.c.

const unsigned short defaultalphabet[]`[static]`

Definition at line 102 of file app_sms.c.

char* descrip`[static]`

Definition at line 69 of file app_sms.c.

const unsigned short escapes[]`[static]`

Definition at line 115 of file app_sms.c.

LOCAL_USER_DECL

Definition at line 99 of file app_sms.c.

char log_file[255]`[static]`

Definition at line 60 of file app_sms.c.

Referenced by load_module().

volatile unsigned char message_ref`[static]`

Definition at line 57 of file app_sms.c.

volatile unsigned int seq`[static]`

Definition at line 58 of file app_sms.c.

Referenced by handle_link_data(), and handle_remote_data().

struct ast_generator smsgen`[static]`

Initial value:

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

Definition at line 1354 of file app_sms.c.

char spool_dir[255]`[static]`

Definition at line 61 of file app_sms.c.

Referenced by load_module().

STANDARD_LOCAL_USER

Definition at line 97 of file app_sms.c.

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

Definition at line 67 of file app_sms.c.

char* tdesc = "SMS/PSTN handler"`[static]`

Definition at line 63 of file app_sms.c.

signed short wave[]`[static]`

Definition at line 84 of file app_sms.c.

Referenced by festival_exec(), and load_module().