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 "asterisk/format_cache.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_slin
#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), OPTIONS_NO_LOG = (1 << 6)
}
enum  sms_opt_args { OPTION_ARG_PAUSE = 0, OPTION_ARG_ARRAY_SIZE }

Functions

static void adddata_proto2 (sms_t *h, unsigned char msg, char *data, int size)
 AST_MODULE_INFO_STANDARD_EXTENDED (ASTERISK_GPL_KEY,"SMS/PSTN handler")
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 char * app = "SMS"
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 }, [ 'n' ] = { .flag = OPTIONS_NO_LOG }, [ '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_slin

Definition at line 151 of file app_sms.c.

Referenced by sms_generate().

#define DIR_RX   1

Definition at line 1485 of file app_sms.c.

Referenced by sms_debug(), and sms_messagerx().

#define DIR_TX   2

Definition at line 1486 of file app_sms.c.

Referenced by sms_messagetx().

#define DLL2_ACK ( h   )     ((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 285 of file app_sms.c.

Referenced by sms_readfile().

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

Definition at line 283 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 284 of file app_sms.c.

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

#define MAX_DEBUG_LEN   300

Definition at line 1250 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 154 of file app_sms.c.

Referenced by sms_messagetx().

#define SMSLEN   160

max SMS length

Definition at line 217 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 218 of file app_sms.c.

Referenced by packsms16(), and packsms8().


Typedef Documentation

typedef signed short output_t

Definition at line 149 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 163 of file app_sms.c.

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

enum sms_flags

Enumerator:
OPTION_BE_SMSC 
OPTION_ANSWER 
OPTION_TWO 
OPTION_PAUSE 
OPTION_SRR 
OPTION_DCS 
OPTIONS_NO_LOG 

Definition at line 1858 of file app_sms.c.

01858                {
01859    OPTION_BE_SMSC = (1 << 0),             /* act as sms center */
01860    OPTION_ANSWER  = (1 << 1),             /* answer on incoming calls */
01861    OPTION_TWO  = (1 << 2),                 /* Use Protocol Two */
01862    OPTION_PAUSE   = (1 << 3),             /* pause before sending data, in ms */
01863    OPTION_SRR  = (1 << 4),                 /* set srr */
01864    OPTION_DCS  = (1 << 5),                 /* set dcs */
01865    OPTIONS_NO_LOG = (1 << 6),             /* Don't log SMS content */
01866 };

Enumerator:
OPTION_ARG_PAUSE 
OPTION_ARG_ARRAY_SIZE 

Definition at line 1868 of file app_sms.c.

01868                   {
01869    OPTION_ARG_PAUSE = 0,
01870    OPTION_ARG_ARRAY_SIZE
01871 };


Function Documentation

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

References sms_s::omsg.

Referenced by putdummydata_proto2(), and sms_compose2().

01191 {
01192    int x = h->omsg[1] + 2;                 /* Get current position */
01193    if (x == 2) {
01194       x += 2;                             /* First: skip Payload length (set later) */
01195    }
01196    h->omsg[x++] = msg;                     /* Message code */
01197    h->omsg[x++] = (unsigned char)size;     /* Data size Low */
01198    h->omsg[x++] = 0;                       /* Data size Hi */
01199    for (; size > 0 ; size--) {
01200       h->omsg[x++] = *data++;
01201    }
01202    h->omsg[1] = x - 2;                     /* Frame size */
01203    h->omsg[2] = x - 4;                     /* Payload length (Lo) */
01204    h->omsg[3] = 0;                         /* Payload length (Hi) */
01205 }

AST_MODULE_INFO_STANDARD_EXTENDED ( ASTERISK_GPL_KEY  ,
"SMS/PSTN handler"   
)

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

static, return a date/time in ISO format

Definition at line 305 of file app_sms.c.

References ast_localtime(), ast_strftime(), and NULL.

Referenced by sms_log(), and sms_writefile().

00306 {
00307    struct ast_tm tm;
00308    struct timeval local = { t, 0 };
00309    ast_localtime(&local, &tm, NULL);
00310    ast_strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
00311    return buf;
00312 }

static int load_module ( void   )  [static]

Definition at line 2085 of file app_sms.c.

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

02086 {
02087 #ifdef OUTALAW
02088    int p;
02089    for (p = 0; p < 80; p++) {
02090       wavea[p] = AST_LIN2A(wave[p]);
02091    }
02092 #endif
02093    snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR);
02094    return ast_register_application_xml(app, sms_exec);
02095 }

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

copy number, skipping non digits apart from leading +

Definition at line 290 of file app_sms.c.

Referenced by sms_readfile().

00291 {
00292    if (*s == '+') {
00293       *d++ = *s++;
00294    }
00295    while (*s) {
00296       if (isdigit(*s)) {
00297          *d++ = *s;
00298       }
00299       s++;
00300    }
00301    *d = 0;
00302 }

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

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

Definition at line 748 of file app_sms.c.

Referenced by sms_compose1().

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

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

pack a date and return

Definition at line 555 of file app_sms.c.

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

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

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

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

Referenced by sms_compose1().

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

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

References dummy(), NULL, and SMSLEN_8.

Referenced by packsms(), and sms_readfile().

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

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

References b, dummy(), NULL, and SMSLEN.

Referenced by packsms(), and sms_readfile().

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

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

References dummy(), NULL, and SMSLEN_8.

Referenced by packsms(), and sms_readfile().

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

static void putdummydata_proto2 ( sms_t h  )  [static]

Definition at line 1207 of file app_sms.c.

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

Referenced by sms_compose2().

01208 {
01209    adddata_proto2(h, 0x10, "\0", 1);           /* Media Identifier > SMS */
01210    adddata_proto2(h, 0x11, "\0\0\0\0\0\0", 6); /* Firmware version */
01211    adddata_proto2(h, 0x12, "\2\0\4", 3);       /* SMS provider ID */
01212    adddata_proto2(h, 0x13, h->udtxt, h->udl);  /* Body */
01213 }

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

read dir skipping dot files...

Definition at line 1104 of file app_sms.c.

References f.

Referenced by sms_nextoutgoing().

01105 {
01106    struct dirent *f;
01107    do {
01108       f = readdir(d);
01109    } while (f && (*f->d_name == '.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] != '.'));
01110    return f;
01111 }

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

01687 {
01688    return sms_t_ptr;
01689 }

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

compose a message for protocol 1

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

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

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

Definition at line 1215 of file app_sms.c.

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

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

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

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

01488 {
01489    char txt[259 * 3 + 1];
01490    char *p = txt;                          /* always long enough */
01491    unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
01492    int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
01493    int q = 0;
01494    while (q < n && q < 30) {
01495       sprintf(p, " %02hhX", msg[q++]);
01496       p += 3;
01497    }
01498    if (q < n) {
01499       sprintf(p, "...");
01500    }
01501    ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
01502 }

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

Definition at line 1883 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, d, sms_s::dcs, sms_s::ipc0, sms_s::ipc1, LOG_ERROR, sms_s::nolog, sms_s::opause_0, OPTION_ARG_ARRAY_SIZE, OPTION_ARG_PAUSE, OPTION_BE_SMSC, OPTION_DCS, OPTION_SRR, OPTION_TWO, OPTIONS_NO_LOG, 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().

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

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

References __OUT_FMT, ast_alloca, ast_channel_name(), AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log, ast_write(), buf, 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.

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

static unsigned char sms_handleincoming ( sms_t h  )  [static]

handle the incoming message

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

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

static int sms_handleincoming_proto2 ( sms_t h  )  [static]

sms_handleincoming_proto2: handle the incoming message

Definition at line 1264 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, NULL, 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().

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

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

Definition at line 1251 of file app_sms.c.

References f, and MAX_DEBUG_LEN.

Referenced by sms_handleincoming_proto2().

01252 {
01253    char *p;
01254    int f;
01255 
01256    for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3) {
01257       sprintf(p, "%02hhX ", (unsigned char)buf[f]);
01258    }
01259    return(s);
01260 }

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

Log the output, and remove file.

Definition at line 776 of file app_sms.c.

References AST_FILE_MODE, ast_log, buf, sms_s::da, errno, isodate(), LOG_WARNING, sms_s::mr, sms_s::nolog, NULL, 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().

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

static void sms_messagerx ( sms_t h  )  [static]

Definition at line 1505 of file app_sms.c.

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

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

static void sms_messagerx2 ( sms_t h  )  [static]

Definition at line 1345 of file app_sms.c.

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

01346 {
01347    int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */
01348    int cause;
01349 
01350 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
01351    switch (p) {
01352    case DLL2_SMS_EST:                      /* Protocol 2: Connection ready (fake): send message  */
01353       sms_nextoutgoing (h);
01354       /* 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 "); */
01355       break;
01356 
01357    case DLL2_SMS_INFO_MO:                  /* transport SMS_SUBMIT */
01358    case DLL2_SMS_INFO_MT:                  /* transport SMS_DELIVERY */
01359       cause = sms_handleincoming_proto2(h);
01360       if (!cause) {                       /* ACK */
01361          sms_log(h, 'Y');
01362       }
01363       h->omsg[0] = DLL2_ACK(h);
01364       h->omsg[1] = 0x06;                  /* msg len */
01365       h->omsg[2] = 0x04;                  /* payload len */
01366       h->omsg[3] = 0x00;                  /* payload len */
01367       h->omsg[4] = 0x1f;                  /* Response type */
01368       h->omsg[5] = 0x01;                  /* parameter len */
01369       h->omsg[6] = 0x00;                  /* parameter len */
01370       h->omsg[7] = cause;                 /* CONFIRM or error */
01371       sms_messagetx(h);
01372       break;
01373 
01374    case DLL2_SMS_NACK:                     /* Protocol 2: SMS_NAK */
01375       h->omsg[0] = DLL2_SMS_REL;          /* SMS_REL */
01376       h->omsg[1] = 0x00;                  /* msg len */
01377       sms_messagetx(h);
01378       break;
01379 
01380    case DLL2_SMS_ACK0:
01381    case DLL2_SMS_ACK1:
01382       /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */
01383       if ( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
01384          /* a response to our Release, just hangup */
01385          h->hangup = 1;                  /* hangup */
01386       } else {
01387          /* XXX depending on what we are.. */
01388          ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY\n");
01389          sms_nextoutgoing (h);
01390       }
01391       break;
01392 
01393    case DLL2_SMS_REL:                      /* Protocol 2: SMS_REL (hangup req) */
01394       h->omsg[0] = DLL2_ACK(h);
01395       h->omsg[1] = 0;
01396       sms_messagetx(h);
01397       break;
01398    }
01399 }

static void sms_messagetx ( sms_t h  )  [static]

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

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

static void sms_nextoutgoing ( sms_t h  )  [static]

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

Definition at line 1444 of file app_sms.c.

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

Referenced by sms_messagerx(), and sms_messagerx2().

01445 {    
01446    char fn[100 + NAME_MAX] = "";
01447    DIR *d;
01448    char more = 0;
01449 
01450    *h->da = *h->oa = '\0';                 /* clear destinations */
01451    h->rx = 0;                              /* outgoing message */
01452    snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? "mttx" : "motx");
01453    ast_mkdir(fn, 0777);                    /* ensure it exists */
01454    d = opendir(fn);
01455    if (d) {
01456       struct dirent *f = readdirqueue(d, h->queue);
01457       if (f) {
01458          snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", f->d_name);
01459          sms_readfile(h, fn);
01460          if (readdirqueue(d, h->queue)) {
01461             more = 1;                   /* more to send */
01462          }
01463       }
01464       closedir(d);
01465    }
01466    if (*h->da || *h->oa) {                 /* message to send */
01467       if (h->protocol == 2) {
01468          sms_compose2(h, more);
01469       } else {
01470          sms_compose1(h, more);
01471       }
01472    } else {                                /* no message */
01473       if (h->protocol == 2) {
01474          h->omsg[0] = 0x17;              /* SMS_REL */
01475          h->omsg[1] = 0;
01476       } else {
01477          h->omsg[0] = 0x94;              /* SMS_REL */
01478          h->omsg[1] = 0;
01479          h->sent_rel = 1;
01480       }
01481    }
01482    sms_messagetx(h);
01483 }

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

References abs, 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_s::sent_rel, sms_messagerx(), and sms_messagetx().

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

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

parse and delete a file

Definition at line 829 of file app_sms.c.

References ast_log, ast_mktime(), ast_tvnow(), d, sms_s::da, sms_s::dcs, is16bit, is7bit, is8bit, LOG_NOTICE, LOG_WARNING, sms_s::mr, NULL, 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().

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

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

Definition at line 1691 of file app_sms.c.

01692 {
01693    return;  /* nothing to do here. */
01694 }

static void sms_writefile ( sms_t h  )  [static]

white a received text message to a file

Definition at line 1000 of file app_sms.c.

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

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

static int unload_module ( void   )  [static]

Definition at line 2080 of file app_sms.c.

References ast_unregister_application().

02081 {
02082    return ast_unregister_application(app);
02083 }

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

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

Definition at line 730 of file app_sms.c.

Referenced by sms_handleincoming().

00731 {
00732    unsigned char l = i[0], p;
00733    if (i[1] == 0x91) {
00734       *o++ = '+';
00735    }
00736    for (p = 0; p < l; p++) {
00737       if (p & 1) {
00738          *o++ = (i[2 + p / 2] >> 4) + '0';
00739       } else {
00740          *o++ = (i[2 + p / 2] & 0xF) + '0';
00741       }
00742    }
00743    *o = 0;
00744    return (l + 5) / 2;
00745 }

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

unpack a date and return

Definition at line 581 of file app_sms.c.

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

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

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

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

Referenced by sms_handleincoming().

00715 {
00716    int l = *i++;
00717    if (is7bit(dcs)) {
00718       unpacksms7(i, l, udh, udhl, ud, udl, udhi);
00719       l = (l * 7 + 7) / 8;                /* adjust length to return */
00720    } else if (is8bit(dcs)) {
00721       unpacksms8(i, l, udh, udhl, ud, udl, udhi);
00722    } else {
00723       l += l % 2;
00724       unpacksms16(i, l, udh, udhl, ud, udl, udhi);
00725    }
00726    return l + 1;
00727 }

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

Referenced by unpacksms().

00687 {
00688    unsigned short *o = ud;
00689    *udhl = 0;
00690    if (udhi) {
00691       int n = *i;
00692       *udhl = n;
00693       if (n) {
00694          i++;
00695          l--;
00696          while (l && n) {
00697             l--;
00698             n--;
00699             *udh++ = *i++;
00700          }
00701       }
00702    }
00703    while (l--) {
00704       int v = *i++;
00705       if (l && l--) {
00706          v = (v << 8) + *i++;
00707       }
00708       *o++ = v;
00709    }
00710    *udl = (o - ud);
00711 }

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

References b, and h.

Referenced by unpacksms().

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

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

Referenced by unpacksms().

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

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

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

Definition at line 317 of file app_sms.c.

Referenced by main(), rxqcheck(), and sms_readfile().

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


Variable Documentation

char* app = "SMS" [static]

Definition at line 126 of file app_sms.c.

const unsigned short defaultalphabet[] [static]

Definition at line 193 of file app_sms.c.

const unsigned short escapes[] [static]

Definition at line 206 of file app_sms.c.

char log_file[255] [static]

Definition at line 124 of file app_sms.c.

volatile unsigned char message_ref [static]

Definition at line 121 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 }, [ 'n' ] = { .flag = OPTIONS_NO_LOG }, [ 'p' ] = { .flag = OPTION_PAUSE , .arg_index = OPTION_ARG_PAUSE + 1 }, } [static]

Definition at line 1881 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 1696 of file app_sms.c.

const signed short wave[] [static]

Definition at line 134 of file app_sms.c.

const output_t* wave_out = wave [static]

Definition at line 150 of file app_sms.c.


Generated on Thu Apr 16 06:28:43 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6