Thu Oct 11 06:34:32 2012

Asterisk developer's documentation


app_sms.c File Reference

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

#include "asterisk.h"
#include <dirent.h>
#include <ctype.h>
#include <sys/stat.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"

Include dependency graph for app_sms.c:

Go to the source code of this file.

Data Structures

struct  sms_s

Defines

#define __OUT_FMT   AST_FORMAT_SLINEAR
#define DIR_RX   1
#define DIR_TX   2
#define DLL2_ACK(h)   ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
#define is16bit(dcs)   ( ((dcs) & 0xC0) ? 0 : (((dcs) & 0xc) == 8) )
#define is7bit(dcs)   ( ((dcs) & 0xC0) ? (!((dcs) & 4) ) : (((dcs) & 0xc) == 0) )
#define is8bit(dcs)   ( ((dcs) & 0xC0) ? ( ((dcs) & 4) ) : (((dcs) & 0xc) == 4) )
#define MAX_DEBUG_LEN   300
#define MAXSAMPLES   (800)
#define OSYNC_BITS   80
#define SMSLEN   160
#define SMSLEN_8   140

Typedefs

typedef signed short output_t
typedef struct sms_s sms_t

Enumerations

enum  message_types {
  DLL_SMS_MASK = 0x7f, DLL1_SMS_DATA = 0x11, DLL1_SMS_ERROR = 0x12, DLL1_SMS_EST = 0x13,
  DLL1_SMS_REL = 0x14, DLL1_SMS_ACK = 0x15, DLL1_SMS_NACK = 0x16, DLL1_SMS_COMPLETE = 0x80,
  DLL1_SMS_MORE = 0x00, DLL2_SMS_EST = 0x7f, DLL2_SMS_INFO_MO = 0x10, DLL2_SMS_INFO_MT = 0x11,
  DLL2_SMS_INFO_STA = 0x12, DLL2_SMS_NACK = 0x13, DLL2_SMS_ACK0 = 0x14, DLL2_SMS_ACK1 = 0x15,
  DLL2_SMS_ENQ = 0x16, DLL2_SMS_REL = 0x17, DLL2_SMS_COMPLETE = 0x00, DLL2_SMS_MORE = 0x80
}
enum  sms_flags {
  OPTION_BE_SMSC = (1 << 0), OPTION_ANSWER = (1 << 1), OPTION_TWO = (1 << 2), OPTION_PAUSE = (1 << 3),
  OPTION_SRR = (1 << 4), OPTION_DCS = (1 << 5)
}
enum  sms_opt_args { OPTION_ARG_PAUSE = 0, OPTION_ARG_ARRAY_SIZE }

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "SMS/PSTN handler" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static char * app = "SMS"
static struct ast_module_infoast_module_info = &__mod_info
static const unsigned short defaultalphabet []
static const unsigned short escapes []
static char log_file [255]
static volatile unsigned char message_ref
static volatile unsigned int seq
static struct ast_app_option sms_options [128] = { [ 's' ] = { .flag = OPTION_BE_SMSC }, [ 'a' ] = { .flag = OPTION_ANSWER }, [ 't' ] = { .flag = OPTION_TWO }, [ 'r' ] = { .flag = OPTION_SRR }, [ 'o' ] = { .flag = OPTION_DCS }, [ 'p' ] = { .flag = OPTION_PAUSE , .arg_index = OPTION_ARG_PAUSE + 1 }, }
static struct ast_generator smsgen
static const signed short wave []
static const output_twave_out = wave


Detailed Description

SMS application - ETSI ES 201 912 protocol 1 implementation.

Development notes
Note:
The ETSI standards are available free of charge from ETSI at http://pda.etsi.org/pda/queryform.asp Among the relevant documents here we have:
ES 201 912 SMS for PSTN/ISDN TS 123 040 Technical realization of SMS

Author:
Adrian Kennard (for the original protocol 1 code)

Filippo Grassilli (Hyppo) - protocol 2 support Not fully tested, under development

Definition in file app_sms.c.


Define Documentation

#define __OUT_FMT   AST_FORMAT_SLINEAR

Definition at line 147 of file app_sms.c.

Referenced by sms_generate().

#define DIR_RX   1

Definition at line 1472 of file app_sms.c.

Referenced by sms_debug(), and sms_messagerx().

#define DIR_TX   2

Definition at line 1473 of file app_sms.c.

Referenced by sms_messagetx().

#define DLL2_ACK (  )     ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)

Referenced by sms_messagerx2().

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

Definition at line 279 of file app_sms.c.

Referenced by sms_readfile().

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

Definition at line 277 of file app_sms.c.

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

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

Definition at line 278 of file app_sms.c.

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

#define MAX_DEBUG_LEN   300

Definition at line 1238 of file app_sms.c.

Referenced by sms_handleincoming_proto2(), and sms_hexdump().

#define MAXSAMPLES   (800)

Referenced by sms_generate().

#define OSYNC_BITS   80

Definition at line 150 of file app_sms.c.

Referenced by sms_messagetx().

#define SMSLEN   160

max SMS length

Definition at line 213 of file app_sms.c.

Referenced by packsms7(), and sms_readfile().

#define SMSLEN_8   140

max SMS length for 8-bit char

Definition at line 214 of file app_sms.c.

Referenced by packsms16(), and packsms8().


Typedef Documentation

typedef signed short output_t

Definition at line 145 of file app_sms.c.

typedef struct sms_s sms_t


Enumeration Type Documentation

The SMS spec ETSI ES 201 912 defines two protocols with different message types. Also note that the high bit is used to indicate whether the message is complete or not, but in two opposite ways: for Protocol 1, 0x80 means that the message is complete; for Protocol 2, 0x00 means that the message is complete;

Enumerator:
DLL_SMS_MASK 
DLL1_SMS_DATA 
DLL1_SMS_ERROR 
DLL1_SMS_EST 
DLL1_SMS_REL 
DLL1_SMS_ACK 
DLL1_SMS_NACK 
DLL1_SMS_COMPLETE 
DLL1_SMS_MORE 
DLL2_SMS_EST 
DLL2_SMS_INFO_MO 
DLL2_SMS_INFO_MT 
DLL2_SMS_INFO_STA 
DLL2_SMS_NACK 
DLL2_SMS_ACK0 
DLL2_SMS_ACK1 
DLL2_SMS_ENQ 
DLL2_SMS_REL 
DLL2_SMS_COMPLETE 
DLL2_SMS_MORE 

Definition at line 159 of file app_sms.c.

00159                    {
00160    DLL_SMS_MASK        = 0x7f,             /* mask for the valid bits */
00161 
00162    /* Protocol 1 values */
00163    DLL1_SMS_DATA       = 0x11,             /* data packet */
00164    DLL1_SMS_ERROR      = 0x12,
00165    DLL1_SMS_EST        = 0x13,             /* start the connection */
00166    DLL1_SMS_REL        = 0x14,             /* end the connection */
00167    DLL1_SMS_ACK        = 0x15,
00168    DLL1_SMS_NACK       = 0x16,
00169 
00170    DLL1_SMS_COMPLETE   = 0x80,             /* packet is complete */
00171    DLL1_SMS_MORE       = 0x00,             /* more data to follow */
00172 
00173    /* Protocol 2 values */
00174    DLL2_SMS_EST        = 0x7f,             /* magic number. No message body */
00175    DLL2_SMS_INFO_MO    = 0x10,
00176    DLL2_SMS_INFO_MT    = 0x11,
00177    DLL2_SMS_INFO_STA   = 0x12,
00178    DLL2_SMS_NACK       = 0x13,
00179    DLL2_SMS_ACK0       = 0x14,             /* ack even-numbered frame */
00180    DLL2_SMS_ACK1       = 0x15,             /* ack odd-numbered frame */
00181    DLL2_SMS_ENQ        = 0x16,
00182    DLL2_SMS_REL        = 0x17,             /* end the connection */
00183 
00184    DLL2_SMS_COMPLETE   = 0x00,             /* packet is complete */
00185    DLL2_SMS_MORE       = 0x80,             /* more data to follow */
00186 };

enum sms_flags

Enumerator:
OPTION_BE_SMSC 
OPTION_ANSWER 
OPTION_TWO 
OPTION_PAUSE 
OPTION_SRR 
OPTION_DCS 

Definition at line 1839 of file app_sms.c.

01839                {
01840    OPTION_BE_SMSC = (1 << 0),             /* act as sms center */
01841    OPTION_ANSWER  = (1 << 1),             /* answer on incoming calls */
01842    OPTION_TWO  = (1 << 2),                 /* Use Protocol Two */
01843    OPTION_PAUSE   = (1 << 3),             /* pause before sending data, in ms */
01844    OPTION_SRR  = (1 << 4),                 /* set srr */
01845    OPTION_DCS  = (1 << 5),                 /* set dcs */
01846 };

Enumerator:
OPTION_ARG_PAUSE 
OPTION_ARG_ARRAY_SIZE 

Definition at line 1848 of file app_sms.c.

01848                   {
01849    OPTION_ARG_PAUSE = 0,
01850    OPTION_ARG_ARRAY_SIZE
01851 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 2075 of file app_sms.c.

static void __unreg_module ( void   )  [static]

Definition at line 2075 of file app_sms.c.

static void adddata_proto2 ( sms_t h,
unsigned char  msg,
char *  data,
int  size 
) [static]

Add data to a protocol 2 message. Use the length field (h->omsg[1]) as a pointer to the next free position.

Definition at line 1178 of file app_sms.c.

References sms_s::omsg.

Referenced by putdummydata_proto2(), and sms_compose2().

01179 {
01180    int x = h->omsg[1] + 2;                 /* Get current position */
01181    if (x == 2) {
01182       x += 2;                             /* First: skip Payload length (set later) */
01183    }
01184    h->omsg[x++] = msg;                     /* Message code */
01185    h->omsg[x++] = (unsigned char)size;     /* Data size Low */
01186    h->omsg[x++] = 0;                       /* Data size Hi */
01187    for (; size > 0 ; size--) {
01188       h->omsg[x++] = *data++;
01189    }
01190    h->omsg[1] = x - 2;                     /* Frame size */
01191    h->omsg[2] = x - 4;                     /* Payload length (Lo) */
01192    h->omsg[3] = 0;                         /* Payload length (Hi) */
01193 }

static char* isodate ( time_t  t,
char *  buf,
int  len 
) [static]

static, return a date/time in ISO format

Definition at line 299 of file app_sms.c.

References ast_localtime(), and ast_strftime().

Referenced by sms_log(), and sms_writefile().

00300 {
00301    struct ast_tm tm;
00302    struct timeval local = { t, 0 };
00303    ast_localtime(&local, &tm, NULL);
00304    ast_strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
00305    return buf;
00306 }

static int load_module ( void   )  [static]

Definition at line 2063 of file app_sms.c.

References ast_config_AST_LOG_DIR, AST_LIN2A, ast_register_application_xml, and sms_exec().

02064 {
02065 #ifdef OUTALAW
02066    int p;
02067    for (p = 0; p < 80; p++) {
02068       wavea[p] = AST_LIN2A(wave[p]);
02069    }
02070 #endif
02071    snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR);
02072    return ast_register_application_xml(app, sms_exec);
02073 }

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

copy number, skipping non digits apart from leading +

Definition at line 284 of file app_sms.c.

Referenced by sms_readfile().

00285 {
00286    if (*s == '+') {
00287       *d++ = *s++;
00288    }
00289    while (*s) {
00290       if (isdigit(*s)) {
00291          *d++ = *s;
00292       }
00293       s++;
00294    }
00295    *d = 0;
00296 }

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

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

Definition at line 741 of file app_sms.c.

Referenced by sms_compose1().

00742 {
00743    unsigned char p = 2;
00744    o[0] = 0;                               /* number of bytes */
00745    if (*i == '+') {                        /* record as bit 0 in byte 1 */
00746       i++;
00747       o[1] = 0x91;
00748    } else {
00749       o[1] = 0x81;
00750    }
00751    for ( ; *i ; i++) {
00752       if (!isdigit(*i)) {                 /* ignore non-digits */
00753          continue;
00754       }
00755       if (o[0] & 1) {
00756          o[p++] |= ((*i & 0xF) << 4);
00757       } else {
00758          o[p] = (*i & 0xF);
00759       }
00760       o[0]++;
00761    }
00762    if (o[0] & 1) {
00763       o[p++] |= 0xF0;                     /* pad */
00764    }
00765    return p;
00766 }

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

pack a date and return

Definition at line 549 of file app_sms.c.

References ast_localtime(), ast_tm::tm_gmtoff, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, and ast_tm::tm_year.

Referenced by sms_compose1().

00550 {
00551    struct ast_tm t;
00552    struct timeval topack = { w, 0 };
00553    int z;
00554 
00555    ast_localtime(&topack, &t, NULL);
00556 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
00557    z = -t.tm_gmtoff / 60 / 15;
00558 #else
00559    z = timezone / 60 / 15;
00560 #endif
00561    *o++ = ((t.tm_year % 10) << 4) + (t.tm_year % 100) / 10;
00562    *o++ = (((t.tm_mon + 1) % 10) << 4) + (t.tm_mon + 1) / 10;
00563    *o++ = ((t.tm_mday % 10) << 4) + t.tm_mday / 10;
00564    *o++ = ((t.tm_hour % 10) << 4) + t.tm_hour / 10;
00565    *o++ = ((t.tm_min % 10) << 4) + t.tm_min / 10;
00566    *o++ = ((t.tm_sec % 10) << 4) + t.tm_sec / 10;
00567    if (z < 0) {
00568       *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
00569    } else {
00570       *o++ = ((z % 10) << 4) + z / 10;
00571    }
00572 }

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

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

Definition at line 516 of file app_sms.c.

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

Referenced by sms_compose1().

00517 {
00518    unsigned char *p = base;
00519    if (udl == 0) {
00520       *p++ = 0;                           /* no user data */
00521    } else {
00522       
00523       int l = 0;
00524       if (is7bit(dcs)) {                  /* 7 bit */
00525          if ((l = packsms7(p + 1, udhl, udh, udl, ud)) < 0) {
00526             l = 0;
00527          }
00528          *p++ = l;
00529          p += (l * 7 + 7) / 8;
00530       } else if (is8bit(dcs)) {           /* 8 bit */
00531          if ((l = packsms8(p + 1, udhl, udh, udl, ud)) < 0) {
00532             l = 0;
00533          }
00534          *p++ = l;
00535          p += l;
00536       } else {                            /* UCS-2 */
00537          if ((l = packsms16(p + 1, udhl, udh, udl, ud)) < 0) {
00538             l = 0;
00539          }
00540          *p++ = l;
00541          p += l;
00542       }
00543    }
00544    return p - base;
00545 }

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

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

Definition at line 481 of file app_sms.c.

References dummy(), and SMSLEN_8.

Referenced by packsms(), and sms_readfile().

00482 {
00483    unsigned char p = 0;
00484    unsigned char dummy[SMSLEN_8];
00485 
00486    if (o == NULL) {
00487       o = dummy;
00488    }
00489    /* header - no encoding */
00490    if (udhl) {
00491       o[p++] = udhl;
00492       while (udhl--) {
00493          o[p++] = *udh++;
00494          if (p >= SMSLEN_8) {
00495             return p;
00496          }
00497       }
00498    }
00499    while (udl--) {
00500       long u;
00501       u = *ud++;
00502       o[p++] = (u >> 8);
00503       if (p >= SMSLEN_8) {
00504          return p - 1;                   /* could not fit last character */
00505       }
00506       o[p++] = u;
00507       if (p >= SMSLEN_8) {
00508          return p;
00509       }
00510    }
00511    return p;
00512 }

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

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

Definition at line 365 of file app_sms.c.

References dummy(), and SMSLEN.

Referenced by packsms(), and sms_readfile().

00366 {
00367    unsigned char p = 0;                    /* output pointer (bytes) */
00368    unsigned char b = 0;                    /* bit position */
00369    unsigned char n = 0;                    /* output character count */
00370    unsigned char dummy[SMSLEN];
00371 
00372    if (o == NULL) {                        /* output to a dummy buffer if o not set */
00373       o = dummy;
00374    }
00375 
00376    if (udhl) {                             /* header */
00377       o[p++] = udhl;
00378       b = 1;
00379       n = 1;
00380       while (udhl--) {
00381          o[p++] = *udh++;
00382          b += 8;
00383          while (b >= 7) {
00384             b -= 7;
00385             n++;
00386          }
00387          if (n >= SMSLEN)
00388             return n;
00389       }
00390       if (b) {
00391          b = 7 - b;
00392          if (++n >= SMSLEN)
00393             return n;
00394       }                                   /* filling to septet boundary */
00395    }
00396    o[p] = 0;
00397    /* message */
00398    while (udl--) {
00399       long u;
00400       unsigned char v;
00401       u = *ud++;
00402       /* XXX 0 is invalid ? */
00403       /* look up in defaultalphabet[]. If found, v is the 7-bit code */
00404       for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
00405       if (v == 128 /* not found */ && u && n + 1 < SMSLEN) {
00406          /* if not found, look in the escapes table (we need 2 bytes) */
00407          for (v = 0; v < 128 && escapes[v] != u; v++);
00408          if (v < 128) { /* escaped sequence, esc + v */
00409             /* store the low (8-b) bits in o[p], the remaining bits in o[p+1] */
00410             o[p] |= (27 << b);          /* the low bits go into o[p] */ 
00411             b += 7;
00412             if (b >= 8) {
00413                b -= 8;
00414                p++;
00415                o[p] = (27 >> (7 - b));
00416             }
00417             n++;
00418          }
00419       }
00420       if (v == 128)
00421          return -1;                      /* invalid character */
00422       /* store, same as above */
00423       o[p] |= (v << b);
00424       b += 7;
00425       if (b >= 8) {
00426          b -= 8;
00427          p++;
00428          o[p] = (v >> (7 - b));
00429       }
00430       if (++n >= SMSLEN)
00431          return n;
00432    }
00433    return n;
00434 }

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

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

Definition at line 442 of file app_sms.c.

References dummy(), and SMSLEN_8.

Referenced by packsms(), and sms_readfile().

00443 {
00444    unsigned char p = 0;
00445    unsigned char dummy[SMSLEN_8];
00446 
00447    if (o == NULL)
00448       o = dummy;
00449    /* header - no encoding */
00450    if (udhl) {
00451       o[p++] = udhl;
00452       while (udhl--) {
00453          o[p++] = *udh++;
00454          if (p >= SMSLEN_8) {
00455             return p;
00456          }
00457       }
00458    }
00459    while (udl--) {
00460       long u;
00461       u = *ud++;
00462       if (u < 0 || u > 0xFF) {
00463          return -1;                      /* not valid */
00464       }
00465       o[p++] = u;
00466       if (p >= SMSLEN_8) {
00467          return p;
00468       }
00469    }
00470    return p;
00471 }

static void putdummydata_proto2 ( sms_t h  )  [static]

Definition at line 1195 of file app_sms.c.

References adddata_proto2(), sms_s::udl, and sms_s::udtxt.

Referenced by sms_compose2().

01196 {
01197    adddata_proto2(h, 0x10, "\0", 1);           /* Media Identifier > SMS */
01198    adddata_proto2(h, 0x11, "\0\0\0\0\0\0", 6); /* Firmware version */
01199    adddata_proto2(h, 0x12, "\2\0\4", 3);       /* SMS provider ID */
01200    adddata_proto2(h, 0x13, h->udtxt, h->udl);  /* Body */
01201 }

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

read dir skipping dot files...

Definition at line 1092 of file app_sms.c.

References f.

Referenced by sms_nextoutgoing().

01093 {
01094    struct dirent *f;
01095    do {
01096       f = readdir(d);
01097    } while (f && (*f->d_name == '.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] != '.'));
01098    return f;
01099 }

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

Just return the pointer to the descriptor that we received.

Definition at line 1671 of file app_sms.c.

01672 {
01673    return sms_t_ptr;
01674 }

static void sms_compose1 ( sms_t h,
int  more 
) [static]

compose a message for protocol 1

Definition at line 1390 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::rp, 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_nextoutgoing().

01391 {
01392    unsigned int p = 2;                     /* next byte to write. Skip type and len */
01393 
01394    h->omsg[0] = 0x91;                      /* SMS_DATA */
01395    if (h->smsc) {                          /* deliver */
01396       h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
01397       p += packaddress(h->omsg + p, h->oa);
01398       h->omsg[p++] = h->pid;
01399       h->omsg[p++] = h->dcs;
01400       packdate(h->omsg + p, h->scts.tv_sec);
01401       p += 7;
01402       p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01403    } else {                                /* submit */
01404       h->omsg[p++] =
01405          0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
01406       if (h->mr < 0) {
01407          h->mr = message_ref++;
01408       }
01409       h->omsg[p++] = h->mr;
01410       p += packaddress(h->omsg + p, h->da);
01411       h->omsg[p++] = h->pid;
01412       h->omsg[p++] = h->dcs;
01413       if (h->vp) {                        /* relative VP */
01414          if (h->vp < 720) {
01415             h->omsg[p++] = (h->vp + 4) / 5 - 1;
01416          } else if (h->vp < 1440) {
01417             h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
01418          } else if (h->vp < 43200) {
01419             h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
01420          } else if (h->vp < 635040) {
01421             h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
01422          } else {
01423             h->omsg[p++] = 255;         /* max */
01424          }
01425       }
01426       p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01427    }
01428    h->omsg[1] = p - 2;
01429 }

static void sms_compose2 ( sms_t h,
int  more 
) [static]

Definition at line 1203 of file app_sms.c.

References adddata_proto2(), ast_localtime(), sms_s::da, sms_s::oa, sms_s::omsg, putdummydata_proto2(), sms_s::scts, sms_s::smsc, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, and ast_tm::tm_mon.

Referenced by sms_nextoutgoing().

01204 {
01205    struct ast_tm tm;
01206    struct timeval now = h->scts;
01207    char stm[9];
01208 
01209    h->omsg[0] = 0x00;                      /* set later... */
01210    h->omsg[1] = 0;
01211    putdummydata_proto2(h);
01212    if (h->smsc) {                          /* deliver */
01213       h->omsg[0] = 0x11;                  /* SMS_DELIVERY */
01214       /* Required: 10 11 12 13 14 15 17 (seems they must be ordered!) */
01215       ast_localtime(&now, &tm, NULL);
01216       sprintf(stm, "%02d%02d%02d%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);  /* Date mmddHHMM */
01217       adddata_proto2(h, 0x14, stm, 8);    /* Date */
01218       if (*h->oa == 0) {
01219          strcpy(h->oa, "00000000");
01220       }
01221       adddata_proto2(h, 0x15, h->oa, strlen(h->oa)); /* Originator */
01222       adddata_proto2(h, 0x17, "\1", 1);   /* Calling Terminal ID */
01223    } else {                                /* submit */
01224       h->omsg[0] = 0x10;                  /* SMS_SUBMIT */
01225       /* Required: 10 11 12 13 17 18 1B 1C (seems they must be ordered!) */
01226       adddata_proto2(h, 0x17, "\1", 1);   /* Calling Terminal ID */
01227       if (*h->da == 0) {
01228          strcpy(h->da, "00000000");
01229       }
01230       adddata_proto2(h, 0x18, h->da, strlen(h->da)); /* Originator */
01231       adddata_proto2(h, 0x1B, "\1", 1);         /* Called Terminal ID */
01232       adddata_proto2(h, 0x1C, "\0\0\0", 3);    /* Notification */
01233    }
01234 }

static void sms_debug ( int  dir,
sms_t h 
) [static]

Definition at line 1474 of file app_sms.c.

References ast_verb, DIR_RX, sms_s::ibytep, sms_s::imsg, and sms_s::omsg.

Referenced by sms_messagerx(), and sms_messagetx().

01475 {
01476    char txt[259 * 3 + 1];
01477    char *p = txt;                          /* always long enough */
01478    unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
01479    int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
01480    int q = 0;
01481    while (q < n && q < 30) {
01482       sprintf(p, " %02X", msg[q++]);
01483       p += 3;
01484    }
01485    if (q < n) {
01486       sprintf(p, "...");
01487    }
01488    ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
01489 }

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

Definition at line 1862 of file app_sms.c.

References AST_APP_ARG, ast_app_parse_options(), ast_channel_caller(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verb, sms_s::cli, sms_s::dcs, sms_s::ipc0, sms_s::ipc1, LOG_ERROR, sms_s::opause_0, OPTION_ARG_ARRAY_SIZE, OPTION_ARG_PAUSE, OPTION_BE_SMSC, OPTION_DCS, OPTION_SRR, OPTION_TWO, parse(), sms_s::pid, sms_s::protocol, sms_s::queue, S_COR, S_OR, sms_options, sms_s::smsc, and sms_s::srr.

Referenced by load_module().

01863 {
01864    int res = -1;
01865    sms_t h = { 0 };
01866    /* argument parsing support */
01867    struct ast_flags flags;
01868    char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, };
01869    char *p;
01870    AST_DECLARE_APP_ARGS(sms_args,
01871       AST_APP_ARG(queue);
01872       AST_APP_ARG(options);
01873       AST_APP_ARG(addr);
01874       AST_APP_ARG(body);
01875    );
01876 
01877    if (!data) {
01878       ast_log(LOG_ERROR, "Requires queue name at least\n");
01879       return -1;
01880    }
01881 
01882    parse = ast_strdupa(data);              /* create a local copy */
01883    AST_STANDARD_APP_ARGS(sms_args, parse);
01884    if (sms_args.argc > 1) {
01885       ast_app_parse_options(sms_options, &flags, sms_opts, sms_args.options);
01886    }
01887 
01888    ast_verb(1, "sms argc %d queue <%s> opts <%s> addr <%s> body <%s>\n",
01889       sms_args.argc, S_OR(sms_args.queue, ""),
01890       S_OR(sms_args.options, ""),
01891       S_OR(sms_args.addr, ""),
01892       S_OR(sms_args.body, "") );
01893 
01894    h.ipc0 = h.ipc1 = 20;                   /* phase for cosine */
01895    h.dcs = 0xF1;                           /* default */
01896 
01897    ast_copy_string(h.cli,
01898       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
01899       sizeof(h.cli));
01900 
01901    if (ast_strlen_zero(sms_args.queue)) {
01902       ast_log(LOG_ERROR, "Requires queue name\n");
01903       goto done;
01904    }
01905    if (strlen(sms_args.queue) >= sizeof(h.queue)) {
01906       ast_log(LOG_ERROR, "Queue name too long\n");
01907       goto done;
01908    }
01909    ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue));
01910 
01911    for (p = h.queue; *p; p++) {
01912       if (!isalnum(*p)) {
01913          *p = '-';                       /* make very safe for filenames */
01914       }
01915    }
01916 
01917    h.smsc = ast_test_flag(&flags, OPTION_BE_SMSC);
01918    h.protocol = ast_test_flag(&flags, OPTION_TWO) ? 2 : 1;
01919    if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE])) {
01920       h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
01921    }
01922    if (h.opause_0 < 25 || h.opause_0 > 2000) {
01923       h.opause_0 = 300;                   /* default 300ms */
01924    }
01925    ast_verb(1, "initial delay %dms\n", h.opause_0);
01926 
01927 
01928    /* the following apply if there is an arg3/4 and apply to the created message file */
01929    if (ast_test_flag(&flags, OPTION_SRR)) {
01930       h.srr = 1;
01931    }
01932    if (ast_test_flag(&flags, OPTION_DCS)) {
01933       h.dcs = 1;
01934    }
01935 #if 0 
01936       case '1':
01937       case '2':
01938       case '3':
01939       case '4':
01940       case '5':
01941       case '6':
01942       case '7':                           /* set the pid for saved local message */
01943          h.pid = 0x40 + (*d & 0xF);
01944          break;
01945       }
01946 #endif
01947    if (sms_args.argc > 2) {
01948       unsigned char *up;
01949 
01950       /* submitting a message, not taking call. */
01951       /* deprecated, use smsq instead */
01952       h.scts = ast_tvnow();
01953       if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) {
01954          ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr);
01955          goto done;
01956       }
01957       if (h.smsc) {
01958          ast_copy_string(h.oa, sms_args.addr, sizeof(h.oa));
01959       } else {
01960          ast_copy_string(h.da, sms_args.addr, sizeof(h.da));
01961          ast_copy_string(h.oa, h.cli, sizeof(h.oa));
01962       }
01963       h.udl = 0;
01964       if (ast_strlen_zero(sms_args.body)) {
01965          ast_log(LOG_ERROR, "Missing body for %s\n", sms_args.addr);
01966          goto done;
01967       }
01968       up = (unsigned char *)sms_args.body;
01969       while (*up && h.udl < SMSLEN) {
01970          h.ud[h.udl++] = utf8decode(&up);
01971       }
01972       if (is7bit(h.dcs) && packsms7(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01973          ast_log(LOG_WARNING, "Invalid 7 bit GSM data\n");
01974          goto done;
01975       }
01976       if (is8bit(h.dcs) && packsms8(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01977          ast_log(LOG_WARNING, "Invalid 8 bit data\n");
01978          goto done;
01979       }
01980       if (is16bit(h.dcs) && packsms16(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01981          ast_log(LOG_WARNING, "Invalid 16 bit data\n");
01982          goto done;
01983       }
01984       h.rx = 0;                           /* sent message */
01985       h.mr = -1;
01986       sms_writefile(&h);
01987       res = h.err;
01988       goto done;
01989    }
01990    
01991    if (ast_channel_state(chan) != AST_STATE_UP) {     /* make sure channel is answered before any TX */
01992       ast_answer(chan);
01993    }
01994 
01995    if (ast_test_flag(&flags, OPTION_ANSWER)) {
01996       h.framenumber = 1;                  /* Proto 2 */
01997       /* set up SMS_EST initial message */
01998       if (h.protocol == 2) {
01999          h.omsg[0] = DLL2_SMS_EST;
02000          h.omsg[1] = 0;
02001       } else {
02002          h.omsg[0] = DLL1_SMS_EST | DLL1_SMS_COMPLETE;
02003          h.omsg[1] = 0;
02004       }
02005       sms_messagetx(&h);
02006    }
02007 
02008    res = ast_set_write_format_by_id(chan, __OUT_FMT);
02009    if (res >= 0) {
02010       res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
02011    }
02012    if (res < 0) {
02013       ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
02014       goto done;
02015    }
02016 
02017    if ( (res = ast_activate_generator(chan, &smsgen, &h)) < 0) {
02018       ast_log(LOG_ERROR, "Failed to activate generator on '%s'\n", ast_channel_name(chan));
02019       goto done;
02020    }
02021 
02022    /* Do our thing here */
02023    for (;;) {
02024       struct ast_frame *f;
02025       int i = ast_waitfor(chan, -1);
02026       if (i < 0) {
02027          ast_log(LOG_NOTICE, "waitfor failed\n");
02028          break;
02029       }
02030       if (h.hangup) {
02031          ast_log(LOG_NOTICE, "channel hangup\n");
02032          break;
02033       }
02034       f = ast_read(chan);
02035       if (!f) {
02036          ast_log(LOG_NOTICE, "ast_read failed\n");
02037          break;
02038       }
02039       if (f->frametype == AST_FRAME_VOICE) {
02040          sms_process(&h, f->samples, f->data.ptr);
02041       }
02042 
02043       ast_frfree(f);
02044    }
02045    res = h.err;                            /* XXX */
02046 
02047    /* 
02048     * The SMS generator data is on the stack.  We _MUST_ make sure the generator
02049     * is stopped before returning from this function.
02050     */
02051    ast_deactivate_generator(chan);
02052 
02053    sms_log(&h, '?');                       /* log incomplete message */
02054 done:
02055    return (res);
02056 }

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

outgoing data are produced by this generator function, that reads from the descriptor whether it has data to send and which ones.

Definition at line 1593 of file app_sms.c.

References __OUT_FMT, ast_alloca, ast_channel_name(), ast_format_set(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), ast_frame::data, ast_frame::datalen, DLL2_SMS_EST, errno, ast_frame_subclass::format, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, MAXSAMPLES, 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::oseizure, sms_s::osync, sms_s::protocol, ast_frame::ptr, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

01594 {
01595    struct ast_frame f = { 0 };
01596 #define MAXSAMPLES (800)
01597    output_t *buf;
01598    sms_t *h = data;
01599    int i;
01600 
01601    if (samples > MAXSAMPLES) {
01602       ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
01603           MAXSAMPLES, samples);
01604       samples = MAXSAMPLES;
01605    }
01606    len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET;
01607    buf = ast_alloca(len);
01608 
01609    f.frametype = AST_FRAME_VOICE;
01610    ast_format_set(&f.subclass.format, __OUT_FMT, 0);
01611    f.datalen = samples * sizeof(*buf);
01612    f.offset = AST_FRIENDLY_OFFSET;
01613    f.mallocd = 0;
01614    f.data.ptr = buf;
01615    f.samples = samples;
01616    f.src = "app_sms";
01617    /* create a buffer containing the digital sms pattern */
01618    for (i = 0; i < samples; i++) {
01619       buf[i] = wave_out[0];               /* default is silence */
01620 
01621       if (h->opause) {
01622          h->opause--;
01623       } else if (h->obyten || h->osync) { /* sending data */
01624          buf[i] = wave_out[h->ophase];
01625          h->ophase += (h->obyte & 1) ? 13 : 21; /* compute next phase */
01626          if (h->ophase >= 80)
01627             h->ophase -= 80;
01628          if ((h->ophasep += 12) >= 80) { /* time to send the next bit */
01629             h->ophasep -= 80;
01630             if (h->oseizure > 0) {      /* sending channel seizure (proto 2) */
01631                h->oseizure--;
01632                h->obyte ^= 1;          /* toggle low bit */
01633             } else if (h->osync) {
01634                h->obyte = 1;           /* send mark as sync bit */
01635                h->osync--;             /* sending sync bits */
01636                if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
01637                   h->obytep = h->obyten = 0; /* we are done */
01638                }
01639             } else {
01640                h->obitp++;
01641                if (h->obitp == 1) {
01642                   h->obyte = 0;       /* start bit; */
01643                } else if (h->obitp == 2) {
01644                   h->obyte = h->omsg[h->obytep];
01645                } else if (h->obitp == 10) {
01646                   h->obyte = 1; /* stop bit */
01647                   h->obitp = 0;
01648                   h->obytep++;
01649                   if (h->obytep == h->obyten) {
01650                      h->obytep = h->obyten = 0; /* sent */
01651                      h->osync = 10;   /* trailing marks */
01652                   }
01653                } else {
01654                   h->obyte >>= 1;
01655                }
01656             }
01657          }
01658       }
01659    }
01660    if (ast_write(chan, &f) < 0) {
01661       ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
01662       return -1;
01663    }
01664    return 0;
01665 #undef MAXSAMPLES
01666 }

static unsigned char sms_handleincoming ( sms_t h  )  [static]

handle the incoming message

Definition at line 1102 of file app_sms.c.

References ast_copy_string(), ast_log(), ast_tvnow(), 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().

01103 {
01104    unsigned char p = 3;
01105    if (h->smsc) {                          /* SMSC */
01106       if ((h->imsg[2] & 3) == 1) {        /* SMS-SUBMIT */
01107          h->udhl = h->udl = 0;
01108          h->vp = 0;
01109          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
01110          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
01111          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01112          ast_copy_string(h->oa, h->cli, sizeof(h->oa));
01113          h->scts = ast_tvnow();
01114          h->mr = h->imsg[p++];
01115          p += unpackaddress(h->da, h->imsg + p);
01116          h->pid = h->imsg[p++];
01117          h->dcs = h->imsg[p++];
01118          if ((h->imsg[2] & 0x18) == 0x10) {       /* relative VP */
01119             if (h->imsg[p] < 144) {
01120                h->vp = (h->imsg[p] + 1) * 5;
01121             } else if (h->imsg[p] < 168) {
01122                h->vp = 720 + (h->imsg[p] - 143) * 30;
01123             } else if (h->imsg[p] < 197) {
01124                h->vp = (h->imsg[p] - 166) * 1440;
01125             } else {
01126                h->vp = (h->imsg[p] - 192) * 10080;
01127             }
01128             p++;
01129          } else if (h->imsg[2] & 0x18) {
01130             p += 7;                     /* ignore enhanced / absolute VP */
01131          }
01132          p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01133          h->rx = 1;                      /* received message */
01134          sms_writefile(h);               /* write the file */
01135          if (p != h->imsg[1] + 2) {
01136             ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01137             return 0xFF;        /* duh! */
01138          }
01139       } else {
01140          ast_log(LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
01141          return 0xFF;
01142       }
01143    } else {                                /* client */
01144       if (!(h->imsg[2] & 3)) {            /* SMS-DELIVER */
01145          *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
01146          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
01147          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
01148          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01149          h->mr = -1;
01150          p += unpackaddress(h->oa, h->imsg + p);
01151          h->pid = h->imsg[p++];
01152          h->dcs = h->imsg[p++];
01153          h->scts = unpackdate(h->imsg + p);
01154          p += 7;
01155          p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01156          h->rx = 1;                      /* received message */
01157          sms_writefile(h);               /* write the file */
01158          if (p != h->imsg[1] + 2) {
01159             ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01160             return 0xFF;                /* duh! */
01161          }
01162       } else {
01163          ast_log(LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
01164          return 0xFF;
01165       }
01166    }
01167    return 0;                               /* no error */
01168 }

static int sms_handleincoming_proto2 ( sms_t h  )  [static]

sms_handleincoming_proto2: handle the incoming message

Definition at line 1252 of file app_sms.c.

References ast_copy_string(), ast_localtime(), ast_mktime(), ast_tvnow(), ast_verb, sms_s::da, f, sms_s::imsg, MAX_DEBUG_LEN, sms_s::oa, sms_s::rx, sms_s::scts, sms_hexdump(), sms_writefile(), ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, sms_s::ud, and sms_s::udl.

Referenced by sms_messagerx2().

01253 {
01254    int f, i, sz = 0;
01255    int msg, msgsz;
01256    struct ast_tm tm;
01257    struct timeval now = { 0, 0 };
01258    char debug_buf[MAX_DEBUG_LEN * 3 + 1];
01259 
01260    sz = h->imsg[1] + 2;
01261    /* ast_verb(3, "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg, sz, debug_buf)); */
01262 
01263    /* Parse message body (called payload) */
01264    now = h->scts = ast_tvnow();
01265    for (f = 4; f < sz; ) {
01266       msg = h->imsg[f++];
01267       msgsz = h->imsg[f++];
01268       msgsz += (h->imsg[f++] * 256);
01269       switch (msg) {
01270       case 0x13:                          /* Body */
01271          ast_verb(3, "SMS-P2 Body#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]);
01272          if (msgsz >= sizeof(h->ud)) {
01273             msgsz = sizeof(h->ud) - 1;
01274          }
01275          for (i = 0; i < msgsz; i++) {
01276             h->ud[i] = h->imsg[f + i];
01277          }
01278          h->udl = msgsz;
01279          break;
01280       case 0x14:                          /* Date SCTS */
01281          now = h->scts = ast_tvnow();
01282          ast_localtime(&now, &tm, NULL);
01283          tm.tm_mon = ( (h->imsg[f] * 10) + h->imsg[f + 1] ) - 1;
01284          tm.tm_mday = ( (h->imsg[f + 2] * 10) + h->imsg[f + 3] );
01285          tm.tm_hour = ( (h->imsg[f + 4] * 10) + h->imsg[f + 5] );
01286          tm.tm_min = ( (h->imsg[f + 6] * 10) + h->imsg[f + 7] );
01287          tm.tm_sec = 0;
01288          h->scts = ast_mktime(&tm, NULL);
01289          ast_verb(3, "SMS-P2 Date#%02X=%02d/%02d %02d:%02d\n", msg, tm.tm_mday, tm.tm_mon + 1, tm.tm_hour, tm.tm_min);
01290          break;
01291       case 0x15:                          /* Calling line (from SMSC) */
01292          if (msgsz >= 20) {
01293             msgsz = 20 - 1;
01294          }
01295          ast_verb(3, "SMS-P2 Origin#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]);
01296          ast_copy_string(h->oa, (char *)(&h->imsg[f]), msgsz + 1);
01297          break;
01298       case 0x18:                          /* Destination(from TE/phone) */
01299          if (msgsz >= 20) {
01300             msgsz = 20 - 1;
01301          }
01302          ast_verb(3, "SMS-P2 Destination#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]);
01303          ast_copy_string(h->da, (char *)(&h->imsg[f]), msgsz + 1);
01304          break;
01305       case 0x1C:                          /* Notify */
01306          ast_verb(3, "SMS-P2 Notify#%02X=%s\n", msg, sms_hexdump(&h->imsg[f], 3, debug_buf));
01307          break;
01308       default:
01309          ast_verb(3, "SMS-P2 Par#%02X [%d]: %s\n", msg, msgsz, sms_hexdump(&h->imsg[f], msgsz, debug_buf));
01310          break;
01311       }
01312       f+=msgsz;                           /* Skip to next */
01313    }
01314    h->rx = 1;                              /* received message */
01315    sms_writefile(h);                       /* write the file */
01316    return 0;                               /* no error */
01317 }

static char* sms_hexdump ( unsigned char  buf[],
int  size,
char *  s 
) [static]

Definition at line 1239 of file app_sms.c.

References f, and MAX_DEBUG_LEN.

Referenced by sms_handleincoming_proto2().

01240 {
01241    char *p;
01242    int f;
01243 
01244    for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3) {
01245       sprintf(p, "%02X ", (unsigned char)buf[f]);
01246    }
01247    return(s);
01248 }

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

Log the output, and remove file.

Definition at line 769 of file app_sms.c.

References AST_FILE_MODE, ast_log(), sms_s::da, errno, isodate(), LOG_WARNING, sms_s::mr, sms_s::oa, sms_s::queue, sms_s::rx, S_OR, sms_s::smsc, sms_s::ud, and sms_s::udl.

Referenced by sms_messagerx(), and sms_messagerx2().

00770 {
00771    int o;
00772 
00773    if (*h->oa == '\0' && *h->da == '\0') {
00774       return;
00775    }
00776    o = open(log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE);
00777    if (o >= 0) {
00778       char line[1000], mrs[3] = "", *p;
00779       char buf[30];
00780       unsigned char n;
00781 
00782       if (h->mr >= 0) {
00783          snprintf(mrs, sizeof(mrs), "%02X", h->mr);
00784       }
00785       snprintf(line, sizeof(line), "%s %c%c%c%s %s %s %s ",
00786          isodate(time(NULL), buf, sizeof(buf)),
00787          status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue,
00788          S_OR(h->oa, "-"), S_OR(h->da, "-") );
00789       p = line + strlen(line);
00790       for (n = 0; n < h->udl; n++) {
00791          if (h->ud[n] == '\\') {
00792             *p++ = '\\';
00793             *p++ = '\\';
00794          } else if (h->ud[n] == '\n') {
00795             *p++ = '\\';
00796             *p++ = 'n';
00797          } else if (h->ud[n] == '\r') {
00798             *p++ = '\\';
00799             *p++ = 'r';
00800          } else if (h->ud[n] < 32 || h->ud[n] == 127) {
00801             *p++ = 191;
00802          } else {
00803             *p++ = h->ud[n];
00804          }
00805       }
00806       *p++ = '\n';
00807       *p = 0;
00808       if (write(o, line, strlen(line)) < 0) {
00809          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00810       }
00811       close(o);
00812    }
00813    *h->oa = *h->da = h->udl = 0;
00814 }

static void sms_messagerx ( sms_t h  )  [static]

Definition at line 1492 of file app_sms.c.

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

Referenced by sms_process().

01493 {
01494    int cause;
01495 
01496    sms_debug (DIR_RX, h);
01497    if (h->protocol == 2) {
01498       sms_messagerx2(h);
01499       return;
01500    }
01501    /* parse incoming message for Protocol 1 */
01502    switch (h->imsg[0]) {
01503    case 0x91:                              /* SMS_DATA */
01504       cause = sms_handleincoming (h);
01505       if (!cause) {
01506          sms_log(h, 'Y');
01507          h->omsg[0] = 0x95;              /* SMS_ACK */
01508          h->omsg[1] = 0x02;
01509          h->omsg[2] = 0x00;              /* deliver report */
01510          h->omsg[3] = 0x00;              /* no parameters */
01511       } else {                            /* NACK */
01512          sms_log(h, 'N');
01513          h->omsg[0] = 0x96;              /* SMS_NACK */
01514          h->omsg[1] = 3;
01515          h->omsg[2] = 0;                 /* delivery report */
01516          h->omsg[3] = cause;             /* cause */
01517          h->omsg[4] = 0;                 /* no parameters */
01518       }
01519       sms_messagetx(h);
01520       break;
01521 
01522    case 0x92:                              /* SMS_ERROR */
01523       h->err = 1;
01524       sms_messagetx(h);                   /* send whatever we sent again */
01525       break;
01526    case 0x93:                              /* SMS_EST */
01527       sms_nextoutgoing (h);
01528       break;
01529    case 0x94:                              /* SMS_REL */
01530       h->hangup = 1;                      /* hangup */
01531       break;
01532    case 0x95:                              /* SMS_ACK */
01533       sms_log(h, 'Y');
01534       sms_nextoutgoing (h);
01535       break;
01536    case 0x96:                              /* SMS_NACK */
01537       h->err = 1;
01538       sms_log(h, 'N');
01539       sms_nextoutgoing (h);
01540       break;
01541    default:                                /* Unknown */
01542       h->omsg[0] = 0x92;                  /* SMS_ERROR */
01543       h->omsg[1] = 1;
01544       h->omsg[2] = 3;                     /* unknown message type */
01545       sms_messagetx(h);
01546       break;
01547    }
01548 }

static void sms_messagerx2 ( sms_t h  )  [static]

Definition at line 1333 of file app_sms.c.

References ast_log(), cause, DLL2_ACK, DLL2_SMS_ACK0, DLL2_SMS_ACK1, DLL2_SMS_EST, DLL2_SMS_INFO_MO, DLL2_SMS_INFO_MT, DLL2_SMS_NACK, DLL2_SMS_REL, DLL_SMS_MASK, sms_s::hangup, sms_s::imsg, LOG_NOTICE, sms_s::omsg, sms_handleincoming_proto2(), sms_log(), sms_messagetx(), and sms_nextoutgoing().

Referenced by sms_messagerx().

01334 {
01335    int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */
01336    int cause;
01337 
01338 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
01339    switch (p) {
01340    case DLL2_SMS_EST:                      /* Protocol 2: Connection ready (fake): send message  */
01341       sms_nextoutgoing (h);
01342       /* smssend(h,"11 29 27 00 10 01 00 00 11 06 00 00 00 00 00 00 00 12 03 00 02 00 04 13 01 00 41 14 08 00 30 39 31 35 30 02 30 02 15 02 00 39 30 "); */
01343       break;
01344 
01345    case DLL2_SMS_INFO_MO:                  /* transport SMS_SUBMIT */
01346    case DLL2_SMS_INFO_MT:                  /* transport SMS_DELIVERY */
01347       cause = sms_handleincoming_proto2(h);
01348       if (!cause) {                       /* ACK */
01349          sms_log(h, 'Y');
01350       }
01351       h->omsg[0] = DLL2_ACK(h);
01352       h->omsg[1] = 0x06;                  /* msg len */
01353       h->omsg[2] = 0x04;                  /* payload len */
01354       h->omsg[3] = 0x00;                  /* payload len */
01355       h->omsg[4] = 0x1f;                  /* Response type */
01356       h->omsg[5] = 0x01;                  /* parameter len */
01357       h->omsg[6] = 0x00;                  /* parameter len */
01358       h->omsg[7] = cause;                 /* CONFIRM or error */
01359       sms_messagetx(h);
01360       break;
01361 
01362    case DLL2_SMS_NACK:                     /* Protocol 2: SMS_NAK */
01363       h->omsg[0] = DLL2_SMS_REL;          /* SMS_REL */
01364       h->omsg[1] = 0x00;                  /* msg len */
01365       sms_messagetx(h);
01366       break;
01367 
01368    case DLL2_SMS_ACK0:
01369    case DLL2_SMS_ACK1:
01370       /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */
01371       if ( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
01372          /* a response to our Release, just hangup */
01373          h->hangup = 1;                  /* hangup */
01374       } else {
01375          /* XXX depending on what we are.. */
01376          ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY\n");
01377          sms_nextoutgoing (h);
01378       }
01379       break;
01380 
01381    case DLL2_SMS_REL:                      /* Protocol 2: SMS_REL (hangup req) */
01382       h->omsg[0] = DLL2_ACK(h);
01383       h->omsg[1] = 0;
01384       sms_messagetx(h);
01385       break;
01386    }
01387 }

static void sms_messagetx ( sms_t h  )  [static]

Definition at line 1550 of file app_sms.c.

References DIR_TX, sms_s::framenumber, len(), sms_s::obitp, sms_s::obyte, sms_s::obyten, sms_s::obytep, sms_s::omsg, sms_s::opause, sms_s::opause_0, sms_s::oseizure, sms_s::osync, OSYNC_BITS, sms_s::protocol, and sms_debug().

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

01551 {
01552    unsigned char c = 0, p;
01553    int len = h->omsg[1] + 2;               /* total message length excluding checksum */
01554 
01555    for (p = 0; p < len; p++) {             /* compute checksum */
01556       c += h->omsg[p];
01557    }
01558    h->omsg[len] = 0 - c;                   /* actually, (256 - (c & 0fxx)) & 0xff) */
01559    sms_debug(DIR_TX, h);
01560    h->framenumber++;                       /* Proto 2 */
01561    h->obytep = 0;
01562    h->obitp = 0;
01563    if (h->protocol == 2) {                 /* Proto 2: */
01564       h->oseizure = 300;                  /* 300bits (or more ?) */
01565       h->obyte = 0;                       /* Seizure starts with  space (0) */
01566       if (h->omsg[0] == 0x7F) {
01567          h->opause = 8 * h->opause_0;    /* initial message delay */
01568       } else {
01569          h->opause = 400;
01570       }
01571    } else {                                /* Proto 1: */
01572       h->oseizure = 0;                    /* No seizure */
01573       h->obyte = 1;                       /* send mark ('1') at the beginning */
01574       /* Change the initial message delay. BT requires 300ms,
01575        * but for others this might be way too much and the phone
01576        * could time out. XXX make it configurable.
01577       */
01578       if (h->omsg[0] == 0x93) {
01579          h->opause = 8 * h->opause_0;    /* initial message delay */
01580       } else {
01581          h->opause = 200;
01582       }
01583    }
01584    /* Note - setting osync triggers the generator */
01585    h->osync = OSYNC_BITS;                  /* 80 sync bits */
01586    h->obyten = len + 1;                    /* bytes to send (including checksum) */
01587 }

static void sms_nextoutgoing ( sms_t h  )  [static]

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

Definition at line 1432 of file app_sms.c.

References ast_config_AST_SPOOL_DIR, ast_mkdir(), sms_s::da, sms_s::oa, sms_s::omsg, sms_s::protocol, sms_s::queue, readdirqueue(), sms_s::rx, sms_compose1(), sms_compose2(), sms_messagetx(), sms_readfile(), and sms_s::smsc.

Referenced by sms_messagerx(), and sms_messagerx2().

01433 {    
01434    char fn[100 + NAME_MAX] = "";
01435    DIR *d;
01436    char more = 0;
01437 
01438    *h->da = *h->oa = '\0';                 /* clear destinations */
01439    h->rx = 0;                              /* outgoing message */
01440    snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? "mttx" : "motx");
01441    ast_mkdir(fn, 0777);                    /* ensure it exists */
01442    d = opendir(fn);
01443    if (d) {
01444       struct dirent *f = readdirqueue(d, h->queue);
01445       if (f) {
01446          snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", f->d_name);
01447          sms_readfile(h, fn);
01448          if (readdirqueue(d, h->queue)) {
01449             more = 1;                   /* more to send */
01450          }
01451       }
01452       closedir(d);
01453    }
01454    if (*h->da || *h->oa) {                 /* message to send */
01455       if (h->protocol == 2) {
01456          sms_compose2(h, more);
01457       } else {
01458          sms_compose1(h, more);
01459       }
01460    } else {                                /* no message */
01461       if (h->protocol == 2) {
01462          h->omsg[0] = 0x17;              /* SMS_REL */
01463          h->omsg[1] = 0;
01464       } else {
01465          h->omsg[0] = 0x94;              /* SMS_REL */
01466          h->omsg[1] = 0;
01467       }
01468    }
01469    sms_messagetx(h);
01470 }

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

Process an incoming frame, trying to detect the carrier and decode the message. The two frequencies are 1300 and 2100 Hz. The decoder detects the amplitude of the signal over the last few samples, filtering the absolute values with a lowpass filter. If the magnitude (h->imag) is large enough, multiply the signal by the two carriers, and compute the amplitudes m0 and m1. Record the current sample as '0' or '1' depending on which one is greater. The last 3 bits are stored in h->ibith, with the count of '1' bits in h->ibitt. XXX the rest is to be determined.

Definition at line 1699 of file app_sms.c.

References ast_log(), ast_verb, sms_s::err, sms_s::framenumber, 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_NOTICE, sms_s::obyten, sms_s::omsg, sms_s::osync, sms_s::protocol, sms_messagerx(), and sms_messagetx().

01700 {
01701    int bit;
01702 
01703    /*
01704     * Ignore incoming audio while a packet is being transmitted,
01705     * the protocol is half-duplex.
01706     * Unfortunately this means that if the outbound and incoming
01707     * transmission overlap (which is an error condition anyways),
01708     * we may miss some data and this makes debugging harder.
01709     */
01710    if (h->obyten || h->osync) {
01711       return;
01712    }
01713    for ( ; samples-- ; data++) {
01714       unsigned long long m0, m1;
01715       if (abs(*data) > h->imag) {
01716          h->imag = abs(*data);
01717       } else {
01718          h->imag = h->imag * 7 / 8;
01719       }
01720       if (h->imag <= 500) {               /* below [arbitrary] threahold: lost carrier */
01721          if (h->idle++ == 80000) {       /* nothing happening */
01722             ast_log(LOG_NOTICE, "No data, hanging up\n");
01723             h->hangup = 1;
01724             h->err = 1;
01725          }
01726          if (h->ierr) {                  /* error */
01727             ast_log(LOG_NOTICE, "Error %d, hanging up\n", h->ierr);
01728             /* Protocol 1 */
01729             h->err = 1;
01730             h->omsg[0] = 0x92;          /* error */
01731             h->omsg[1] = 1;
01732             h->omsg[2] = h->ierr;
01733             sms_messagetx(h);           /* send error */
01734          }
01735          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01736          continue;
01737       }
01738       h->idle = 0;
01739 
01740       /* multiply signal by the two carriers. */
01741       h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
01742       h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
01743       h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
01744       h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
01745       /* compute the amplitudes */
01746       m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
01747       m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
01748 
01749       /* advance the sin/cos pointers */
01750       if ((h->ips0 += 21) >= 80) {
01751          h->ips0 -= 80;
01752       }
01753       if ((h->ipc0 += 21) >= 80) {
01754          h->ipc0 -= 80;
01755       }
01756       if ((h->ips1 += 13) >= 80) {
01757          h->ips1 -= 80;
01758       }
01759       if ((h->ipc1 += 13) >= 80) {
01760          h->ipc1 -= 80;
01761       }
01762 
01763       /* set new bit to 1 or 0 depending on which value is stronger */
01764       h->ibith <<= 1;
01765       if (m1 > m0) {
01766          h->ibith |= 1;
01767       }
01768       if (h->ibith & 8) {
01769          h->ibitt--;
01770       }
01771       if (h->ibith & 1) {
01772          h->ibitt++;
01773       }
01774       bit = ((h->ibitt > 1) ? 1 : 0);
01775       if (bit != h->ibitl) {
01776          h->ibitc = 1;
01777       } else {
01778          h->ibitc++;
01779       }
01780       h->ibitl = bit;
01781       if (!h->ibitn && h->ibitc == 4 && !bit) {
01782          h->ibitn = 1;
01783          h->iphasep = 0;
01784       }
01785       if (bit && h->ibitc == 200) {       /* sync, restart message */
01786          /* Protocol 2: empty connection ready (I am master) */
01787          if (h->framenumber < 0 && h->ibytec >= 160 && !memcmp(h->imsg, "UUUUUUUUUUUUUUUUUUUU", 20)) {
01788             h->framenumber = 1;
01789             ast_verb(3, "SMS protocol 2 detected\n");
01790             h->protocol = 2;
01791             h->imsg[0] = 0xff;          /* special message (fake) */
01792             h->imsg[1] = h->imsg[2] = 0x00;
01793             h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01794             sms_messagerx(h);
01795          }
01796          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01797       }
01798       if (h->ibitn) {
01799          h->iphasep += 12;
01800          if (h->iphasep >= 80) {         /* next bit */
01801             h->iphasep -= 80;
01802             if (h->ibitn++ == 9) {      /* end of byte */
01803                if (!bit) {             /* bad stop bit */
01804                   ast_log(LOG_NOTICE, "bad stop bit\n");
01805                   h->ierr = 0xFF;     /* unknown error */
01806                } else {
01807                   if (h->ibytep < sizeof(h->imsg)) {
01808                      h->imsg[h->ibytep] = h->ibytev;
01809                      h->ibytec += h->ibytev;
01810                      h->ibytep++;
01811                   } else if (h->ibytep == sizeof(h->imsg)) {
01812                      ast_log(LOG_NOTICE, "msg too large\n");
01813                      h->ierr = 2;    /* bad message length */
01814                   }
01815                   if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
01816                      if (!h->ibytec) {
01817                         sms_messagerx(h);
01818                      } else {
01819                         ast_log(LOG_NOTICE, "bad checksum\n");
01820                         h->ierr = 1; /* bad checksum */
01821                      }
01822                   }
01823                }
01824                h->ibitn = 0;
01825             }
01826             h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
01827          }
01828       }
01829    }
01830 }

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

parse and delete a file

Definition at line 817 of file app_sms.c.

References ast_log(), ast_mktime(), ast_tvnow(), sms_s::da, sms_s::dcs, is16bit, is7bit, is8bit, LOG_NOTICE, 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, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, sms_s::udtxt, utf8decode(), and sms_s::vp.

Referenced by sms_nextoutgoing().

00818 {
00819    char line[1000];
00820    FILE *s;
00821    char dcsset = 0;                        /* if DSC set */
00822    ast_log(LOG_NOTICE, "Sending %s\n", fn);
00823    h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
00824    h->mr = -1;
00825    h->dcs = 0xF1;                          /* normal messages class 1 */
00826    h->scts = ast_tvnow();
00827    s = fopen(fn, "r");
00828    if (s) {
00829       if (unlink(fn)) {                   /* concurrent access, we lost */
00830          fclose(s);
00831          return;
00832       }
00833       while (fgets (line, sizeof(line), s)) {   /* process line in file */
00834          char *p;
00835          void *pp = &p;
00836          for (p = line; *p && *p != '\n' && *p != '\r'; p++);
00837          *p = 0;                         /* strip eoln */
00838          p = line;
00839          if (!*p || *p == ';') {
00840             continue;                   /* blank line or comment, ignore */
00841          }
00842          while (isalnum(*p)) {
00843             *p = tolower (*p);
00844             p++;
00845          }
00846          while (isspace (*p)) {
00847             *p++ = 0;
00848          }
00849          if (*p == '=') {
00850             *p++ = 0;
00851             if (!strcmp(line, "ud")) {  /* parse message (UTF-8) */
00852                unsigned char o = 0;
00853                memcpy(h->udtxt, p, SMSLEN); /* for protocol 2 */
00854                while (*p && o < SMSLEN) {
00855                   h->ud[o++] = utf8decode(pp);
00856                }
00857                h->udl = o;
00858                if (*p) {
00859                   ast_log(LOG_WARNING, "UD too long in %s\n", fn);
00860                }
00861             } else {
00862                while (isspace (*p)) {
00863                   p++;
00864                }
00865                if (!strcmp(line, "oa") && strlen(p) < sizeof(h->oa)) {
00866                   numcpy (h->oa, p);
00867                } else if (!strcmp(line, "da") && strlen(p) < sizeof(h->oa)) {
00868                   numcpy (h->da, p);
00869                } else if (!strcmp(line, "pid")) {
00870                   h->pid = atoi(p);
00871                } else if (!strcmp(line, "dcs")) {
00872                   h->dcs = atoi(p);
00873                   dcsset = 1;
00874                } else if (!strcmp(line, "mr")) {
00875                   h->mr = atoi(p);
00876                } else if (!strcmp(line, "srr")) {
00877                   h->srr = (atoi(p) ? 1 : 0);
00878                } else if (!strcmp(line, "vp")) {
00879                   h->vp = atoi(p);
00880                } else if (!strcmp(line, "rp")) {
00881                   h->rp = (atoi(p) ? 1 : 0);
00882                } else if (!strcmp(line, "scts")) {    /* get date/time */
00883                   int Y, m, d, H, M, S;
00884                   /* XXX Why aren't we using ast_strptime here? */
00885                   if (sscanf(p, "%4d-%2d-%2dT%2d:%2d:%2d", &Y, &m, &d, &H, &M, &S) == 6) {
00886                      struct ast_tm t = { 0, };
00887                      t.tm_year = Y - 1900;
00888                      t.tm_mon = m - 1;
00889                      t.tm_mday = d;
00890                      t.tm_hour = H;
00891                      t.tm_min = M;
00892                      t.tm_sec = S;
00893                      t.tm_isdst = -1;
00894                      h->scts = ast_mktime(&t, NULL);
00895                      if (h->scts.tv_sec == 0) {
00896                         ast_log(LOG_WARNING, "Bad date/timein %s: %s", fn, p);
00897                      }
00898                   }
00899                } else {
00900                   ast_log(LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
00901                }
00902             }
00903          } else if (*p == '#') {                   /* raw hex format */
00904             *p++ = 0;
00905             if (*p == '#') {
00906                p++;
00907                if (!strcmp(line, "ud")) {        /* user data */
00908                   int o = 0;
00909                   while (*p && o < SMSLEN) {
00910                      if (isxdigit(*p) && isxdigit(p[1]) && isxdigit(p[2]) && isxdigit(p[3])) {
00911                         h->ud[o++] =
00912                            (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 12) +
00913                            (((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
00914                            (((isalpha(p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha(p[3]) ? 9 : 0) + (p[3] & 0xF));
00915                         p += 4;
00916                      } else
00917                         break;
00918                   }
00919                   h->udl = o;
00920                   if (*p)
00921                      ast_log(LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
00922                } else
00923                   ast_log(LOG_WARNING, "Only ud can use ## format, %s\n", fn);
00924             } else if (!strcmp(line, "ud")) {       /* user data */
00925                int o = 0;
00926                while (*p && o < SMSLEN) {
00927                   if (isxdigit(*p) && isxdigit(p[1])) {
00928                      h->ud[o++] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
00929                      p += 2;
00930                   } else {
00931                      break;
00932                   }
00933                }
00934                h->udl = o;
00935                if (*p) {
00936                   ast_log(LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
00937                }
00938             } else if (!strcmp(line, "udh")) {      /* user data header */
00939                unsigned char o = 0;
00940                h->udhi = 1;
00941                while (*p && o < SMSLEN) {
00942                   if (isxdigit(*p) && isxdigit(p[1])) {
00943                      h->udh[o] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
00944                      o++;
00945                      p += 2;
00946                   } else {
00947                      break;
00948                   }
00949                }
00950                h->udhl = o;
00951                if (*p) {
00952                   ast_log(LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
00953                }
00954             } else {
00955                ast_log(LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
00956             }
00957          } else {
00958             ast_log(LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
00959          }
00960       }
00961       fclose(s);
00962       if (!dcsset && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00963          if (packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00964             if (packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00965                ast_log(LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
00966             } else {
00967                h->dcs = 0x08;          /* default to 16 bit */
00968                ast_log(LOG_WARNING, "Sending in 16 bit format(%s)\n", fn);
00969             }
00970          } else {
00971             h->dcs = 0xF5;              /* default to 8 bit */
00972             ast_log(LOG_WARNING, "Sending in 8 bit format(%s)\n", fn);
00973          }
00974       }
00975       if (is7bit(h->dcs) && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00976          ast_log(LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
00977       }
00978       if (is8bit(h->dcs) && packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00979          ast_log(LOG_WARNING, "Invalid 8 bit data %s\n", fn);
00980       }
00981       if (is16bit(h->dcs) && packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00982          ast_log(LOG_WARNING, "Invalid 16 bit data %s\n", fn);
00983       }
00984    }
00985 }

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

Definition at line 1676 of file app_sms.c.

01677 {
01678    return;  /* nothing to do here. */
01679 }

static void sms_writefile ( sms_t h  )  [static]

white a received text message to a file

Definition at line 988 of file app_sms.c.

References ast_config_AST_SPOOL_DIR, ast_copy_string(), ast_log(), ast_mkdir(), ast_tvnow(), ast_tvzero(), sms_s::da, sms_s::dcs, isodate(), LOG_NOTICE, 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_handleincoming(), and sms_handleincoming_proto2().

00989 {
00990    char fn[200] = "", fn2[200] = "";
00991    char buf[30];
00992    FILE *o;
00993 
00994    if (ast_tvzero(h->scts)) {
00995       h->scts = ast_tvnow();
00996    }
00997    snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
00998    ast_mkdir(fn, 0777);                    /* ensure it exists */
00999    ast_copy_string(fn2, fn, sizeof(fn2));
01000    snprintf(fn2 + strlen(fn2), sizeof(fn2) - strlen(fn2), "/%s.%s-%d", h->queue, isodate(h->scts.tv_sec, buf, sizeof(buf)), seq++);
01001    snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/.%s", fn2 + strlen(fn) + 1);
01002    if ((o = fopen(fn, "w")) == NULL) {
01003       return;
01004    }
01005 
01006    if (*h->oa) {
01007       fprintf(o, "oa=%s\n", h->oa);
01008    }
01009    if (*h->da) {
01010       fprintf(o, "da=%s\n", h->da);
01011    }
01012    if (h->udhi) {
01013       unsigned int p;
01014       fprintf(o, "udh#");
01015       for (p = 0; p < h->udhl; p++) {
01016          fprintf(o, "%02X", h->udh[p]);
01017       }
01018       fprintf(o, "\n");
01019    }
01020    if (h->udl) {
01021       unsigned int p;
01022       for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
01023       if (p < h->udl) {
01024          fputc(';', o);                  /* cannot use ud=, but include as a comment for human readable */
01025       }
01026       fprintf(o, "ud=");
01027       for (p = 0; p < h->udl; p++) {
01028          unsigned short v = h->ud[p];
01029          if (v < 32) {
01030             fputc(191, o);
01031          } else if (v < 0x80) {
01032             fputc(v, o);
01033          } else if (v < 0x800) {
01034             fputc(0xC0 + (v >> 6), o);
01035             fputc(0x80 + (v & 0x3F), o);
01036          } else {
01037             fputc(0xE0 + (v >> 12), o);
01038             fputc(0x80 + ((v >> 6) & 0x3F), o);
01039             fputc(0x80 + (v & 0x3F), o);
01040          }
01041       }
01042       fprintf(o, "\n");
01043       for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
01044       if (p < h->udl) {
01045          for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
01046          if (p == h->udl) {              /* can write in ucs-1 hex */
01047             fprintf(o, "ud#");
01048             for (p = 0; p < h->udl; p++) {
01049                fprintf(o, "%02X", h->ud[p]);
01050             }
01051             fprintf(o, "\n");
01052          } else {                        /* write in UCS-2 */
01053             fprintf(o, "ud##");
01054             for (p = 0; p < h->udl; p++) {
01055                fprintf(o, "%04X", h->ud[p]);
01056             }
01057             fprintf(o, "\n");
01058          }
01059       }
01060    }
01061    if (h->scts.tv_sec) {
01062       char datebuf[30];
01063       fprintf(o, "scts=%s\n", isodate(h->scts.tv_sec, datebuf, sizeof(datebuf)));
01064    }
01065    if (h->pid) {
01066       fprintf(o, "pid=%d\n", h->pid);
01067    }
01068    if (h->dcs != 0xF1) {
01069       fprintf(o, "dcs=%d\n", h->dcs);
01070    }
01071    if (h->vp) {
01072       fprintf(o, "vp=%d\n", h->vp);
01073    }
01074    if (h->srr) {
01075       fprintf(o, "srr=1\n");
01076    }
01077    if (h->mr >= 0) {
01078       fprintf(o, "mr=%d\n", h->mr);
01079    }
01080    if (h->rp) {
01081       fprintf(o, "rp=1\n");
01082    }
01083    fclose(o);
01084    if (rename(fn, fn2)) {
01085       unlink(fn);
01086    } else {
01087       ast_log(LOG_NOTICE, "Received to %s\n", fn2);
01088    }
01089 }

static int unload_module ( void   )  [static]

Definition at line 2058 of file app_sms.c.

References ast_unregister_application().

02059 {
02060    return ast_unregister_application(app);
02061 }

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

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

Definition at line 723 of file app_sms.c.

Referenced by sms_handleincoming().

00724 {
00725    unsigned char l = i[0], p;
00726    if (i[1] == 0x91) {
00727       *o++ = '+';
00728    }
00729    for (p = 0; p < l; p++) {
00730       if (p & 1) {
00731          *o++ = (i[2 + p / 2] >> 4) + '0';
00732       } else {
00733          *o++ = (i[2 + p / 2] & 0xF) + '0';
00734       }
00735    }
00736    *o = 0;
00737    return (l + 5) / 2;
00738 }

static struct timeval unpackdate ( unsigned char *  i  )  [static, read]

unpack a date and return

Definition at line 575 of file app_sms.c.

References ast_mktime(), ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, and ast_tm::tm_year.

Referenced by sms_handleincoming().

00576 {
00577    struct ast_tm t;
00578 
00579    t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
00580    t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
00581    t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
00582    t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
00583    t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
00584    t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
00585    t.tm_isdst = 0;
00586    if (i[6] & 0x08) {
00587       t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00588    } else {
00589       t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00590    }
00591 
00592    return ast_mktime(&t, NULL);
00593 }

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

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

Definition at line 708 of file app_sms.c.

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

Referenced by sms_handleincoming().

00709 {
00710    int l = *i++;
00711    if (is7bit(dcs)) {
00712       unpacksms7(i, l, udh, udhl, ud, udl, udhi);
00713       l = (l * 7 + 7) / 8;                /* adjust length to return */
00714    } else if (is8bit(dcs)) {
00715       unpacksms8(i, l, udh, udhl, ud, udl, udhi);
00716    } else {
00717       unpacksms16(i, l, udh, udhl, ud, udl, udhi);
00718    }
00719    return l + 1;
00720 }

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

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

Definition at line 680 of file app_sms.c.

Referenced by unpacksms().

00681 {
00682    unsigned short *o = ud;
00683    *udhl = 0;
00684    if (udhi) {
00685       int n = *i;
00686       *udhl = n;
00687       if (n) {
00688          i++;
00689          l--;
00690          while (l && n) {
00691             l--;
00692             n--;
00693             *udh++ = *i++;
00694          }
00695       }
00696    }
00697    while (l--) {
00698       int v = *i++;
00699       if (l--) {
00700          v = (v << 8) + *i++;
00701       }
00702       *o++ = v;
00703    }
00704    *udl = (o - ud);
00705 }

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

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

Definition at line 598 of file app_sms.c.

Referenced by unpacksms().

00599 {
00600    unsigned char b = 0, p = 0;
00601    unsigned short *o = ud;
00602    *udhl = 0;
00603    if (udhi && l) {                        /* header */
00604       int h = i[p];
00605       *udhl = h;
00606       if (h) {
00607          b = 1;
00608          p++;
00609          l--;
00610          while (h-- && l) {
00611             *udh++ = i[p++];
00612             b += 8;
00613             while (b >= 7) {
00614                b -= 7;
00615                l--;
00616                if (!l) {
00617                   break;
00618                }
00619             }
00620          }
00621          /* adjust for fill, septets */
00622          if (b) {
00623             b = 7 - b;
00624             l--;
00625          }
00626       }
00627    }
00628    while (l--) {
00629       unsigned char v;
00630       if (b < 2) {
00631          v = ((i[p] >> b) & 0x7F);       /* everything in one byte */
00632       } else {
00633          v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
00634       }
00635       b += 7;
00636       if (b >= 8) {
00637          b -= 8;
00638          p++;
00639       }
00640       /* 0x00A0 is the encoding of ESC (27) in defaultalphabet */
00641       if (o > ud && o[-1] == 0x00A0 && escapes[v]) {
00642          o[-1] = escapes[v];
00643       } else {
00644          *o++ = defaultalphabet[v];
00645       }
00646    }
00647    *udl = (o - ud);
00648 }

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

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

Definition at line 654 of file app_sms.c.

Referenced by unpacksms().

00655 {
00656    unsigned short *o = ud;
00657    *udhl = 0;
00658    if (udhi) {
00659       int n = *i;
00660       *udhl = n;
00661       if (n) {
00662          i++;
00663          l--;
00664          while (l && n) {
00665             l--;
00666             n--;
00667             *udh++ = *i++;
00668          }
00669       }
00670    }
00671    while (l--) {
00672       *o++ = *i++;                        /* not to UTF-8 as explicitly 8 bit coding in DCS */
00673    }
00674    *udl = (o - ud);
00675 }

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

Reads next UCS character from NUL terminated UTF-8 string and advance pointer.

Definition at line 311 of file app_sms.c.

Referenced by sms_readfile().

00312 {
00313    unsigned char *p = *pp;
00314    if (!*p) {
00315       return 0;                           /* null termination of string */
00316    }
00317    (*pp)++;
00318    if (*p < 0xC0) {
00319       return *p;                          /* ascii or continuation character */
00320    }
00321    if (*p < 0xE0) {
00322       if (*p < 0xC2 || (p[1] & 0xC0) != 0x80) {
00323          return *p;                      /* not valid UTF-8 */
00324       }
00325       (*pp)++;
00326       return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
00327       }
00328    if (*p < 0xF0) {
00329       if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80) {
00330          return *p;                      /* not valid UTF-8 */
00331       }
00332       (*pp) += 2;
00333       return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
00334    }
00335    if (*p < 0xF8) {
00336       if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80) {
00337          return *p;                      /* not valid UTF-8 */
00338       }
00339       (*pp) += 3;
00340       return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
00341    }
00342    if (*p < 0xFC) {
00343       if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00344          || (p[4] & 0xC0) != 0x80) {
00345          return *p;                      /* not valid UTF-8 */
00346       }
00347       (*pp) += 4;
00348       return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
00349    }
00350    if (*p < 0xFE) {
00351       if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00352          || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80) {
00353          return *p;                      /* not valid UTF-8 */
00354       }
00355       (*pp) += 5;
00356       return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
00357    }
00358    return *p;                              /* not sensible */
00359 }


Variable Documentation

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

Definition at line 2075 of file app_sms.c.

char* app = "SMS" [static]

Definition at line 122 of file app_sms.c.

Definition at line 2075 of file app_sms.c.

const unsigned short defaultalphabet[] [static]

Definition at line 189 of file app_sms.c.

const unsigned short escapes[] [static]

Definition at line 202 of file app_sms.c.

char log_file[255] [static]

Definition at line 120 of file app_sms.c.

volatile unsigned char message_ref [static]

Definition at line 117 of file app_sms.c.

volatile unsigned int seq [static]

struct ast_app_option sms_options[128] = { [ 's' ] = { .flag = OPTION_BE_SMSC }, [ 'a' ] = { .flag = OPTION_ANSWER }, [ 't' ] = { .flag = OPTION_TWO }, [ 'r' ] = { .flag = OPTION_SRR }, [ 'o' ] = { .flag = OPTION_DCS }, [ 'p' ] = { .flag = OPTION_PAUSE , .arg_index = OPTION_ARG_PAUSE + 1 }, } [static]

Definition at line 1860 of file app_sms.c.

Referenced by sms_exec().

struct ast_generator smsgen [static]

Initial value:

 {
   .alloc = sms_alloc,
   .release = sms_release,
   .generate = sms_generate,
}

Definition at line 1681 of file app_sms.c.

const signed short wave[] [static]

Definition at line 130 of file app_sms.c.

const output_t* wave_out = wave [static]

Definition at line 146 of file app_sms.c.


Generated on Thu Oct 11 06:34:32 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6