Wed Jan 8 2020 09:49:55

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"

Go to the source code of this file.

Data Structures

struct  sms_s
 

Macros

#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 /* initial sync bits */
 
#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 More...
 
static int load_module (void)
 
static void numcpy (char *d, char *s)
 copy number, skipping non digits apart from leading + More...
 
static unsigned char packaddress (unsigned char *o, char *i)
 store an address at o, and return number of bytes used More...
 
static void packdate (unsigned char *o, time_t w)
 pack a date and return More...
 
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 More...
 
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 More...
 
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 More...
 
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 More...
 
static void putdummydata_proto2 (sms_t *h)
 
static struct dirent * readdirqueue (DIR *d, char *queue)
 read dir skipping dot files... More...
 
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 More...
 
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 More...
 
static int sms_handleincoming_proto2 (sms_t *h)
 sms_handleincoming_proto2: handle the incoming message More...
 
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. More...
 
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 More...
 
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 More...
 
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 More...
 
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 More...
 
static struct timeval unpackdate (unsigned char *i)
 unpack a date and return More...
 
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 More...
 
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 More...
 
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 More...
 
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. More...
 
static long utf8decode (unsigned char **pp)
 Reads next UCS character from NUL terminated UTF-8 string and advance pointer. More...
 

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 = "ac1f6a56484a8820659555499174e588" , .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.

Macro Definition 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 1475 of file app_sms.c.

Referenced by sms_debug(), and sms_messagerx().

#define DIR_TX   2

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

Referenced by sms_readfile().

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

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

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

#define MAX_DEBUG_LEN   300

Definition at line 1240 of file app_sms.c.

Referenced by sms_handleincoming_proto2(), and sms_hexdump().

#define MAXSAMPLES   (800)

Referenced by sms_generate().

#define OSYNC_BITS   80 /* initial sync bits */

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.

159  {
160  DLL_SMS_MASK = 0x7f, /* mask for the valid bits */
161 
162  /* Protocol 1 values */
163  DLL1_SMS_DATA = 0x11, /* data packet */
164  DLL1_SMS_ERROR = 0x12,
165  DLL1_SMS_EST = 0x13, /* start the connection */
166  DLL1_SMS_REL = 0x14, /* end the connection */
167  DLL1_SMS_ACK = 0x15,
168  DLL1_SMS_NACK = 0x16,
169 
170  DLL1_SMS_COMPLETE = 0x80, /* packet is complete */
171  DLL1_SMS_MORE = 0x00, /* more data to follow */
172 
173  /* Protocol 2 values */
174  DLL2_SMS_EST = 0x7f, /* magic number. No message body */
175  DLL2_SMS_INFO_MO = 0x10,
176  DLL2_SMS_INFO_MT = 0x11,
177  DLL2_SMS_INFO_STA = 0x12,
178  DLL2_SMS_NACK = 0x13,
179  DLL2_SMS_ACK0 = 0x14, /* ack even-numbered frame */
180  DLL2_SMS_ACK1 = 0x15, /* ack odd-numbered frame */
181  DLL2_SMS_ENQ = 0x16,
182  DLL2_SMS_REL = 0x17, /* end the connection */
183 
184  DLL2_SMS_COMPLETE = 0x00, /* packet is complete */
185  DLL2_SMS_MORE = 0x80, /* more data to follow */
186 };
enum sms_flags
Enumerator
OPTION_BE_SMSC 
OPTION_ANSWER 
OPTION_TWO 
OPTION_PAUSE 
OPTION_SRR 
OPTION_DCS 

Definition at line 1846 of file app_sms.c.

1846  {
1847  OPTION_BE_SMSC = (1 << 0), /* act as sms center */
1848  OPTION_ANSWER = (1 << 1), /* answer on incoming calls */
1849  OPTION_TWO = (1 << 2), /* Use Protocol Two */
1850  OPTION_PAUSE = (1 << 3), /* pause before sending data, in ms */
1851  OPTION_SRR = (1 << 4), /* set srr */
1852  OPTION_DCS = (1 << 5), /* set dcs */
1853 };
Enumerator
OPTION_ARG_PAUSE 
OPTION_ARG_ARRAY_SIZE 

Definition at line 1855 of file app_sms.c.

Function Documentation

static void __reg_module ( void  )
static

Definition at line 2082 of file app_sms.c.

static void __unreg_module ( void  )
static

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

References sms_s::omsg.

Referenced by putdummydata_proto2(), and sms_compose2().

1181 {
1182  int x = h->omsg[1] + 2; /* Get current position */
1183  if (x == 2) {
1184  x += 2; /* First: skip Payload length (set later) */
1185  }
1186  h->omsg[x++] = msg; /* Message code */
1187  h->omsg[x++] = (unsigned char)size; /* Data size Low */
1188  h->omsg[x++] = 0; /* Data size Hi */
1189  for (; size > 0 ; size--) {
1190  h->omsg[x++] = *data++;
1191  }
1192  h->omsg[1] = x - 2; /* Frame size */
1193  h->omsg[2] = x - 4; /* Payload length (Lo) */
1194  h->omsg[3] = 0; /* Payload length (Hi) */
1195 }
unsigned char omsg[256]
Definition: app_sms.c:246
static char* isodate ( time_t  t,
char *  buf,
int  len 
)
static

static, return a date/time in ISO format

Definition at line 300 of file app_sms.c.

References ast_localtime(), and ast_strftime().

Referenced by sms_log(), and sms_writefile().

301 {
302  struct ast_tm tm;
303  struct timeval local = { t, 0 };
304  ast_localtime(&local, &tm, NULL);
305  ast_strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
306  return buf;
307 }
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
static int load_module ( void  )
static

Definition at line 2070 of file app_sms.c.

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

2071 {
2072 #ifdef OUTALAW
2073  int p;
2074  for (p = 0; p < 80; p++) {
2075  wavea[p] = AST_LIN2A(wave[p]);
2076  }
2077 #endif
2078  snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR);
2080 }
static char * app
Definition: app_sms.c:122
static int sms_exec(struct ast_channel *chan, const char *data)
Definition: app_sms.c:1869
static const signed short wave[]
Definition: app_sms.c:130
static char log_file[255]
Definition: app_sms.c:120
const char * ast_config_AST_LOG_DIR
Definition: asterisk.c:263
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
#define AST_LIN2A(a)
Definition: alaw.h:50
static void numcpy ( char *  d,
char *  s 
)
static

copy number, skipping non digits apart from leading +

Definition at line 285 of file app_sms.c.

Referenced by sms_readfile().

286 {
287  if (*s == '+') {
288  *d++ = *s++;
289  }
290  while (*s) {
291  if (isdigit(*s)) {
292  *d++ = *s;
293  }
294  s++;
295  }
296  *d = 0;
297 }
static unsigned char packaddress ( unsigned char *  o,
char *  i 
)
static

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

Definition at line 743 of file app_sms.c.

Referenced by sms_compose1().

744 {
745  unsigned char p = 2;
746  o[0] = 0; /* number of bytes */
747  if (*i == '+') { /* record as bit 0 in byte 1 */
748  i++;
749  o[1] = 0x91;
750  } else {
751  o[1] = 0x81;
752  }
753  for ( ; *i ; i++) {
754  if (!isdigit(*i)) { /* ignore non-digits */
755  continue;
756  }
757  if (o[0] & 1) {
758  o[p++] |= ((*i & 0xF) << 4);
759  } else {
760  o[p] = (*i & 0xF);
761  }
762  o[0]++;
763  }
764  if (o[0] & 1) {
765  o[p++] |= 0xF0; /* pad */
766  }
767  return p;
768 }
static void packdate ( unsigned char *  o,
time_t  w 
)
static

pack a date and return

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

551 {
552  struct ast_tm t;
553  struct timeval topack = { w, 0 };
554  int z;
555 
556  ast_localtime(&topack, &t, NULL);
557 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
558  z = -t.tm_gmtoff / 60 / 15;
559 #else
560  z = timezone / 60 / 15;
561 #endif
562  *o++ = ((t.tm_year % 10) << 4) + (t.tm_year % 100) / 10;
563  *o++ = (((t.tm_mon + 1) % 10) << 4) + (t.tm_mon + 1) / 10;
564  *o++ = ((t.tm_mday % 10) << 4) + t.tm_mday / 10;
565  *o++ = ((t.tm_hour % 10) << 4) + t.tm_hour / 10;
566  *o++ = ((t.tm_min % 10) << 4) + t.tm_min / 10;
567  *o++ = ((t.tm_sec % 10) << 4) + t.tm_sec / 10;
568  if (z < 0) {
569  *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
570  } else {
571  *o++ = ((z % 10) << 4) + z / 10;
572  }
573 }
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
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 517 of file app_sms.c.

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

Referenced by sms_compose1().

518 {
519  unsigned char *p = base;
520  if (udl == 0) {
521  *p++ = 0; /* no user data */
522  } else {
523 
524  int l = 0;
525  if (is7bit(dcs)) { /* 7 bit */
526  if ((l = packsms7(p + 1, udhl, udh, udl, ud)) < 0) {
527  l = 0;
528  }
529  *p++ = l;
530  p += (l * 7 + 7) / 8;
531  } else if (is8bit(dcs)) { /* 8 bit */
532  if ((l = packsms8(p + 1, udhl, udh, udl, ud)) < 0) {
533  l = 0;
534  }
535  *p++ = l;
536  p += l;
537  } else { /* UCS-2 */
538  if ((l = packsms16(p + 1, udhl, udh, udl, ud)) < 0) {
539  l = 0;
540  }
541  *p++ = l;
542  p += l;
543  }
544  }
545  return p - base;
546 }
#define is7bit(dcs)
Definition: app_sms.c:278
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 ...
Definition: app_sms.c:482
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 ...
Definition: app_sms.c:366
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 ...
Definition: app_sms.c:443
#define is8bit(dcs)
Definition: app_sms.c:279
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 482 of file app_sms.c.

References dummy(), and SMSLEN_8.

Referenced by packsms(), and sms_readfile().

483 {
484  unsigned char p = 0;
485  unsigned char dummy[SMSLEN_8];
486 
487  if (o == NULL) {
488  o = dummy;
489  }
490  /* header - no encoding */
491  if (udhl) {
492  o[p++] = udhl;
493  while (udhl--) {
494  o[p++] = *udh++;
495  if (p >= SMSLEN_8) {
496  return p;
497  }
498  }
499  }
500  while (udl--) {
501  long u;
502  u = *ud++;
503  o[p++] = (u >> 8);
504  if (p >= SMSLEN_8) {
505  return p - 1; /* could not fit last character */
506  }
507  o[p++] = u;
508  if (p >= SMSLEN_8) {
509  return p;
510  }
511  }
512  return p;
513 }
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
#define SMSLEN_8
Definition: app_sms.c:214
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 366 of file app_sms.c.

References dummy(), and SMSLEN.

Referenced by packsms(), and sms_readfile().

367 {
368  unsigned char p = 0; /* output pointer (bytes) */
369  unsigned char b = 0; /* bit position */
370  unsigned char n = 0; /* output character count */
371  unsigned char dummy[SMSLEN];
372 
373  if (o == NULL) { /* output to a dummy buffer if o not set */
374  o = dummy;
375  }
376 
377  if (udhl) { /* header */
378  o[p++] = udhl;
379  b = 1;
380  n = 1;
381  while (udhl--) {
382  o[p++] = *udh++;
383  b += 8;
384  while (b >= 7) {
385  b -= 7;
386  n++;
387  }
388  if (n >= SMSLEN)
389  return n;
390  }
391  if (b) {
392  b = 7 - b;
393  if (++n >= SMSLEN)
394  return n;
395  } /* filling to septet boundary */
396  }
397  o[p] = 0;
398  /* message */
399  while (udl--) {
400  long u;
401  unsigned char v;
402  u = *ud++;
403  /* XXX 0 is invalid ? */
404  /* look up in defaultalphabet[]. If found, v is the 7-bit code */
405  for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
406  if (v == 128 /* not found */ && u && n + 1 < SMSLEN) {
407  /* if not found, look in the escapes table (we need 2 bytes) */
408  for (v = 0; v < 128 && escapes[v] != u; v++);
409  if (v < 128) { /* escaped sequence, esc + v */
410  /* store the low (8-b) bits in o[p], the remaining bits in o[p+1] */
411  o[p] |= (27 << b); /* the low bits go into o[p] */
412  b += 7;
413  if (b >= 8) {
414  b -= 8;
415  p++;
416  o[p] = (27 >> (7 - b));
417  }
418  n++;
419  }
420  }
421  if (v == 128)
422  return -1; /* invalid character */
423  /* store, same as above */
424  o[p] |= (v << b);
425  b += 7;
426  if (b >= 8) {
427  b -= 8;
428  p++;
429  o[p] = (v >> (7 - b));
430  }
431  if (++n >= SMSLEN)
432  return n;
433  }
434  return n;
435 }
#define SMSLEN
Definition: app_sms.c:213
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
static const unsigned short defaultalphabet[]
Definition: app_sms.c:189
static const unsigned short escapes[]
Definition: app_sms.c:202
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 443 of file app_sms.c.

References dummy(), and SMSLEN_8.

Referenced by packsms(), and sms_readfile().

444 {
445  unsigned char p = 0;
446  unsigned char dummy[SMSLEN_8];
447 
448  if (o == NULL)
449  o = dummy;
450  /* header - no encoding */
451  if (udhl) {
452  o[p++] = udhl;
453  while (udhl--) {
454  o[p++] = *udh++;
455  if (p >= SMSLEN_8) {
456  return p;
457  }
458  }
459  }
460  while (udl--) {
461  long u;
462  u = *ud++;
463  if (u < 0 || u > 0xFF) {
464  return -1; /* not valid */
465  }
466  o[p++] = u;
467  if (p >= SMSLEN_8) {
468  return p;
469  }
470  }
471  return p;
472 }
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
#define SMSLEN_8
Definition: app_sms.c:214
static void putdummydata_proto2 ( sms_t h)
static

Definition at line 1197 of file app_sms.c.

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

Referenced by sms_compose2().

1198 {
1199  adddata_proto2(h, 0x10, "\0", 1); /* Media Identifier > SMS */
1200  adddata_proto2(h, 0x11, "\0\0\0\0\0\0", 6); /* Firmware version */
1201  adddata_proto2(h, 0x12, "\2\0\4", 3); /* SMS provider ID */
1202  adddata_proto2(h, 0x13, h->udtxt, h->udl); /* Body */
1203 }
char udtxt[SMSLEN]
Definition: app_sms.c:274
static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
Definition: app_sms.c:1180
int udl
Definition: app_sms.c:229
static struct dirent* readdirqueue ( DIR *  d,
char *  queue 
)
static

read dir skipping dot files...

Definition at line 1094 of file app_sms.c.

References f.

Referenced by sms_nextoutgoing().

1095 {
1096  struct dirent *f;
1097  do {
1098  f = readdir(d);
1099  } while (f && (*f->d_name == '.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] != '.'));
1100  return f;
1101 }
static struct ast_format f[]
Definition: format_g726.c:181
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 1674 of file app_sms.c.

1675 {
1676  return sms_t_ptr;
1677 }
static void sms_compose1 ( sms_t h,
int  more 
)
static

compose a message for protocol 1

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

1393 {
1394  unsigned int p = 2; /* next byte to write. Skip type and len */
1395 
1396  h->omsg[0] = 0x91; /* SMS_DATA */
1397  if (h->smsc) { /* deliver */
1398  h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
1399  p += packaddress(h->omsg + p, h->oa);
1400  h->omsg[p++] = h->pid;
1401  h->omsg[p++] = h->dcs;
1402  packdate(h->omsg + p, h->scts.tv_sec);
1403  p += 7;
1404  p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
1405  } else { /* submit */
1406  h->omsg[p++] =
1407  0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
1408  if (h->mr < 0) {
1409  h->mr = message_ref++;
1410  }
1411  h->omsg[p++] = h->mr;
1412  p += packaddress(h->omsg + p, h->da);
1413  h->omsg[p++] = h->pid;
1414  h->omsg[p++] = h->dcs;
1415  if (h->vp) { /* relative VP */
1416  if (h->vp < 720) {
1417  h->omsg[p++] = (h->vp + 4) / 5 - 1;
1418  } else if (h->vp < 1440) {
1419  h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
1420  } else if (h->vp < 43200) {
1421  h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
1422  } else if (h->vp < 635040) {
1423  h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
1424  } else {
1425  h->omsg[p++] = 255; /* max */
1426  }
1427  }
1428  p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
1429  }
1430  h->omsg[1] = p - 2;
1431 }
unsigned int vp
Definition: app_sms.c:234
int udhl
Definition: app_sms.c:230
static void packdate(unsigned char *o, time_t w)
pack a date and return
Definition: app_sms.c:550
static unsigned char packaddress(unsigned char *o, char *i)
store an address at o, and return number of bytes used
Definition: app_sms.c:743
unsigned char udhi
Definition: app_sms.c:232
struct timeval scts
Definition: app_sms.c:225
unsigned char omsg[256]
Definition: app_sms.c:246
static volatile unsigned char message_ref
Definition: app_sms.c:117
unsigned char srr
Definition: app_sms.c:231
unsigned char smsc
Definition: app_sms.c:220
unsigned char rp
Definition: app_sms.c:233
unsigned short ud[SMSLEN]
Definition: app_sms.c:235
short mr
Definition: app_sms.c:228
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
Definition: app_sms.c:517
int udl
Definition: app_sms.c:229
char da[20]
Definition: app_sms.c:224
unsigned char dcs
Definition: app_sms.c:227
char oa[20]
Definition: app_sms.c:223
unsigned char pid
Definition: app_sms.c:226
unsigned char udh[SMSLEN]
Definition: app_sms.c:236
static void sms_compose2 ( sms_t h,
int  more 
)
static

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

1206 {
1207  struct ast_tm tm;
1208  struct timeval now = h->scts;
1209  char stm[9];
1210 
1211  h->omsg[0] = 0x00; /* set later... */
1212  h->omsg[1] = 0;
1214  if (h->smsc) { /* deliver */
1215  h->omsg[0] = 0x11; /* SMS_DELIVERY */
1216  /* Required: 10 11 12 13 14 15 17 (seems they must be ordered!) */
1217  ast_localtime(&now, &tm, NULL);
1218  sprintf(stm, "%02d%02d%02d%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min); /* Date mmddHHMM */
1219  adddata_proto2(h, 0x14, stm, 8); /* Date */
1220  if (*h->oa == 0) {
1221  strcpy(h->oa, "00000000");
1222  }
1223  adddata_proto2(h, 0x15, h->oa, strlen(h->oa)); /* Originator */
1224  adddata_proto2(h, 0x17, "\1", 1); /* Calling Terminal ID */
1225  } else { /* submit */
1226  h->omsg[0] = 0x10; /* SMS_SUBMIT */
1227  /* Required: 10 11 12 13 17 18 1B 1C (seems they must be ordered!) */
1228  adddata_proto2(h, 0x17, "\1", 1); /* Calling Terminal ID */
1229  if (*h->da == 0) {
1230  strcpy(h->da, "00000000");
1231  }
1232  adddata_proto2(h, 0x18, h->da, strlen(h->da)); /* Originator */
1233  adddata_proto2(h, 0x1B, "\1", 1); /* Called Terminal ID */
1234  adddata_proto2(h, 0x1C, "\0\0\0", 3); /* Notification */
1235  }
1236 }
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
struct timeval scts
Definition: app_sms.c:225
unsigned char omsg[256]
Definition: app_sms.c:246
unsigned char smsc
Definition: app_sms.c:220
static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
Definition: app_sms.c:1180
char da[20]
Definition: app_sms.c:224
char oa[20]
Definition: app_sms.c:223
static void putdummydata_proto2(sms_t *h)
Definition: app_sms.c:1197
static void sms_debug ( int  dir,
sms_t h 
)
static

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

1478 {
1479  char txt[259 * 3 + 1];
1480  char *p = txt; /* always long enough */
1481  unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
1482  int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
1483  int q = 0;
1484  while (q < n && q < 30) {
1485  sprintf(p, " %02X", (unsigned)msg[q++]);
1486  p += 3;
1487  }
1488  if (q < n) {
1489  sprintf(p, "...");
1490  }
1491  ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
1492 }
unsigned char ibytep
Definition: app_sms.c:263
unsigned char imsg[250]
Definition: app_sms.c:247
#define ast_verb(level,...)
Definition: logger.h:243
unsigned char omsg[256]
Definition: app_sms.c:246
#define DIR_RX
Definition: app_sms.c:1475
static int sms_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 1869 of file app_sms.c.

References AST_APP_ARG, ast_app_parse_options(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verb, ast_channel::caller, sms_s::cli, sms_s::dcs, ast_party_caller::id, sms_s::ipc0, sms_s::ipc1, LOG_ERROR, ast_party_id::number, 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, sms_s::srr, ast_party_number::str, and ast_party_number::valid.

Referenced by load_module().

1870 {
1871  int res = -1;
1872  sms_t h = { 0 };
1873  /* argument parsing support */
1874  struct ast_flags flags = { 0 };
1875  char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, };
1876  char *p;
1877  AST_DECLARE_APP_ARGS(sms_args,
1878  AST_APP_ARG(queue);
1879  AST_APP_ARG(options);
1880  AST_APP_ARG(addr);
1881  AST_APP_ARG(body);
1882  );
1883 
1884  if (!data) {
1885  ast_log(LOG_ERROR, "Requires queue name at least\n");
1886  return -1;
1887  }
1888 
1889  parse = ast_strdupa(data); /* create a local copy */
1890  AST_STANDARD_APP_ARGS(sms_args, parse);
1891  if (sms_args.argc > 1) {
1892  ast_app_parse_options(sms_options, &flags, sms_opts, sms_args.options);
1893  }
1894 
1895  ast_verb(1, "sms argc %u queue <%s> opts <%s> addr <%s> body <%s>\n",
1896  sms_args.argc, S_OR(sms_args.queue, ""),
1897  S_OR(sms_args.options, ""),
1898  S_OR(sms_args.addr, ""),
1899  S_OR(sms_args.body, "") );
1900 
1901  h.ipc0 = h.ipc1 = 20; /* phase for cosine */
1902  h.dcs = 0xF1; /* default */
1903 
1904  ast_copy_string(h.cli,
1905  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
1906  sizeof(h.cli));
1907 
1908  if (ast_strlen_zero(sms_args.queue)) {
1909  ast_log(LOG_ERROR, "Requires queue name\n");
1910  goto done;
1911  }
1912  if (strlen(sms_args.queue) >= sizeof(h.queue)) {
1913  ast_log(LOG_ERROR, "Queue name too long\n");
1914  goto done;
1915  }
1916  ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue));
1917 
1918  for (p = h.queue; *p; p++) {
1919  if (!isalnum(*p)) {
1920  *p = '-'; /* make very safe for filenames */
1921  }
1922  }
1923 
1924  h.smsc = ast_test_flag(&flags, OPTION_BE_SMSC);
1925  h.protocol = ast_test_flag(&flags, OPTION_TWO) ? 2 : 1;
1926  if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE])) {
1927  h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
1928  }
1929  if (h.opause_0 < 25 || h.opause_0 > 2000) {
1930  h.opause_0 = 300; /* default 300ms */
1931  }
1932  ast_verb(1, "initial delay %dms\n", h.opause_0);
1933 
1934 
1935  /* the following apply if there is an arg3/4 and apply to the created message file */
1936  if (ast_test_flag(&flags, OPTION_SRR)) {
1937  h.srr = 1;
1938  }
1939  if (ast_test_flag(&flags, OPTION_DCS)) {
1940  h.dcs = 1;
1941  }
1942 #if 0
1943  case '1':
1944  case '2':
1945  case '3':
1946  case '4':
1947  case '5':
1948  case '6':
1949  case '7': /* set the pid for saved local message */
1950  h.pid = 0x40 + (*d & 0xF);
1951  break;
1952  }
1953 #endif
1954  if (sms_args.argc > 2) {
1955  unsigned char *up;
1956 
1957  /* submitting a message, not taking call. */
1958  /* deprecated, use smsq instead */
1959  h.scts = ast_tvnow();
1960  if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) {
1961  ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr);
1962  goto done;
1963  }
1964  if (h.smsc) {
1965  ast_copy_string(h.oa, sms_args.addr, sizeof(h.oa));
1966  } else {
1967  ast_copy_string(h.da, sms_args.addr, sizeof(h.da));
1968  ast_copy_string(h.oa, h.cli, sizeof(h.oa));
1969  }
1970  h.udl = 0;
1971  if (ast_strlen_zero(sms_args.body)) {
1972  ast_log(LOG_ERROR, "Missing body for %s\n", sms_args.addr);
1973  goto done;
1974  }
1975  up = (unsigned char *)sms_args.body;
1976  while (*up && h.udl < SMSLEN) {
1977  h.ud[h.udl++] = utf8decode(&up);
1978  }
1979  if (is7bit(h.dcs) && packsms7(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1980  ast_log(LOG_WARNING, "Invalid 7 bit GSM data\n");
1981  goto done;
1982  }
1983  if (is8bit(h.dcs) && packsms8(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1984  ast_log(LOG_WARNING, "Invalid 8 bit data\n");
1985  goto done;
1986  }
1987  if (is16bit(h.dcs) && packsms16(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1988  ast_log(LOG_WARNING, "Invalid 16 bit data\n");
1989  goto done;
1990  }
1991  h.rx = 0; /* sent message */
1992  h.mr = -1;
1993  sms_writefile(&h);
1994  res = h.err;
1995  goto done;
1996  }
1997 
1998  if (chan->_state != AST_STATE_UP) { /* make sure channel is answered before any TX */
1999  ast_answer(chan);
2000  }
2001 
2002  if (ast_test_flag(&flags, OPTION_ANSWER)) {
2003  h.framenumber = 1; /* Proto 2 */
2004  /* set up SMS_EST initial message */
2005  if (h.protocol == 2) {
2006  h.omsg[0] = DLL2_SMS_EST;
2007  h.omsg[1] = 0;
2008  } else {
2010  h.omsg[1] = 0;
2011  }
2012  sms_messagetx(&h);
2013  }
2014 
2015  res = ast_set_write_format(chan, __OUT_FMT);
2016  if (res >= 0) {
2018  }
2019  if (res < 0) {
2020  ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
2021  goto done;
2022  }
2023 
2024  if ( (res = ast_activate_generator(chan, &smsgen, &h)) < 0) {
2025  ast_log(LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
2026  goto done;
2027  }
2028 
2029  /* Do our thing here */
2030  for (;;) {
2031  struct ast_frame *f;
2032  int i = ast_waitfor(chan, -1);
2033  if (i < 0) {
2034  ast_log(LOG_NOTICE, "waitfor failed\n");
2035  break;
2036  }
2037  if (h.hangup) {
2038  ast_log(LOG_NOTICE, "channel hangup\n");
2039  break;
2040  }
2041  f = ast_read(chan);
2042  if (!f) {
2043  ast_log(LOG_NOTICE, "ast_read failed\n");
2044  break;
2045  }
2046  if (f->frametype == AST_FRAME_VOICE) {
2047  sms_process(&h, f->samples, f->data.ptr);
2048  }
2049 
2050  ast_frfree(f);
2051  }
2052  res = h.err; /* XXX */
2053 
2054  /*
2055  * The SMS generator data is on the stack. We _MUST_ make sure the generator
2056  * is stopped before returning from this function.
2057  */
2059 
2060  sms_log(&h, '?'); /* log incomplete message */
2061 done:
2062  return (res);
2063 }
#define is7bit(dcs)
Definition: app_sms.c:278
static void sms_messagetx(sms_t *h)
Definition: app_sms.c:1553
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
unsigned char hangup
Definition: app_sms.c:217
unsigned char ipc1
Definition: app_sms.c:257
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int opause_0
Definition: app_sms.c:270
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
Definition: channel.c:3148
static long utf8decode(unsigned char **pp)
Reads next UCS character from NUL terminated UTF-8 string and advance pointer.
Definition: app_sms.c:312
void * ptr
Definition: frame.h:160
#define SMSLEN
Definition: app_sms.c:213
int udhl
Definition: app_sms.c:230
unsigned char ipc0
Definition: app_sms.c:256
#define LOG_WARNING
Definition: logger.h:144
unsigned char rx
Definition: app_sms.c:221
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
unsigned int flags
Definition: utils.h:201
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
Definition: app_sms.c:216
#define ast_verb(level,...)
Definition: logger.h:243
struct timeval scts
Definition: app_sms.c:225
unsigned char omsg[256]
Definition: app_sms.c:246
static void sms_process(sms_t *h, int samples, signed short *data)
Definition: app_sms.c:1702
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
char queue[30]
Definition: app_sms.c:222
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
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 ...
Definition: app_sms.c:482
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
unsigned char srr
Definition: app_sms.c:231
static void sms_writefile(sms_t *h)
white a received text message to a file
Definition: app_sms.c:990
unsigned char smsc
Definition: app_sms.c:220
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
int framenumber
Definition: app_sms.c:273
#define is16bit(dcs)
Definition: app_sms.c:280
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
char cli[20]
Definition: app_sms.c:237
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_app_option sms_options[128]
Definition: app_sms.c:1867
static struct ast_generator smsgen
Definition: app_sms.c:1684
unsigned short ud[SMSLEN]
Definition: app_sms.c:235
#define __OUT_FMT
Definition: app_sms.c:147
while(yyssp!=yyss)
Definition: ast_expr2.c:2538
short mr
Definition: app_sms.c:228
#define LOG_NOTICE
Definition: logger.h:133
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static void sms_log(sms_t *h, char status)
Log the output, and remove file.
Definition: app_sms.c:771
static struct ast_format f[]
Definition: format_g726.c:181
Structure used to handle boolean flags.
Definition: utils.h:200
int udl
Definition: app_sms.c:229
void ast_deactivate_generator(struct ast_channel *chan)
Definition: channel.c:3107
unsigned char err
Definition: app_sms.c:218
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 ...
Definition: app_sms.c:366
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
char da[20]
Definition: app_sms.c:224
unsigned char dcs
Definition: app_sms.c:227
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
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 ...
Definition: app_sms.c:443
Data structure associated with a single frame of data.
Definition: frame.h:142
char oa[20]
Definition: app_sms.c:223
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
union ast_frame::@172 data
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
#define is8bit(dcs)
Definition: app_sms.c:279
unsigned char pid
Definition: app_sms.c:226
int protocol
Definition: app_sms.c:271
int samples
Definition: frame.h:150
unsigned char udh[SMSLEN]
Definition: app_sms.c:236
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
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 1596 of file app_sms.c.

References __OUT_FMT, ast_alloca, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, DLL2_SMS_EST, errno, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, MAXSAMPLES, ast_channel::name, sms_s::obitp, sms_s::obyte, sms_s::obyten, sms_s::obytep, ast_frame::offset, sms_s::omsg, sms_s::opause, sms_s::ophase, sms_s::ophasep, sms_s::oseizure, sms_s::osync, sms_s::protocol, ast_frame::ptr, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

1597 {
1598  struct ast_frame f = { 0 };
1599 #define MAXSAMPLES (800)
1600  output_t *buf;
1601  sms_t *h = data;
1602  int i;
1603 
1604  if (samples > MAXSAMPLES) {
1605  ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
1606  MAXSAMPLES, samples);
1607  samples = MAXSAMPLES;
1608  }
1609  len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET;
1610  buf = ast_alloca(len);
1611 
1613  f.subclass.codec = __OUT_FMT;
1614  f.datalen = samples * sizeof(*buf);
1616  f.mallocd = 0;
1617  f.data.ptr = buf;
1618  f.samples = samples;
1619  f.src = "app_sms";
1620  /* create a buffer containing the digital sms pattern */
1621  for (i = 0; i < samples; i++) {
1622  buf[i] = wave_out[0]; /* default is silence */
1623 
1624  if (h->opause) {
1625  h->opause--;
1626  } else if (h->obyten || h->osync) { /* sending data */
1627  buf[i] = wave_out[h->ophase];
1628  h->ophase += (h->obyte & 1) ? 13 : 21; /* compute next phase */
1629  if (h->ophase >= 80)
1630  h->ophase -= 80;
1631  if ((h->ophasep += 12) >= 80) { /* time to send the next bit */
1632  h->ophasep -= 80;
1633  if (h->oseizure > 0) { /* sending channel seizure (proto 2) */
1634  h->oseizure--;
1635  h->obyte ^= 1; /* toggle low bit */
1636  } else if (h->osync) {
1637  h->obyte = 1; /* send mark as sync bit */
1638  h->osync--; /* sending sync bits */
1639  if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
1640  h->obytep = h->obyten = 0; /* we are done */
1641  }
1642  } else {
1643  h->obitp++;
1644  if (h->obitp == 1) {
1645  h->obyte = 0; /* start bit; */
1646  } else if (h->obitp == 2) {
1647  h->obyte = h->omsg[h->obytep];
1648  } else if (h->obitp == 10) {
1649  h->obyte = 1; /* stop bit */
1650  h->obitp = 0;
1651  h->obytep++;
1652  if (h->obytep == h->obyten) {
1653  h->obytep = h->obyten = 0; /* sent */
1654  h->osync = 10; /* trailing marks */
1655  }
1656  } else {
1657  h->obyte >>= 1;
1658  }
1659  }
1660  }
1661  }
1662  }
1663  if (ast_write(chan, &f) < 0) {
1664  ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
1665  return -1;
1666  }
1667  return 0;
1668 #undef MAXSAMPLES
1669 }
union ast_frame_subclass subclass
Definition: frame.h:146
int offset
Definition: frame.h:156
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
void * ptr
Definition: frame.h:160
unsigned char obyten
Definition: app_sms.c:245
unsigned char ophase
Definition: app_sms.c:238
#define LOG_WARNING
Definition: logger.h:144
unsigned char obitp
Definition: app_sms.c:242
unsigned char osync
Definition: app_sms.c:243
format_t codec
Definition: frame.h:137
Definition: app_sms.c:216
unsigned char omsg[256]
Definition: app_sms.c:246
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
const char * src
Definition: frame.h:158
int datalen
Definition: frame.h:148
unsigned char obyte
Definition: app_sms.c:240
static const output_t * wave_out
Definition: app_sms.c:146
signed short output_t
Definition: app_sms.c:145
unsigned char ophasep
Definition: app_sms.c:239
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned char obytep
Definition: app_sms.c:244
#define __OUT_FMT
Definition: app_sms.c:147
int oseizure
Definition: app_sms.c:272
int errno
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
int mallocd
Definition: frame.h:152
unsigned int opause
Definition: app_sms.c:241
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define MAXSAMPLES
union ast_frame::@172 data
int protocol
Definition: app_sms.c:271
int samples
Definition: frame.h:150
static unsigned char sms_handleincoming ( sms_t h)
static

handle the incoming message

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

1105 {
1106  unsigned char p = 3;
1107  if (h->smsc) { /* SMSC */
1108  if ((h->imsg[2] & 3) == 1) { /* SMS-SUBMIT */
1109  h->udhl = h->udl = 0;
1110  h->vp = 0;
1111  h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1112  h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1113  h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1114  ast_copy_string(h->oa, h->cli, sizeof(h->oa));
1115  h->scts = ast_tvnow();
1116  h->mr = h->imsg[p++];
1117  p += unpackaddress(h->da, h->imsg + p);
1118  h->pid = h->imsg[p++];
1119  h->dcs = h->imsg[p++];
1120  if ((h->imsg[2] & 0x18) == 0x10) { /* relative VP */
1121  if (h->imsg[p] < 144) {
1122  h->vp = (h->imsg[p] + 1) * 5;
1123  } else if (h->imsg[p] < 168) {
1124  h->vp = 720 + (h->imsg[p] - 143) * 30;
1125  } else if (h->imsg[p] < 197) {
1126  h->vp = (h->imsg[p] - 166) * 1440;
1127  } else {
1128  h->vp = (h->imsg[p] - 192) * 10080;
1129  }
1130  p++;
1131  } else if (h->imsg[2] & 0x18) {
1132  p += 7; /* ignore enhanced / absolute VP */
1133  }
1134  p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1135  h->rx = 1; /* received message */
1136  sms_writefile(h); /* write the file */
1137  if (p != h->imsg[1] + 2) {
1138  ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1139  return 0xFF; /* duh! */
1140  }
1141  } else {
1142  ast_log(LOG_WARNING, "Unknown message type %02X\n", (unsigned)h->imsg[2]);
1143  return 0xFF;
1144  }
1145  } else { /* client */
1146  if (!(h->imsg[2] & 3)) { /* SMS-DELIVER */
1147  *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
1148  h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1149  h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1150  h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1151  h->mr = -1;
1152  p += unpackaddress(h->oa, h->imsg + p);
1153  h->pid = h->imsg[p++];
1154  h->dcs = h->imsg[p++];
1155  h->scts = unpackdate(h->imsg + p);
1156  p += 7;
1157  p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1158  h->rx = 1; /* received message */
1159  sms_writefile(h); /* write the file */
1160  if (p != h->imsg[1] + 2) {
1161  ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1162  return 0xFF; /* duh! */
1163  }
1164  } else {
1165  ast_log(LOG_WARNING, "Unknown message type %02X\n", (unsigned)h->imsg[2]);
1166  return 0xFF;
1167  }
1168  }
1169  return 0; /* no error */
1170 }
unsigned int vp
Definition: app_sms.c:234
int udhl
Definition: app_sms.c:230
#define LOG_WARNING
Definition: logger.h:144
unsigned char rx
Definition: app_sms.c:221
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
static unsigned char unpackaddress(char *o, unsigned char *i)
unpack an address from i, return byte length, unpack to o
Definition: app_sms.c:725
unsigned char imsg[250]
Definition: app_sms.c:247
unsigned char udhi
Definition: app_sms.c:232
struct timeval scts
Definition: app_sms.c:225
unsigned char srr
Definition: app_sms.c:231
static void sms_writefile(sms_t *h)
white a received text message to a file
Definition: app_sms.c:990
unsigned char smsc
Definition: app_sms.c:220
unsigned char rp
Definition: app_sms.c:233
char cli[20]
Definition: app_sms.c:237
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned short ud[SMSLEN]
Definition: app_sms.c:235
short mr
Definition: app_sms.c:228
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...
Definition: app_sms.c:709
int udl
Definition: app_sms.c:229
static struct timeval unpackdate(unsigned char *i)
unpack a date and return
Definition: app_sms.c:576
char da[20]
Definition: app_sms.c:224
unsigned char dcs
Definition: app_sms.c:227
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char oa[20]
Definition: app_sms.c:223
unsigned char pid
Definition: app_sms.c:226
unsigned char udh[SMSLEN]
Definition: app_sms.c:236
static int sms_handleincoming_proto2 ( sms_t h)
static

sms_handleincoming_proto2: handle the incoming message

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

1255 {
1256  int f, i, sz = 0;
1257  int msg, msgsz;
1258  struct ast_tm tm;
1259  struct timeval now = { 0, 0 };
1260  char debug_buf[MAX_DEBUG_LEN * 3 + 1];
1261 
1262  sz = h->imsg[1] + 2;
1263  /* ast_verb(3, "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg, sz, debug_buf)); */
1264 
1265  /* Parse message body (called payload) */
1266  now = h->scts = ast_tvnow();
1267  for (f = 4; f < sz; ) {
1268  msg = h->imsg[f++];
1269  msgsz = h->imsg[f++];
1270  msgsz += (h->imsg[f++] * 256);
1271  switch (msg) {
1272  case 0x13: /* Body */
1273  ast_verb(3, "SMS-P2 Body#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
1274  if (msgsz >= sizeof(h->ud)) {
1275  msgsz = sizeof(h->ud) - 1;
1276  }
1277  for (i = 0; i < msgsz; i++) {
1278  h->ud[i] = h->imsg[f + i];
1279  }
1280  h->udl = msgsz;
1281  break;
1282  case 0x14: /* Date SCTS */
1283  now = h->scts = ast_tvnow();
1284  ast_localtime(&now, &tm, NULL);
1285  tm.tm_mon = ( (h->imsg[f] * 10) + h->imsg[f + 1] ) - 1;
1286  tm.tm_mday = ( (h->imsg[f + 2] * 10) + h->imsg[f + 3] );
1287  tm.tm_hour = ( (h->imsg[f + 4] * 10) + h->imsg[f + 5] );
1288  tm.tm_min = ( (h->imsg[f + 6] * 10) + h->imsg[f + 7] );
1289  tm.tm_sec = 0;
1290  h->scts = ast_mktime(&tm, NULL);
1291  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);
1292  break;
1293  case 0x15: /* Calling line (from SMSC) */
1294  if (msgsz >= 20) {
1295  msgsz = 20 - 1;
1296  }
1297  ast_verb(3, "SMS-P2 Origin#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
1298  ast_copy_string(h->oa, (char *)(&h->imsg[f]), msgsz + 1);
1299  break;
1300  case 0x18: /* Destination(from TE/phone) */
1301  if (msgsz >= 20) {
1302  msgsz = 20 - 1;
1303  }
1304  ast_verb(3, "SMS-P2 Destination#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
1305  ast_copy_string(h->da, (char *)(&h->imsg[f]), msgsz + 1);
1306  break;
1307  case 0x1C: /* Notify */
1308  ast_verb(3, "SMS-P2 Notify#%02X=%s\n", (unsigned)msg, sms_hexdump(&h->imsg[f], 3, debug_buf));
1309  break;
1310  default:
1311  ast_verb(3, "SMS-P2 Par#%02X [%d]: %s\n", (unsigned)msg, msgsz, sms_hexdump(&h->imsg[f], msgsz, debug_buf));
1312  break;
1313  }
1314  f+=msgsz; /* Skip to next */
1315  }
1316  h->rx = 1; /* received message */
1317  sms_writefile(h); /* write the file */
1318  return 0; /* no error */
1319 }
unsigned char rx
Definition: app_sms.c:221
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
unsigned char imsg[250]
Definition: app_sms.c:247
#define ast_verb(level,...)
Definition: logger.h:243
struct timeval scts
Definition: app_sms.c:225
static void sms_writefile(sms_t *h)
white a received text message to a file
Definition: app_sms.c:990
unsigned short ud[SMSLEN]
Definition: app_sms.c:235
static char * sms_hexdump(unsigned char buf[], int size, char *s)
Definition: app_sms.c:1241
static struct ast_format f[]
Definition: format_g726.c:181
#define MAX_DEBUG_LEN
Definition: app_sms.c:1240
int udl
Definition: app_sms.c:229
char da[20]
Definition: app_sms.c:224
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2185
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char oa[20]
Definition: app_sms.c:223
static char* sms_hexdump ( unsigned char  buf[],
int  size,
char *  s 
)
static

Definition at line 1241 of file app_sms.c.

References f, and MAX_DEBUG_LEN.

Referenced by sms_handleincoming_proto2().

1242 {
1243  char *p;
1244  int f;
1245 
1246  for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3) {
1247  sprintf(p, "%02X ", (unsigned)buf[f]);
1248  }
1249  return(s);
1250 }
static struct ast_format f[]
Definition: format_g726.c:181
#define MAX_DEBUG_LEN
Definition: app_sms.c:1240
static void sms_log ( sms_t h,
char  status 
)
static

Log the output, and remove file.

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

772 {
773  int o;
774 
775  if (*h->oa == '\0' && *h->da == '\0') {
776  return;
777  }
778  o = open(log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE);
779  if (o >= 0) {
780  char line[1000], mrs[3] = "", *p;
781  char buf[30];
782  unsigned char n;
783 
784  if (h->mr >= 0) {
785  snprintf(mrs, sizeof(mrs), "%02X", (unsigned)h->mr);
786  }
787  snprintf(line, sizeof(line), "%s %c%c%c%s %s %s %s ",
788  isodate(time(NULL), buf, sizeof(buf)),
789  status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue,
790  S_OR(h->oa, "-"), S_OR(h->da, "-") );
791  p = line + strlen(line);
792  for (n = 0; n < h->udl; n++) {
793  if (h->ud[n] == '\\') {
794  *p++ = '\\';
795  *p++ = '\\';
796  } else if (h->ud[n] == '\n') {
797  *p++ = '\\';
798  *p++ = 'n';
799  } else if (h->ud[n] == '\r') {
800  *p++ = '\\';
801  *p++ = 'r';
802  } else if (h->ud[n] < 32 || h->ud[n] == 127) {
803  *p++ = 191;
804  } else {
805  *p++ = h->ud[n];
806  }
807  }
808  *p++ = '\n';
809  *p = 0;
810  if (write(o, line, strlen(line)) < 0) {
811  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
812  }
813  close(o);
814  }
815  *h->oa = *h->da = h->udl = 0;
816 }
#define LOG_WARNING
Definition: logger.h:144
unsigned char rx
Definition: app_sms.c:221
#define AST_FILE_MODE
Definition: asterisk.h:36
char queue[30]
Definition: app_sms.c:222
static char * isodate(time_t t, char *buf, int len)
static, return a date/time in ISO format
Definition: app_sms.c:300
unsigned char smsc
Definition: app_sms.c:220
static char log_file[255]
Definition: app_sms.c:120
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned short ud[SMSLEN]
Definition: app_sms.c:235
short mr
Definition: app_sms.c:228
int errno
int udl
Definition: app_sms.c:229
char da[20]
Definition: app_sms.c:224
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
char oa[20]
Definition: app_sms.c:223
jack_status_t status
Definition: app_jack.c:143
static void sms_messagerx ( sms_t h)
static

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

1496 {
1497  int cause;
1498 
1499  sms_debug (DIR_RX, h);
1500  if (h->protocol == 2) {
1501  sms_messagerx2(h);
1502  return;
1503  }
1504  /* parse incoming message for Protocol 1 */
1505  switch (h->imsg[0]) {
1506  case 0x91: /* SMS_DATA */
1507  cause = sms_handleincoming (h);
1508  if (!cause) {
1509  sms_log(h, 'Y');
1510  h->omsg[0] = 0x95; /* SMS_ACK */
1511  h->omsg[1] = 0x02;
1512  h->omsg[2] = 0x00; /* deliver report */
1513  h->omsg[3] = 0x00; /* no parameters */
1514  } else { /* NACK */
1515  sms_log(h, 'N');
1516  h->omsg[0] = 0x96; /* SMS_NACK */
1517  h->omsg[1] = 3;
1518  h->omsg[2] = 0; /* delivery report */
1519  h->omsg[3] = cause; /* cause */
1520  h->omsg[4] = 0; /* no parameters */
1521  }
1522  sms_messagetx(h);
1523  break;
1524 
1525  case 0x92: /* SMS_ERROR */
1526  h->err = 1;
1527  sms_messagetx(h); /* send whatever we sent again */
1528  break;
1529  case 0x93: /* SMS_EST */
1530  sms_nextoutgoing (h);
1531  break;
1532  case 0x94: /* SMS_REL */
1533  h->hangup = 1; /* hangup */
1534  break;
1535  case 0x95: /* SMS_ACK */
1536  sms_log(h, 'Y');
1537  sms_nextoutgoing (h);
1538  break;
1539  case 0x96: /* SMS_NACK */
1540  h->err = 1;
1541  sms_log(h, 'N');
1542  sms_nextoutgoing (h);
1543  break;
1544  default: /* Unknown */
1545  h->omsg[0] = 0x92; /* SMS_ERROR */
1546  h->omsg[1] = 1;
1547  h->omsg[2] = 3; /* unknown message type */
1548  sms_messagetx(h);
1549  break;
1550  }
1551 }
static void sms_messagetx(sms_t *h)
Definition: app_sms.c:1553
unsigned char hangup
Definition: app_sms.c:217
static void sms_debug(int dir, sms_t *h)
Definition: app_sms.c:1477
unsigned char imsg[250]
Definition: app_sms.c:247
unsigned char omsg[256]
Definition: app_sms.c:246
#define DIR_RX
Definition: app_sms.c:1475
static void sms_log(sms_t *h, char status)
Log the output, and remove file.
Definition: app_sms.c:771
static void sms_messagerx2(sms_t *h)
Definition: app_sms.c:1335
unsigned char err
Definition: app_sms.c:218
int protocol
Definition: app_sms.c:271
static void sms_nextoutgoing(sms_t *h)
find and fill in next message, or send a REL if none waiting
Definition: app_sms.c:1434
static unsigned char sms_handleincoming(sms_t *h)
handle the incoming message
Definition: app_sms.c:1104
static void sms_messagerx2 ( sms_t h)
static

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

1336 {
1337  int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */
1338  int cause;
1339 
1340 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
1341  switch (p) {
1342  case DLL2_SMS_EST: /* Protocol 2: Connection ready (fake): send message */
1343  sms_nextoutgoing (h);
1344  /* 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 "); */
1345  break;
1346 
1347  case DLL2_SMS_INFO_MO: /* transport SMS_SUBMIT */
1348  case DLL2_SMS_INFO_MT: /* transport SMS_DELIVERY */
1349  cause = sms_handleincoming_proto2(h);
1350  if (!cause) { /* ACK */
1351  sms_log(h, 'Y');
1352  }
1353  h->omsg[0] = DLL2_ACK(h);
1354  h->omsg[1] = 0x06; /* msg len */
1355  h->omsg[2] = 0x04; /* payload len */
1356  h->omsg[3] = 0x00; /* payload len */
1357  h->omsg[4] = 0x1f; /* Response type */
1358  h->omsg[5] = 0x01; /* parameter len */
1359  h->omsg[6] = 0x00; /* parameter len */
1360  h->omsg[7] = cause; /* CONFIRM or error */
1361  sms_messagetx(h);
1362  break;
1363 
1364  case DLL2_SMS_NACK: /* Protocol 2: SMS_NAK */
1365  h->omsg[0] = DLL2_SMS_REL; /* SMS_REL */
1366  h->omsg[1] = 0x00; /* msg len */
1367  sms_messagetx(h);
1368  break;
1369 
1370  case DLL2_SMS_ACK0:
1371  case DLL2_SMS_ACK1:
1372  /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */
1373  if ( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
1374  /* a response to our Release, just hangup */
1375  h->hangup = 1; /* hangup */
1376  } else {
1377  /* XXX depending on what we are.. */
1378  ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY\n");
1379  sms_nextoutgoing (h);
1380  }
1381  break;
1382 
1383  case DLL2_SMS_REL: /* Protocol 2: SMS_REL (hangup req) */
1384  h->omsg[0] = DLL2_ACK(h);
1385  h->omsg[1] = 0;
1386  sms_messagetx(h);
1387  break;
1388  }
1389 }
static void sms_messagetx(sms_t *h)
Definition: app_sms.c:1553
unsigned char hangup
Definition: app_sms.c:217
static int sms_handleincoming_proto2(sms_t *h)
sms_handleincoming_proto2: handle the incoming message
Definition: app_sms.c:1254
unsigned char imsg[250]
Definition: app_sms.c:247
unsigned char omsg[256]
Definition: app_sms.c:246
#define DLL2_ACK(h)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static void sms_log(sms_t *h, char status)
Log the output, and remove file.
Definition: app_sms.c:771
static void sms_nextoutgoing(sms_t *h)
find and fill in next message, or send a REL if none waiting
Definition: app_sms.c:1434
static void sms_messagetx ( sms_t h)
static

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

1554 {
1555  unsigned char c = 0, p;
1556  int len = h->omsg[1] + 2; /* total message length excluding checksum */
1557 
1558  for (p = 0; p < len; p++) { /* compute checksum */
1559  c += h->omsg[p];
1560  }
1561  h->omsg[len] = 0 - c; /* actually, (256 - (c & 0fxx)) & 0xff) */
1562  sms_debug(DIR_TX, h);
1563  h->framenumber++; /* Proto 2 */
1564  h->obytep = 0;
1565  h->obitp = 0;
1566  if (h->protocol == 2) { /* Proto 2: */
1567  h->oseizure = 300; /* 300bits (or more ?) */
1568  h->obyte = 0; /* Seizure starts with space (0) */
1569  if (h->omsg[0] == 0x7F) {
1570  h->opause = 8 * h->opause_0; /* initial message delay */
1571  } else {
1572  h->opause = 400;
1573  }
1574  } else { /* Proto 1: */
1575  h->oseizure = 0; /* No seizure */
1576  h->obyte = 1; /* send mark ('1') at the beginning */
1577  /* Change the initial message delay. BT requires 300ms,
1578  * but for others this might be way too much and the phone
1579  * could time out. XXX make it configurable.
1580  */
1581  if (h->omsg[0] == 0x93) {
1582  h->opause = 8 * h->opause_0; /* initial message delay */
1583  } else {
1584  h->opause = 200;
1585  }
1586  }
1587  /* Note - setting osync triggers the generator */
1588  h->osync = OSYNC_BITS; /* 80 sync bits */
1589  h->obyten = len + 1; /* bytes to send (including checksum) */
1590 }
int opause_0
Definition: app_sms.c:270
unsigned char obyten
Definition: app_sms.c:245
unsigned char obitp
Definition: app_sms.c:242
static void sms_debug(int dir, sms_t *h)
Definition: app_sms.c:1477
unsigned char osync
Definition: app_sms.c:243
unsigned char omsg[256]
Definition: app_sms.c:246
#define OSYNC_BITS
Definition: app_sms.c:150
unsigned char obyte
Definition: app_sms.c:240
int framenumber
Definition: app_sms.c:273
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define DIR_TX
Definition: app_sms.c:1476
unsigned char obytep
Definition: app_sms.c:244
int oseizure
Definition: app_sms.c:272
unsigned int opause
Definition: app_sms.c:241
int protocol
Definition: app_sms.c:271
static void sms_nextoutgoing ( sms_t h)
static

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

Definition at line 1434 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_s::sent_rel, sms_compose1(), sms_compose2(), sms_messagetx(), sms_readfile(), and sms_s::smsc.

Referenced by sms_messagerx(), and sms_messagerx2().

1435 {
1436  char fn[100 + NAME_MAX] = "";
1437  DIR *d;
1438  char more = 0;
1439 
1440  *h->da = *h->oa = '\0'; /* clear destinations */
1441  h->rx = 0; /* outgoing message */
1442  snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? "mttx" : "motx");
1443  ast_mkdir(fn, 0777); /* ensure it exists */
1444  d = opendir(fn);
1445  if (d) {
1446  struct dirent *f = readdirqueue(d, h->queue);
1447  if (f) {
1448  snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", f->d_name);
1449  sms_readfile(h, fn);
1450  if (readdirqueue(d, h->queue)) {
1451  more = 1; /* more to send */
1452  }
1453  }
1454  closedir(d);
1455  }
1456  if (*h->da || *h->oa) { /* message to send */
1457  if (h->protocol == 2) {
1458  sms_compose2(h, more);
1459  } else {
1460  sms_compose1(h, more);
1461  }
1462  } else { /* no message */
1463  if (h->protocol == 2) {
1464  h->omsg[0] = 0x17; /* SMS_REL */
1465  h->omsg[1] = 0;
1466  } else {
1467  h->omsg[0] = 0x94; /* SMS_REL */
1468  h->omsg[1] = 0;
1469  h->sent_rel = 1;
1470  }
1471  }
1472  sms_messagetx(h);
1473 }
static void sms_messagetx(sms_t *h)
Definition: app_sms.c:1553
unsigned char rx
Definition: app_sms.c:221
static void sms_compose1(sms_t *h, int more)
compose a message for protocol 1
Definition: app_sms.c:1392
unsigned char omsg[256]
Definition: app_sms.c:246
static void sms_readfile(sms_t *h, char *fn)
parse and delete a file
Definition: app_sms.c:819
static struct dirent * readdirqueue(DIR *d, char *queue)
read dir skipping dot files...
Definition: app_sms.c:1094
static void sms_compose2(sms_t *h, int more)
Definition: app_sms.c:1205
char queue[30]
Definition: app_sms.c:222
unsigned char smsc
Definition: app_sms.c:220
static struct ast_format f[]
Definition: format_g726.c:181
const char * ast_config_AST_SPOOL_DIR
Definition: asterisk.c:259
char da[20]
Definition: app_sms.c:224
char oa[20]
Definition: app_sms.c:223
unsigned char sent_rel
Definition: app_sms.c:219
int protocol
Definition: app_sms.c:271
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2151
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 1702 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_s::sent_rel, sms_messagerx(), and sms_messagetx().

1703 {
1704  int bit;
1705 
1706  /*
1707  * Ignore incoming audio while a packet is being transmitted,
1708  * the protocol is half-duplex.
1709  * Unfortunately this means that if the outbound and incoming
1710  * transmission overlap (which is an error condition anyways),
1711  * we may miss some data and this makes debugging harder.
1712  */
1713  if (h->obyten || h->osync) {
1714  return;
1715  }
1716  for ( ; samples-- ; data++) {
1717  unsigned long long m0, m1;
1718  if (abs(*data) > h->imag) {
1719  h->imag = abs(*data);
1720  } else {
1721  h->imag = h->imag * 7 / 8;
1722  }
1723  if (h->imag <= 500) { /* below [arbitrary] threahold: lost carrier */
1724  if (h->idle++ == 80000) { /* nothing happening */
1725  ast_log(LOG_NOTICE, "No data, hanging up\n");
1726  h->hangup = 1;
1727  h->err = 1;
1728  }
1729  if (h->ierr) { /* error */
1730  ast_log(LOG_NOTICE, "Error %d, hanging up\n", h->ierr);
1731  /* Protocol 1 */
1732  h->err = 1;
1733  h->omsg[0] = 0x92; /* error */
1734  h->omsg[1] = 1;
1735  h->omsg[2] = h->ierr;
1736  sms_messagetx(h); /* send error */
1737  }
1738  h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1739  continue;
1740  }
1741  h->idle = 0;
1742 
1743  /* multiply signal by the two carriers. */
1744  h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
1745  h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
1746  h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
1747  h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
1748  /* compute the amplitudes */
1749  m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
1750  m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
1751 
1752  /* advance the sin/cos pointers */
1753  if ((h->ips0 += 21) >= 80) {
1754  h->ips0 -= 80;
1755  }
1756  if ((h->ipc0 += 21) >= 80) {
1757  h->ipc0 -= 80;
1758  }
1759  if ((h->ips1 += 13) >= 80) {
1760  h->ips1 -= 80;
1761  }
1762  if ((h->ipc1 += 13) >= 80) {
1763  h->ipc1 -= 80;
1764  }
1765 
1766  /* set new bit to 1 or 0 depending on which value is stronger */
1767  h->ibith <<= 1;
1768  if (m1 > m0) {
1769  h->ibith |= 1;
1770  }
1771  if (h->ibith & 8) {
1772  h->ibitt--;
1773  }
1774  if (h->ibith & 1) {
1775  h->ibitt++;
1776  }
1777  bit = ((h->ibitt > 1) ? 1 : 0);
1778  if (bit != h->ibitl) {
1779  h->ibitc = 1;
1780  } else {
1781  h->ibitc++;
1782  }
1783  h->ibitl = bit;
1784  if (!h->ibitn && h->ibitc == 4 && !bit) {
1785  h->ibitn = 1;
1786  h->iphasep = 0;
1787  }
1788  if (bit && h->ibitc == 200) { /* sync, restart message */
1789  /* Protocol 2: empty connection ready (I am master) */
1790  if (h->framenumber < 0 && h->ibytec >= 160 && !memcmp(h->imsg, "UUUUUUUUUUUUUUUUUUUU", 20)) {
1791  h->framenumber = 1;
1792  ast_verb(3, "SMS protocol 2 detected\n");
1793  h->protocol = 2;
1794  h->imsg[0] = 0xff; /* special message (fake) */
1795  h->imsg[1] = h->imsg[2] = 0x00;
1796  h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1797  sms_messagerx(h);
1798  }
1799  h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1800  }
1801  if (h->ibitn) {
1802  h->iphasep += 12;
1803  if (h->iphasep >= 80) { /* next bit */
1804  h->iphasep -= 80;
1805  if (h->ibitn++ == 9) { /* end of byte */
1806  if (!bit) { /* bad stop bit */
1807  if (h->sent_rel) {
1808  h->hangup = 1;
1809  } else {
1810  ast_log(LOG_NOTICE, "Bad stop bit\n");
1811  h->ierr = 0xFF; /* unknown error */
1812  }
1813  } else {
1814  if (h->ibytep < sizeof(h->imsg)) {
1815  h->imsg[h->ibytep] = h->ibytev;
1816  h->ibytec += h->ibytev;
1817  h->ibytep++;
1818  } else if (h->ibytep == sizeof(h->imsg)) {
1819  ast_log(LOG_NOTICE, "msg too large\n");
1820  h->ierr = 2; /* bad message length */
1821  }
1822  if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
1823  if (!h->ibytec) {
1824  sms_messagerx(h);
1825  } else {
1826  ast_log(LOG_NOTICE, "bad checksum\n");
1827  h->ierr = 1; /* bad checksum */
1828  }
1829  }
1830  }
1831  h->ibitn = 0;
1832  }
1833  h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
1834  }
1835  }
1836  }
1837 }
static void sms_messagerx(sms_t *h)
Definition: app_sms.c:1495
static void sms_messagetx(sms_t *h)
Definition: app_sms.c:1553
unsigned char hangup
Definition: app_sms.c:217
unsigned char ipc1
Definition: app_sms.c:257
unsigned char obyten
Definition: app_sms.c:245
unsigned char ipc0
Definition: app_sms.c:256
unsigned char ibitl
Definition: app_sms.c:258
unsigned char ibytep
Definition: app_sms.c:263
unsigned char osync
Definition: app_sms.c:243
unsigned char imsg[250]
Definition: app_sms.c:247
#define ast_verb(level,...)
Definition: logger.h:243
unsigned int idle
Definition: app_sms.c:252
signed long long imc0
Definition: app_sms.c:248
unsigned char omsg[256]
Definition: app_sms.c:246
unsigned char ibytev
Definition: app_sms.c:262
unsigned char ibitt
Definition: app_sms.c:267
unsigned char ips0
Definition: app_sms.c:254
static const signed short wave[]
Definition: app_sms.c:130
signed long long imc1
Definition: app_sms.c:248
unsigned short imag
Definition: app_sms.c:253
int framenumber
Definition: app_sms.c:273
unsigned char ierr
Definition: app_sms.c:265
unsigned char ibitc
Definition: app_sms.c:259
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
unsigned char err
Definition: app_sms.c:218
unsigned char ibytec
Definition: app_sms.c:264
unsigned char ibith
Definition: app_sms.c:266
unsigned char ips1
Definition: app_sms.c:255
unsigned char sent_rel
Definition: app_sms.c:219
unsigned char iphasep
Definition: app_sms.c:260
signed long long ims0
Definition: app_sms.c:248
int protocol
Definition: app_sms.c:271
unsigned char ibitn
Definition: app_sms.c:261
signed long long ims1
Definition: app_sms.c:248
static void sms_readfile ( sms_t h,
char *  fn 
)
static

parse and delete a file

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

820 {
821  char line[1000];
822  FILE *s;
823  char dcsset = 0; /* if DSC set */
824  ast_log(LOG_NOTICE, "Sending %s\n", fn);
825  h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
826  h->mr = -1;
827  h->dcs = 0xF1; /* normal messages class 1 */
828  h->scts = ast_tvnow();
829  s = fopen(fn, "r");
830  if (s) {
831  if (unlink(fn)) { /* concurrent access, we lost */
832  fclose(s);
833  return;
834  }
835  while (fgets (line, sizeof(line), s)) { /* process line in file */
836  char *p;
837  void *pp = &p;
838  for (p = line; *p && *p != '\n' && *p != '\r'; p++);
839  *p = 0; /* strip eoln */
840  p = line;
841  if (!*p || *p == ';') {
842  continue; /* blank line or comment, ignore */
843  }
844  while (isalnum(*p)) {
845  *p = tolower (*p);
846  p++;
847  }
848  while (isspace (*p)) {
849  *p++ = 0;
850  }
851  if (*p == '=') {
852  *p++ = 0;
853  if (!strcmp(line, "ud")) { /* parse message (UTF-8) */
854  unsigned char o = 0;
855  memcpy(h->udtxt, p, SMSLEN); /* for protocol 2 */
856  while (*p && o < SMSLEN) {
857  h->ud[o++] = utf8decode(pp);
858  }
859  h->udl = o;
860  if (*p) {
861  ast_log(LOG_WARNING, "UD too long in %s\n", fn);
862  }
863  } else {
864  while (isspace (*p)) {
865  p++;
866  }
867  if (!strcmp(line, "oa") && strlen(p) < sizeof(h->oa)) {
868  numcpy (h->oa, p);
869  } else if (!strcmp(line, "da") && strlen(p) < sizeof(h->oa)) {
870  numcpy (h->da, p);
871  } else if (!strcmp(line, "pid")) {
872  h->pid = atoi(p);
873  } else if (!strcmp(line, "dcs")) {
874  h->dcs = atoi(p);
875  dcsset = 1;
876  } else if (!strcmp(line, "mr")) {
877  h->mr = atoi(p);
878  } else if (!strcmp(line, "srr")) {
879  h->srr = (atoi(p) ? 1 : 0);
880  } else if (!strcmp(line, "vp")) {
881  h->vp = atoi(p);
882  } else if (!strcmp(line, "rp")) {
883  h->rp = (atoi(p) ? 1 : 0);
884  } else if (!strcmp(line, "scts")) { /* get date/time */
885  int Y, m, d, H, M, S;
886  /* XXX Why aren't we using ast_strptime here? */
887  if (sscanf(p, "%4d-%2d-%2dT%2d:%2d:%2d", &Y, &m, &d, &H, &M, &S) == 6) {
888  struct ast_tm t = { 0, };
889  t.tm_year = Y - 1900;
890  t.tm_mon = m - 1;
891  t.tm_mday = d;
892  t.tm_hour = H;
893  t.tm_min = M;
894  t.tm_sec = S;
895  t.tm_isdst = -1;
896  h->scts = ast_mktime(&t, NULL);
897  if (h->scts.tv_sec == 0) {
898  ast_log(LOG_WARNING, "Bad date/timein %s: %s", fn, p);
899  }
900  }
901  } else {
902  ast_log(LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
903  }
904  }
905  } else if (*p == '#') { /* raw hex format */
906  *p++ = 0;
907  if (*p == '#') {
908  p++;
909  if (!strcmp(line, "ud")) { /* user data */
910  int o = 0;
911  while (*p && o < SMSLEN) {
912  if (isxdigit(*p) && isxdigit(p[1]) && isxdigit(p[2]) && isxdigit(p[3])) {
913  h->ud[o++] =
914  (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 12) +
915  (((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
916  (((isalpha(p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha(p[3]) ? 9 : 0) + (p[3] & 0xF));
917  p += 4;
918  } else
919  break;
920  }
921  h->udl = o;
922  if (*p)
923  ast_log(LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
924  } else
925  ast_log(LOG_WARNING, "Only ud can use ## format, %s\n", fn);
926  } else if (!strcmp(line, "ud")) { /* user data */
927  int o = 0;
928  while (*p && o < SMSLEN) {
929  if (isxdigit(*p) && isxdigit(p[1])) {
930  h->ud[o++] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
931  p += 2;
932  } else {
933  break;
934  }
935  }
936  h->udl = o;
937  if (*p) {
938  ast_log(LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
939  }
940  } else if (!strcmp(line, "udh")) { /* user data header */
941  unsigned char o = 0;
942  h->udhi = 1;
943  while (*p && o < SMSLEN) {
944  if (isxdigit(*p) && isxdigit(p[1])) {
945  h->udh[o] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
946  o++;
947  p += 2;
948  } else {
949  break;
950  }
951  }
952  h->udhl = o;
953  if (*p) {
954  ast_log(LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
955  }
956  } else {
957  ast_log(LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
958  }
959  } else {
960  ast_log(LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
961  }
962  }
963  fclose(s);
964  if (!dcsset && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
965  if (packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
966  if (packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
967  ast_log(LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
968  } else {
969  h->dcs = 0x08; /* default to 16 bit */
970  ast_log(LOG_WARNING, "Sending in 16 bit format(%s)\n", fn);
971  }
972  } else {
973  h->dcs = 0xF5; /* default to 8 bit */
974  ast_log(LOG_WARNING, "Sending in 8 bit format(%s)\n", fn);
975  }
976  }
977  if (is7bit(h->dcs) && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
978  ast_log(LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
979  }
980  if (is8bit(h->dcs) && packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
981  ast_log(LOG_WARNING, "Invalid 8 bit data %s\n", fn);
982  }
983  if (is16bit(h->dcs) && packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
984  ast_log(LOG_WARNING, "Invalid 16 bit data %s\n", fn);
985  }
986  }
987 }
#define is7bit(dcs)
Definition: app_sms.c:278
unsigned int vp
Definition: app_sms.c:234
static long utf8decode(unsigned char **pp)
Reads next UCS character from NUL terminated UTF-8 string and advance pointer.
Definition: app_sms.c:312
#define SMSLEN
Definition: app_sms.c:213
int udhl
Definition: app_sms.c:230
#define LOG_WARNING
Definition: logger.h:144
unsigned char rx
Definition: app_sms.c:221
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define S(e)
int tm_year
Definition: localtime.h:41
unsigned char udhi
Definition: app_sms.c:232
struct timeval scts
Definition: app_sms.c:225
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 ...
Definition: app_sms.c:482
int tm_mon
Definition: localtime.h:40
unsigned char srr
Definition: app_sms.c:231
int tm_mday
Definition: localtime.h:39
unsigned char rp
Definition: app_sms.c:233
#define is16bit(dcs)
Definition: app_sms.c:280
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned short ud[SMSLEN]
Definition: app_sms.c:235
short mr
Definition: app_sms.c:228
#define LOG_NOTICE
Definition: logger.h:133
char udtxt[SMSLEN]
Definition: app_sms.c:274
int tm_hour
Definition: localtime.h:38
int tm_sec
Definition: localtime.h:36
int udl
Definition: app_sms.c:229
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 ...
Definition: app_sms.c:366
char da[20]
Definition: app_sms.c:224
unsigned char dcs
Definition: app_sms.c:227
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2185
int tm_isdst
Definition: localtime.h:44
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 ...
Definition: app_sms.c:443
char oa[20]
Definition: app_sms.c:223
static void numcpy(char *d, char *s)
copy number, skipping non digits apart from leading +
Definition: app_sms.c:285
#define is8bit(dcs)
Definition: app_sms.c:279
unsigned char pid
Definition: app_sms.c:226
int tm_min
Definition: localtime.h:37
unsigned char udh[SMSLEN]
Definition: app_sms.c:236
static void sms_release ( struct ast_channel chan,
void *  data 
)
static

Definition at line 1679 of file app_sms.c.

1680 {
1681  return; /* nothing to do here. */
1682 }
static void sms_writefile ( sms_t h)
static

white a received text message to a file

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

991 {
992  char fn[200] = "", fn2[200] = "";
993  char buf[30];
994  FILE *o;
995 
996  if (ast_tvzero(h->scts)) {
997  h->scts = ast_tvnow();
998  }
999  snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
1000  ast_mkdir(fn, 0777); /* ensure it exists */
1001  ast_copy_string(fn2, fn, sizeof(fn2));
1002  snprintf(fn2 + strlen(fn2), sizeof(fn2) - strlen(fn2), "/%s.%s-%u", h->queue, isodate(h->scts.tv_sec, buf, sizeof(buf)), seq++);
1003  snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/.%s", fn2 + strlen(fn) + 1);
1004  if ((o = fopen(fn, "w")) == NULL) {
1005  return;
1006  }
1007 
1008  if (*h->oa) {
1009  fprintf(o, "oa=%s\n", h->oa);
1010  }
1011  if (*h->da) {
1012  fprintf(o, "da=%s\n", h->da);
1013  }
1014  if (h->udhi) {
1015  unsigned int p;
1016  fprintf(o, "udh#");
1017  for (p = 0; p < h->udhl; p++) {
1018  fprintf(o, "%02X", (unsigned)h->udh[p]);
1019  }
1020  fprintf(o, "\n");
1021  }
1022  if (h->udl) {
1023  unsigned int p;
1024  for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
1025  if (p < h->udl) {
1026  fputc(';', o); /* cannot use ud=, but include as a comment for human readable */
1027  }
1028  fprintf(o, "ud=");
1029  for (p = 0; p < h->udl; p++) {
1030  unsigned short v = h->ud[p];
1031  if (v < 32) {
1032  fputc(191, o);
1033  } else if (v < 0x80) {
1034  fputc(v, o);
1035  } else if (v < 0x800) {
1036  fputc(0xC0 + (v >> 6), o);
1037  fputc(0x80 + (v & 0x3F), o);
1038  } else {
1039  fputc(0xE0 + (v >> 12), o);
1040  fputc(0x80 + ((v >> 6) & 0x3F), o);
1041  fputc(0x80 + (v & 0x3F), o);
1042  }
1043  }
1044  fprintf(o, "\n");
1045  for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
1046  if (p < h->udl) {
1047  for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
1048  if (p == h->udl) { /* can write in ucs-1 hex */
1049  fprintf(o, "ud#");
1050  for (p = 0; p < h->udl; p++) {
1051  fprintf(o, "%02X", (unsigned)h->ud[p]);
1052  }
1053  fprintf(o, "\n");
1054  } else { /* write in UCS-2 */
1055  fprintf(o, "ud##");
1056  for (p = 0; p < h->udl; p++) {
1057  fprintf(o, "%04X", (unsigned)h->ud[p]);
1058  }
1059  fprintf(o, "\n");
1060  }
1061  }
1062  }
1063  if (h->scts.tv_sec) {
1064  char datebuf[30];
1065  fprintf(o, "scts=%s\n", isodate(h->scts.tv_sec, datebuf, sizeof(datebuf)));
1066  }
1067  if (h->pid) {
1068  fprintf(o, "pid=%d\n", h->pid);
1069  }
1070  if (h->dcs != 0xF1) {
1071  fprintf(o, "dcs=%d\n", h->dcs);
1072  }
1073  if (h->vp) {
1074  fprintf(o, "vp=%u\n", h->vp);
1075  }
1076  if (h->srr) {
1077  fprintf(o, "srr=1\n");
1078  }
1079  if (h->mr >= 0) {
1080  fprintf(o, "mr=%d\n", h->mr);
1081  }
1082  if (h->rp) {
1083  fprintf(o, "rp=1\n");
1084  }
1085  fclose(o);
1086  if (rename(fn, fn2)) {
1087  unlink(fn);
1088  } else {
1089  ast_log(LOG_NOTICE, "Received to %s\n", fn2);
1090  }
1091 }
unsigned int vp
Definition: app_sms.c:234
int udhl
Definition: app_sms.c:230
unsigned char rx
Definition: app_sms.c:221
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
unsigned char udhi
Definition: app_sms.c:232
struct timeval scts
Definition: app_sms.c:225
char queue[30]
Definition: app_sms.c:222
static char * isodate(time_t t, char *buf, int len)
static, return a date/time in ISO format
Definition: app_sms.c:300
unsigned char srr
Definition: app_sms.c:231
unsigned char smsc
Definition: app_sms.c:220
unsigned char rp
Definition: app_sms.c:233
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned short ud[SMSLEN]
Definition: app_sms.c:235
short mr
Definition: app_sms.c:228
#define LOG_NOTICE
Definition: logger.h:133
const char * ast_config_AST_SPOOL_DIR
Definition: asterisk.c:259
int udl
Definition: app_sms.c:229
static volatile unsigned int seq
Definition: app_sms.c:118
char da[20]
Definition: app_sms.c:224
unsigned char dcs
Definition: app_sms.c:227
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char oa[20]
Definition: app_sms.c:223
unsigned char pid
Definition: app_sms.c:226
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2151
unsigned char udh[SMSLEN]
Definition: app_sms.c:236
static int unload_module ( void  )
static

Definition at line 2065 of file app_sms.c.

References ast_unregister_application().

2066 {
2068 }
static char * app
Definition: app_sms.c:122
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static unsigned char unpackaddress ( char *  o,
unsigned char *  i 
)
static

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

Definition at line 725 of file app_sms.c.

Referenced by sms_handleincoming().

726 {
727  unsigned char l = i[0], p;
728  if (i[1] == 0x91) {
729  *o++ = '+';
730  }
731  for (p = 0; p < l; p++) {
732  if (p & 1) {
733  *o++ = (i[2 + p / 2] >> 4) + '0';
734  } else {
735  *o++ = (i[2 + p / 2] & 0xF) + '0';
736  }
737  }
738  *o = 0;
739  return (l + 5) / 2;
740 }
static struct timeval unpackdate ( unsigned char *  i)
static

unpack a date and return

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

577 {
578  struct ast_tm t;
579 
580  t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
581  t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
582  t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
583  t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
584  t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
585  t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
586  t.tm_isdst = 0;
587  if (i[6] & 0x08) {
588  t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
589  } else {
590  t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
591  }
592 
593  return ast_mktime(&t, NULL);
594 }
int tm_year
Definition: localtime.h:41
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2185
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 709 of file app_sms.c.

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

Referenced by sms_handleincoming().

710 {
711  int l = *i++;
712  if (is7bit(dcs)) {
713  unpacksms7(i, l, udh, udhl, ud, udl, udhi);
714  l = (l * 7 + 7) / 8; /* adjust length to return */
715  } else if (is8bit(dcs)) {
716  unpacksms8(i, l, udh, udhl, ud, udl, udhi);
717  } else {
718  l += l % 2;
719  unpacksms16(i, l, udh, udhl, ud, udl, udhi);
720  }
721  return l + 1;
722 }
#define is7bit(dcs)
Definition: app_sms.c:278
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...
Definition: app_sms.c:655
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...
Definition: app_sms.c:681
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...
Definition: app_sms.c:599
#define is8bit(dcs)
Definition: app_sms.c:279
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 681 of file app_sms.c.

Referenced by unpacksms().

682 {
683  unsigned short *o = ud;
684  *udhl = 0;
685  if (udhi) {
686  int n = *i;
687  *udhl = n;
688  if (n) {
689  i++;
690  l--;
691  while (l && n) {
692  l--;
693  n--;
694  *udh++ = *i++;
695  }
696  }
697  }
698  while (l--) {
699  int v = *i++;
700  if (l && l--) {
701  v = (v << 8) + *i++;
702  }
703  *o++ = v;
704  }
705  *udl = (o - ud);
706 }
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 599 of file app_sms.c.

Referenced by unpacksms().

600 {
601  unsigned char b = 0, p = 0;
602  unsigned short *o = ud;
603  *udhl = 0;
604  if (udhi && l) { /* header */
605  int h = i[p];
606  *udhl = h;
607  if (h) {
608  b = 1;
609  p++;
610  l--;
611  while (h-- && l) {
612  *udh++ = i[p++];
613  b += 8;
614  while (b >= 7) {
615  b -= 7;
616  l--;
617  if (!l) {
618  break;
619  }
620  }
621  }
622  /* adjust for fill, septets */
623  if (b) {
624  b = 7 - b;
625  l--;
626  }
627  }
628  }
629  while (l--) {
630  unsigned char v;
631  if (b < 2) {
632  v = ((i[p] >> b) & 0x7F); /* everything in one byte */
633  } else {
634  v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
635  }
636  b += 7;
637  if (b >= 8) {
638  b -= 8;
639  p++;
640  }
641  /* 0x00A0 is the encoding of ESC (27) in defaultalphabet */
642  if (o > ud && o[-1] == 0x00A0 && escapes[v]) {
643  o[-1] = escapes[v];
644  } else {
645  *o++ = defaultalphabet[v];
646  }
647  }
648  *udl = (o - ud);
649 }
static const unsigned short defaultalphabet[]
Definition: app_sms.c:189
static const unsigned short escapes[]
Definition: app_sms.c:202
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 655 of file app_sms.c.

Referenced by unpacksms().

656 {
657  unsigned short *o = ud;
658  *udhl = 0;
659  if (udhi) {
660  int n = *i;
661  *udhl = n;
662  if (n) {
663  i++;
664  l--;
665  while (l && n) {
666  l--;
667  n--;
668  *udh++ = *i++;
669  }
670  }
671  }
672  while (l--) {
673  *o++ = *i++; /* not to UTF-8 as explicitly 8 bit coding in DCS */
674  }
675  *udl = (o - ud);
676 }
static long utf8decode ( unsigned char **  pp)
static

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

Definition at line 312 of file app_sms.c.

Referenced by sms_readfile().

313 {
314  unsigned char *p = *pp;
315  if (!*p) {
316  return 0; /* null termination of string */
317  }
318  (*pp)++;
319  if (*p < 0xC0) {
320  return *p; /* ascii or continuation character */
321  }
322  if (*p < 0xE0) {
323  if (*p < 0xC2 || (p[1] & 0xC0) != 0x80) {
324  return *p; /* not valid UTF-8 */
325  }
326  (*pp)++;
327  return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
328  }
329  if (*p < 0xF0) {
330  if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80) {
331  return *p; /* not valid UTF-8 */
332  }
333  (*pp) += 2;
334  return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
335  }
336  if (*p < 0xF8) {
337  if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80) {
338  return *p; /* not valid UTF-8 */
339  }
340  (*pp) += 3;
341  return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
342  }
343  if (*p < 0xFC) {
344  if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
345  || (p[4] & 0xC0) != 0x80) {
346  return *p; /* not valid UTF-8 */
347  }
348  (*pp) += 4;
349  return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
350  }
351  if (*p < 0xFE) {
352  if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
353  || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80) {
354  return *p; /* not valid UTF-8 */
355  }
356  (*pp) += 5;
357  return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
358  }
359  return *p; /* not sensible */
360 }

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 2082 of file app_sms.c.

char* app = "SMS"
static

Definition at line 122 of file app_sms.c.

Definition at line 2082 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 1867 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,
}
static int sms_generate(struct ast_channel *chan, void *data, int len, int samples)
Definition: app_sms.c:1596
static void sms_release(struct ast_channel *chan, void *data)
Definition: app_sms.c:1679
static void * sms_alloc(struct ast_channel *chan, void *sms_t_ptr)
Definition: app_sms.c:1674

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