Mon Mar 20 08:25:48 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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"

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 SMSLEN   160

Typedefs

typedef sms_s sms_t

Functions

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

Variables

char * app = "SMS"
const unsigned short defaultalphabet []
char * descrip
const unsigned short escapes []
 LOCAL_USER_DECL
char log_file [255]
volatile unsigned char message_ref
volatile unsigned int seq
ast_generator smsgen
char spool_dir [255]
 STANDARD_LOCAL_USER
char * synopsis = "Communicates with SMS service centres and SMS capable analogue phones"
char * tdesc = "SMS/PSTN handler"
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 SMSLEN   160
 

Definition at line 126 of file app_sms.c.


Typedef Documentation

typedef struct sms_s sms_t
 

Referenced by sms_exec(), sms_generate(), sms_handleincoming(), sms_log(), sms_messagerx(), sms_messagetx(), sms_nextoutgoing(), sms_process(), sms_readfile(), and sms_writefile().


Function Documentation

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 1540 of file app_sms.c.

01541 {
01542    return tdesc;
01543 }

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 1552 of file app_sms.c.

01553 {
01554    return ASTERISK_GPL_KEY;
01555 }

int load_module void   ) 
 

Initialize the module.

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.

Definition at line 1526 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.

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

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

Definition at line 201 of file app_sms.c.

References s.

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 }

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 }

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

Definition at line 439 of file app_sms.c.

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 }

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 }

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 }

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 defaultalphabet, and escapes.

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 }

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 }

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

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 }

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

Definition at line 188 of file app_sms.c.

00189 {
00190    return params;
00191 }

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

Definition at line 1092 of file app_sms.c.

References ast_verbose(), 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 }

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

Definition at line 1361 of file app_sms.c.

References ast_channel::_state, ast_activate_generator(), ast_answer(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_frfree(), ast_log(), ast_read(), ast_set_read_format(), ast_set_write_format(), 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_t, sms_writefile(), sms_s::smsc, smsgen, sms_s::srr, sms_s::ud, sms_s::udh, sms_s::udhl, sms_s::udl, and utf8decode().

Referenced by load_module().

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

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_log(), ast_write(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, 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, ast_frame::samples, sms_t, ast_frame::src, ast_frame::subclass, and wave.

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

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_t, 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 }

void sms_log sms_t h,
char  status
[static]
 

Definition at line 639 of file app_sms.c.

References sms_s::da, isodate(), log_file, sms_s::mr, sms_s::oa, sms_s::queue, sms_s::rx, sms_t, 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 }

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(), sms_nextoutgoing(), and sms_t.

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 }

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, sms_debug(), and sms_t.

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 }

void sms_nextoutgoing sms_t h  )  [static]
 

Definition at line 1028 of file app_sms.c.

References sms_s::da, sms_s::dcs, message_ref, 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_t, sms_s::smsc, spool_dir, 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);
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 }

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

Definition at line 1261 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(), sms_messagetx(), sms_t, and wave.

Referenced by sms_exec().

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

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, sms_t, 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, "%d-%d-%dT%d:%d:%d", &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 }

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

Definition at line 193 of file app_sms.c.

00194 {
00195    return;
00196 }

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, seq, sms_t, sms_s::smsc, spool_dir, 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 1515 of file app_sms.c.

References app, and ast_unregister_application().

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

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 }

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 }

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 }

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.

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 }

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.

References defaultalphabet, and escapes.

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 }

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.

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 1545 of file app_sms.c.

References STANDARD_USECOUNT.

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

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.

Referenced by load_module(), and unload_module().

const unsigned short defaultalphabet[] [static]
 

Definition at line 102 of file app_sms.c.

Referenced by packsms7(), and unpacksms7().

char* descrip [static]
 

Definition at line 69 of file app_sms.c.

Referenced by load_module().

const unsigned short escapes[] [static]
 

Definition at line 115 of file app_sms.c.

Referenced by packsms7(), and unpacksms7().

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(), and sms_log().

volatile unsigned char message_ref [static]
 

Definition at line 57 of file app_sms.c.

Referenced by sms_nextoutgoing().

volatile unsigned int seq [static]
 

Definition at line 58 of file app_sms.c.

Referenced by sms_writefile().

struct ast_generator smsgen [static]
 

Initial value:

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

Definition at line 1355 of file app_sms.c.

Referenced by sms_exec().

char spool_dir[255] [static]
 

Definition at line 61 of file app_sms.c.

Referenced by load_module(), sms_nextoutgoing(), and sms_writefile().

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.

Referenced by load_module().

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 load_module(), sms_generate(), and sms_process().


Generated on Mon Mar 20 08:25:48 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1