Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
app_sms.c File Reference

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

#include "asterisk.h"
#include <dirent.h>
#include <ctype.h>
#include <sys/stat.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/format_cache.h"
Include dependency graph for app_sms.c:

Go to the source code of this file.

Data Structures

struct  sms_s
 

Macros

#define __OUT_FMT   ast_format_slin
 
#define DIR_RX   1
 
#define DIR_TX   2
 
#define DLL2_ACK(h)   ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
 
#define is16bit(dcs)   ( ((dcs) & 0xC0) ? 0 : (((dcs) & 0xc) == 8) )
 
#define is7bit(dcs)   ( ((dcs) & 0xC0) ? (!((dcs) & 4) ) : (((dcs) & 0xc) == 0) )
 
#define is8bit(dcs)   ( ((dcs) & 0xC0) ? ( ((dcs) & 4) ) : (((dcs) & 0xc) == 4) )
 
#define MAX_DEBUG_LEN   300
 
#define MAXSAMPLES   (800)
 
#define OSYNC_BITS   80 /* 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), OPTIONS_NO_LOG = (1 << 6)
}
 
enum  sms_opt_args { OPTION_ARG_PAUSE = 0, OPTION_ARG_ARRAY_SIZE }
 

Functions

static void adddata_proto2 (sms_t *h, unsigned char msg, char *data, int size)
 
 AST_MODULE_INFO_STANDARD_EXTENDED (ASTERISK_GPL_KEY, "SMS/PSTN handler")
 
static char * isodate (time_t t, char *buf, int len)
 static, return a date/time in ISO format 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 char * app = "SMS"
 
static const unsigned short defaultalphabet []
 
static const unsigned short escapes []
 
static char log_file [255]
 
static volatile unsigned char message_ref
 
static volatile unsigned int seq
 
static const struct ast_app_option sms_options [128] = { [ 's' ] = { .flag = OPTION_BE_SMSC }, [ 'a' ] = { .flag = OPTION_ANSWER }, [ 't' ] = { .flag = OPTION_TWO }, [ 'r' ] = { .flag = OPTION_SRR }, [ 'o' ] = { .flag = OPTION_DCS }, [ 'n' ] = { .flag = OPTIONS_NO_LOG }, [ 'p' ] = { .flag = OPTION_PAUSE , .arg_index = OPTION_ARG_PAUSE + 1 }, }
 
static struct ast_generator smsgen
 
static const signed short wave []
 
static const output_twave_out = wave
 

Detailed Description

SMS application - ETSI ES 201 912 protocol 1 implementation.

Development notes
Note
The ETSI standards are available free of charge from ETSI at http://pda.etsi.org/pda/queryform.asp Among the relevant documents here we have:

ES 201 912 SMS for PSTN/ISDN TS 123 040 Technical realization of SMS

Author
Adrian Kennard (for the original protocol 1 code)
Filippo Grassilli (Hyppo) - protocol 2 support Not fully tested, under development

Definition in file app_sms.c.

Macro Definition Documentation

◆ __OUT_FMT

#define __OUT_FMT   ast_format_slin

Definition at line 149 of file app_sms.c.

Referenced by sms_exec(), and sms_generate().

◆ DIR_RX

#define DIR_RX   1

Definition at line 1483 of file app_sms.c.

Referenced by sms_debug(), and sms_messagerx().

◆ DIR_TX

#define DIR_TX   2

Definition at line 1484 of file app_sms.c.

Referenced by sms_messagetx().

◆ DLL2_ACK

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

Referenced by sms_messagerx2().

◆ is16bit

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

Definition at line 283 of file app_sms.c.

Referenced by sms_exec(), and sms_readfile().

◆ is7bit

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

Definition at line 281 of file app_sms.c.

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

◆ is8bit

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

Definition at line 282 of file app_sms.c.

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

◆ MAX_DEBUG_LEN

#define MAX_DEBUG_LEN   300

Definition at line 1248 of file app_sms.c.

Referenced by sms_handleincoming_proto2(), and sms_hexdump().

◆ MAXSAMPLES

#define MAXSAMPLES   (800)

Referenced by sms_generate().

◆ OSYNC_BITS

#define OSYNC_BITS   80 /* initial sync bits */

Definition at line 152 of file app_sms.c.

Referenced by sms_messagetx().

◆ SMSLEN

#define SMSLEN   160

max SMS length

Definition at line 215 of file app_sms.c.

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

◆ SMSLEN_8

#define SMSLEN_8   140

max SMS length for 8-bit char

Definition at line 216 of file app_sms.c.

Referenced by packsms16(), and packsms8().

Typedef Documentation

◆ output_t

typedef signed short output_t

Definition at line 147 of file app_sms.c.

◆ sms_t

typedef struct sms_s sms_t

Enumeration Type Documentation

◆ message_types

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

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

◆ sms_flags

enum sms_flags
Enumerator
OPTION_BE_SMSC 
OPTION_ANSWER 
OPTION_TWO 
OPTION_PAUSE 
OPTION_SRR 
OPTION_DCS 
OPTIONS_NO_LOG 

Definition at line 1856 of file app_sms.c.

1856  {
1857  OPTION_BE_SMSC = (1 << 0), /* act as sms center */
1858  OPTION_ANSWER = (1 << 1), /* answer on incoming calls */
1859  OPTION_TWO = (1 << 2), /* Use Protocol Two */
1860  OPTION_PAUSE = (1 << 3), /* pause before sending data, in ms */
1861  OPTION_SRR = (1 << 4), /* set srr */
1862  OPTION_DCS = (1 << 5), /* set dcs */
1863  OPTIONS_NO_LOG = (1 << 6), /* Don't log SMS content */
1864 };

◆ sms_opt_args

Enumerator
OPTION_ARG_PAUSE 
OPTION_ARG_ARRAY_SIZE 

Definition at line 1866 of file app_sms.c.

Function Documentation

◆ adddata_proto2()

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

References sms_s::omsg.

Referenced by putdummydata_proto2(), and sms_compose2().

1189 {
1190  int x = h->omsg[1] + 2; /* Get current position */
1191  if (x == 2) {
1192  x += 2; /* First: skip Payload length (set later) */
1193  }
1194  h->omsg[x++] = msg; /* Message code */
1195  h->omsg[x++] = (unsigned char)size; /* Data size Low */
1196  h->omsg[x++] = 0; /* Data size Hi */
1197  for (; size > 0 ; size--) {
1198  h->omsg[x++] = *data++;
1199  }
1200  h->omsg[1] = x - 2; /* Frame size */
1201  h->omsg[2] = x - 4; /* Payload length (Lo) */
1202  h->omsg[3] = 0; /* Payload length (Hi) */
1203 }
unsigned char omsg[256]
Definition: app_sms.c:249

◆ AST_MODULE_INFO_STANDARD_EXTENDED()

AST_MODULE_INFO_STANDARD_EXTENDED ( ASTERISK_GPL_KEY  ,
"SMS/PSTN handler  
)

Referenced by load_module().

◆ isodate()

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

static, return a date/time in ISO format

Definition at line 303 of file app_sms.c.

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

Referenced by sms_log(), and sms_writefile().

304 {
305  struct ast_tm tm;
306  struct timeval local = { t, 0 };
307  ast_localtime(&local, &tm, NULL);
308  ast_strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
309  return buf;
310 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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:1739
#define NULL
Definition: resample.c:96
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:2524

◆ load_module()

static int load_module ( void  )
static

Definition at line 2083 of file app_sms.c.

References app, ast_config_AST_LOG_DIR, AST_LIN2A, AST_MODULE_INFO_STANDARD_EXTENDED(), ast_register_application_xml, ASTERISK_GPL_KEY, log_file, sms_exec(), and wave.

2084 {
2085 #ifdef OUTALAW
2086  int p;
2087  for (p = 0; p < 80; p++) {
2088  wavea[p] = AST_LIN2A(wave[p]);
2089  }
2090 #endif
2091  snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR);
2093 }
static char * app
Definition: app_sms.c:124
static int sms_exec(struct ast_channel *chan, const char *data)
Definition: app_sms.c:1881
static const signed short wave[]
Definition: app_sms.c:132
static char log_file[255]
Definition: app_sms.c:122
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
#define AST_LIN2A(a)
Definition: alaw.h:50

◆ numcpy()

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

copy number, skipping non digits apart from leading +

Definition at line 288 of file app_sms.c.

Referenced by sms_readfile().

289 {
290  if (*s == '+') {
291  *d++ = *s++;
292  }
293  while (*s) {
294  if (isdigit(*s)) {
295  *d++ = *s;
296  }
297  s++;
298  }
299  *d = 0;
300 }
static struct test_val d

◆ packaddress()

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

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

Definition at line 746 of file app_sms.c.

Referenced by sms_compose1().

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

◆ packdate()

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

pack a date and return

Definition at line 553 of file app_sms.c.

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

Referenced by sms_compose1().

554 {
555  struct ast_tm t;
556  struct timeval topack = { w, 0 };
557  int z;
558 
559  ast_localtime(&topack, &t, NULL);
560 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
561  z = -t.tm_gmtoff / 60 / 15;
562 #else
563  z = timezone / 60 / 15;
564 #endif
565  *o++ = ((t.tm_year % 10) << 4) + (t.tm_year % 100) / 10;
566  *o++ = (((t.tm_mon + 1) % 10) << 4) + (t.tm_mon + 1) / 10;
567  *o++ = ((t.tm_mday % 10) << 4) + t.tm_mday / 10;
568  *o++ = ((t.tm_hour % 10) << 4) + t.tm_hour / 10;
569  *o++ = ((t.tm_min % 10) << 4) + t.tm_min / 10;
570  *o++ = ((t.tm_sec % 10) << 4) + t.tm_sec / 10;
571  if (z < 0) {
572  *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
573  } else {
574  *o++ = ((z % 10) << 4) + z / 10;
575  }
576 }
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:1739
#define NULL
Definition: resample.c:96

◆ packsms()

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

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

Referenced by sms_compose1().

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

◆ packsms16()

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

References dummy(), NULL, SMSLEN_8, and sms_s::udhl.

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

486 {
487  unsigned char p = 0;
488  unsigned char dummy[SMSLEN_8];
489 
490  if (o == NULL) {
491  o = dummy;
492  }
493  /* header - no encoding */
494  if (udhl) {
495  o[p++] = udhl;
496  while (udhl--) {
497  o[p++] = *udh++;
498  if (p >= SMSLEN_8) {
499  return p;
500  }
501  }
502  }
503  while (udl--) {
504  long u;
505  u = *ud++;
506  o[p++] = (u >> 8);
507  if (p >= SMSLEN_8) {
508  return p - 1; /* could not fit last character */
509  }
510  o[p++] = u;
511  if (p >= SMSLEN_8) {
512  return p;
513  }
514  }
515  return p;
516 }
static void dummy(char *unused,...)
Definition: chan_unistim.c:220
#define NULL
Definition: resample.c:96
#define SMSLEN_8
Definition: app_sms.c:216

◆ packsms7()

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

References b, defaultalphabet, dummy(), escapes, NULL, SMSLEN, and sms_s::udhl.

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

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

◆ packsms8()

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

References dummy(), NULL, SMSLEN_8, and sms_s::udhl.

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

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

◆ putdummydata_proto2()

static void putdummydata_proto2 ( sms_t h)
static

Definition at line 1205 of file app_sms.c.

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

Referenced by sms_compose2().

1206 {
1207  adddata_proto2(h, 0x10, "\0", 1); /* Media Identifier > SMS */
1208  adddata_proto2(h, 0x11, "\0\0\0\0\0\0", 6); /* Firmware version */
1209  adddata_proto2(h, 0x12, "\2\0\4", 3); /* SMS provider ID */
1210  adddata_proto2(h, 0x13, h->udtxt, h->udl); /* Body */
1211 }
char udtxt[SMSLEN]
Definition: app_sms.c:277
static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
Definition: app_sms.c:1188
int udl
Definition: app_sms.c:232

◆ readdirqueue()

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

read dir skipping dot files...

Definition at line 1102 of file app_sms.c.

Referenced by sms_nextoutgoing().

1103 {
1104  struct dirent *f;
1105  do {
1106  f = readdir(d);
1107  } while (f && (*f->d_name == '.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] != '.'));
1108  return f;
1109 }
static struct test_val d

◆ sms_alloc()

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

1685 {
1686  return sms_t_ptr;
1687 }

◆ sms_compose1()

static void sms_compose1 ( sms_t h,
int  more 
)
static

compose a message for protocol 1

Definition at line 1400 of file app_sms.c.

References sms_s::da, sms_s::dcs, message_ref, sms_s::mr, sms_s::oa, sms_s::omsg, packaddress(), packdate(), packsms(), sms_s::pid, sms_s::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().

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

◆ sms_compose2()

static void sms_compose2 ( sms_t h,
int  more 
)
static

Definition at line 1213 of file app_sms.c.

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

Referenced by sms_nextoutgoing().

1214 {
1215  struct ast_tm tm;
1216  struct timeval now = h->scts;
1217  char stm[45];
1218 
1219  h->omsg[0] = 0x00; /* set later... */
1220  h->omsg[1] = 0;
1222  if (h->smsc) { /* deliver */
1223  h->omsg[0] = 0x11; /* SMS_DELIVERY */
1224  /* Required: 10 11 12 13 14 15 17 (seems they must be ordered!) */
1225  ast_localtime(&now, &tm, NULL);
1226  sprintf(stm, "%02d%02d%02d%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min); /* Date mmddHHMM */
1227  adddata_proto2(h, 0x14, stm, 8); /* Date */
1228  if (*h->oa == 0) {
1229  strcpy(h->oa, "00000000");
1230  }
1231  adddata_proto2(h, 0x15, h->oa, strlen(h->oa)); /* Originator */
1232  adddata_proto2(h, 0x17, "\1", 1); /* Calling Terminal ID */
1233  } else { /* submit */
1234  h->omsg[0] = 0x10; /* SMS_SUBMIT */
1235  /* Required: 10 11 12 13 17 18 1B 1C (seems they must be ordered!) */
1236  adddata_proto2(h, 0x17, "\1", 1); /* Calling Terminal ID */
1237  if (*h->da == 0) {
1238  strcpy(h->da, "00000000");
1239  }
1240  adddata_proto2(h, 0x18, h->da, strlen(h->da)); /* Originator */
1241  adddata_proto2(h, 0x1B, "\1", 1); /* Called Terminal ID */
1242  adddata_proto2(h, 0x1C, "\0\0\0", 3); /* Notification */
1243  }
1244 }
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:1739
#define NULL
Definition: resample.c:96
struct timeval scts
Definition: app_sms.c:228
unsigned char omsg[256]
Definition: app_sms.c:249
unsigned char smsc
Definition: app_sms.c:222
static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
Definition: app_sms.c:1188
char da[20]
Definition: app_sms.c:227
char oa[20]
Definition: app_sms.c:226
static void putdummydata_proto2(sms_t *h)
Definition: app_sms.c:1205

◆ sms_debug()

static void sms_debug ( int  dir,
sms_t h 
)
static

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

1486 {
1487  char txt[259 * 3 + 1];
1488  char *p = txt; /* always long enough */
1489  unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
1490  int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
1491  int q = 0;
1492  while (q < n && q < 30) {
1493  sprintf(p, " %02hhX", msg[q++]);
1494  p += 3;
1495  }
1496  if (q < n) {
1497  sprintf(p, "...");
1498  }
1499  ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
1500 }
unsigned char ibytep
Definition: app_sms.c:266
unsigned char imsg[250]
Definition: app_sms.c:250
#define ast_verb(level,...)
Definition: logger.h:463
unsigned char omsg[256]
Definition: app_sms.c:249
#define DIR_RX
Definition: app_sms.c:1483

◆ sms_exec()

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

Definition at line 1881 of file app_sms.c.

References __OUT_FMT, ast_activate_generator(), ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_channel_caller(), ast_channel_name(), ast_copy_string(), ast_deactivate_generator(), AST_DECLARE_APP_ARGS, ast_format_slin, AST_FRAME_VOICE, ast_frfree, ast_log, ast_read(), ast_set_read_format(), ast_set_write_format(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_strlen_zero, ast_test_flag, ast_tvnow(), ast_verb, ast_waitfor(), sms_s::cli, d, sms_s::da, ast_frame::data, sms_s::dcs, DLL1_SMS_COMPLETE, DLL1_SMS_EST, DLL2_SMS_EST, done, sms_s::err, ast_flags::flags, sms_s::framenumber, ast_frame::frametype, sms_s::hangup, sms_s::ipc0, sms_s::ipc1, is16bit, is7bit, is8bit, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sms_s::mr, sms_s::nolog, sms_s::oa, sms_s::omsg, sms_s::opause_0, OPTION_ANSWER, OPTION_ARG_ARRAY_SIZE, OPTION_ARG_PAUSE, OPTION_BE_SMSC, OPTION_DCS, OPTION_SRR, OPTION_TWO, options, OPTIONS_NO_LOG, packsms16(), packsms7(), packsms8(), parse(), sms_s::pid, sms_s::protocol, ast_frame::ptr, sms_s::queue, sms_s::rx, S_COR, S_OR, ast_frame::samples, sms_s::scts, sms_log(), sms_messagetx(), sms_options, sms_process(), sms_writefile(), sms_s::smsc, SMSLEN, sms_s::srr, sms_s::ud, sms_s::udh, sms_s::udhl, sms_s::udl, utf8decode(), and while().

Referenced by load_module().

1882 {
1883  int res = -1;
1884  sms_t h = { 0 };
1885  /* argument parsing support */
1886  struct ast_flags flags = { 0 };
1887  char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, };
1888  char *p;
1889  AST_DECLARE_APP_ARGS(sms_args,
1890  AST_APP_ARG(queue);
1892  AST_APP_ARG(addr);
1893  AST_APP_ARG(body);
1894  );
1895 
1896  if (!data) {
1897  ast_log(LOG_ERROR, "Requires queue name at least\n");
1898  return -1;
1899  }
1900 
1901  parse = ast_strdupa(data); /* create a local copy */
1902  AST_STANDARD_APP_ARGS(sms_args, parse);
1903  if (sms_args.argc > 1) {
1904  ast_app_parse_options(sms_options, &flags, sms_opts, sms_args.options);
1905  }
1906 
1907  ast_verb(1, "sms argc %u queue <%s> opts <%s> addr <%s> body <%s>\n",
1908  sms_args.argc, S_OR(sms_args.queue, ""),
1909  S_OR(sms_args.options, ""),
1910  S_OR(sms_args.addr, ""),
1911  S_OR(sms_args.body, "") );
1912 
1913  h.ipc0 = h.ipc1 = 20; /* phase for cosine */
1914  h.dcs = 0xF1; /* default */
1915 
1916  ast_copy_string(h.cli,
1917  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
1918  sizeof(h.cli));
1919 
1920  if (ast_strlen_zero(sms_args.queue)) {
1921  ast_log(LOG_ERROR, "Requires queue name\n");
1922  goto done;
1923  }
1924  if (strlen(sms_args.queue) >= sizeof(h.queue)) {
1925  ast_log(LOG_ERROR, "Queue name too long\n");
1926  goto done;
1927  }
1928  ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue));
1929 
1930  for (p = h.queue; *p; p++) {
1931  if (!isalnum(*p)) {
1932  *p = '-'; /* make very safe for filenames */
1933  }
1934  }
1935 
1936  h.smsc = ast_test_flag(&flags, OPTION_BE_SMSC);
1937  h.protocol = ast_test_flag(&flags, OPTION_TWO) ? 2 : 1;
1938  h.nolog = ast_test_flag(&flags, OPTIONS_NO_LOG) ? 1 : 0;
1939  if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE])) {
1940  h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
1941  }
1942  if (h.opause_0 < 25 || h.opause_0 > 2000) {
1943  h.opause_0 = 300; /* default 300ms */
1944  }
1945  ast_verb(1, "initial delay %dms\n", h.opause_0);
1946 
1947 
1948  /* the following apply if there is an arg3/4 and apply to the created message file */
1949  if (ast_test_flag(&flags, OPTION_SRR)) {
1950  h.srr = 1;
1951  }
1952  if (ast_test_flag(&flags, OPTION_DCS)) {
1953  h.dcs = 1;
1954  }
1955 #if 0
1956  case '1':
1957  case '2':
1958  case '3':
1959  case '4':
1960  case '5':
1961  case '6':
1962  case '7': /* set the pid for saved local message */
1963  h.pid = 0x40 + (*d & 0xF);
1964  break;
1965  }
1966 #endif
1967  if (sms_args.argc > 2) {
1968  unsigned char *up;
1969 
1970  /* submitting a message, not taking call. */
1971  /* deprecated, use smsq instead */
1972  h.scts = ast_tvnow();
1973  if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) {
1974  ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr);
1975  goto done;
1976  }
1977  if (h.smsc) {
1978  ast_copy_string(h.oa, sms_args.addr, sizeof(h.oa));
1979  } else {
1980  ast_copy_string(h.da, sms_args.addr, sizeof(h.da));
1981  ast_copy_string(h.oa, h.cli, sizeof(h.oa));
1982  }
1983  h.udl = 0;
1984  if (ast_strlen_zero(sms_args.body)) {
1985  ast_log(LOG_ERROR, "Missing body for %s\n", sms_args.addr);
1986  goto done;
1987  }
1988  up = (unsigned char *)sms_args.body;
1989  while (*up && h.udl < SMSLEN) {
1990  h.ud[h.udl++] = utf8decode(&up);
1991  }
1992  if (is7bit(h.dcs) && packsms7(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1993  ast_log(LOG_WARNING, "Invalid 7 bit GSM data\n");
1994  goto done;
1995  }
1996  if (is8bit(h.dcs) && packsms8(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1997  ast_log(LOG_WARNING, "Invalid 8 bit data\n");
1998  goto done;
1999  }
2000  if (is16bit(h.dcs) && packsms16(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
2001  ast_log(LOG_WARNING, "Invalid 16 bit data\n");
2002  goto done;
2003  }
2004  h.rx = 0; /* sent message */
2005  h.mr = -1;
2006  sms_writefile(&h);
2007  res = h.err;
2008  goto done;
2009  }
2010 
2011  if (ast_channel_state(chan) != AST_STATE_UP) { /* make sure channel is answered before any TX */
2012  ast_answer(chan);
2013  }
2014 
2015  if (ast_test_flag(&flags, OPTION_ANSWER)) {
2016  h.framenumber = 1; /* Proto 2 */
2017  /* set up SMS_EST initial message */
2018  if (h.protocol == 2) {
2019  h.omsg[0] = DLL2_SMS_EST;
2020  h.omsg[1] = 0;
2021  } else {
2023  h.omsg[1] = 0;
2024  }
2025  sms_messagetx(&h);
2026  }
2027 
2028  res = ast_set_write_format(chan, __OUT_FMT);
2029  if (res >= 0) {
2030  res = ast_set_read_format(chan, ast_format_slin);
2031  }
2032  if (res < 0) {
2033  ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
2034  goto done;
2035  }
2036 
2037  if ( (res = ast_activate_generator(chan, &smsgen, &h)) < 0) {
2038  ast_log(LOG_ERROR, "Failed to activate generator on '%s'\n", ast_channel_name(chan));
2039  goto done;
2040  }
2041 
2042  /* Do our thing here */
2043  for (;;) {
2044  struct ast_frame *f;
2045  int i = ast_waitfor(chan, -1);
2046  if (i < 0) {
2047  ast_log(LOG_NOTICE, "waitfor failed\n");
2048  break;
2049  }
2050  if (h.hangup) {
2051  ast_log(LOG_NOTICE, "channel hangup\n");
2052  break;
2053  }
2054  f = ast_read(chan);
2055  if (!f) {
2056  ast_log(LOG_NOTICE, "ast_read failed\n");
2057  break;
2058  }
2059  if (f->frametype == AST_FRAME_VOICE) {
2060  sms_process(&h, f->samples, f->data.ptr);
2061  }
2062 
2063  ast_frfree(f);
2064  }
2065  res = h.err; /* XXX */
2066 
2067  /*
2068  * The SMS generator data is on the stack. We _MUST_ make sure the generator
2069  * is stopped before returning from this function.
2070  */
2072 
2073  sms_log(&h, '?'); /* log incomplete message */
2074 done:
2075  return (res);
2076 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define is7bit(dcs)
Definition: app_sms.c:281
static void sms_messagetx(sms_t *h)
Definition: app_sms.c:1561
unsigned char hangup
Definition: app_sms.c:219
unsigned char ipc1
Definition: app_sms.c:260
int opause_0
Definition: app_sms.c:273
#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:2960
static long utf8decode(unsigned char **pp)
Reads next UCS character from NUL terminated UTF-8 string and advance pointer.
Definition: app_sms.c:315
#define SMSLEN
Definition: app_sms.c:215
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
int udhl
Definition: app_sms.c:233
unsigned char ipc0
Definition: app_sms.c:259
#define LOG_WARNING
Definition: logger.h:274
unsigned char rx
Definition: app_sms.c:223
static struct test_val d
unsigned int flags
Definition: utils.h:200
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
ast_channel_state
ast_channel states
Definition: channelstate.h:35
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
Definition: app_sms.c:218
#define ast_verb(level,...)
Definition: logger.h:463
struct timeval scts
Definition: app_sms.c:228
unsigned char omsg[256]
Definition: app_sms.c:249
static void sms_process(sms_t *h, int samples, signed short *data)
Definition: app_sms.c:1712
#define ast_strlen_zero(foo)
Definition: strings.h:52
int done
Definition: test_amihooks.c:48
Number structure.
Definition: app_followme.c:154
#define ast_log
Definition: astobj2.c:42
char queue[30]
Definition: app_sms.c:225
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
while(1)
Definition: ast_expr2f.c:894
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:485
#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:85
static const struct ast_app_option sms_options[128]
Definition: app_sms.c:1879
unsigned char srr
Definition: app_sms.c:234
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5890
static void sms_writefile(sms_t *h)
white a received text message to a file
Definition: app_sms.c:998
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: main/app.c:2906
unsigned char smsc
Definition: app_sms.c:222
unsigned char nolog
Definition: app_sms.c:224
#define LOG_ERROR
Definition: logger.h:285
int framenumber
Definition: app_sms.c:276
#define is16bit(dcs)
Definition: app_sms.c:283
char cli[20]
Definition: app_sms.c:240
static struct ast_generator smsgen
Definition: app_sms.c:1694
unsigned short ud[SMSLEN]
Definition: app_sms.c:238
#define __OUT_FMT
Definition: app_sms.c:149
short mr
Definition: app_sms.c:231
#define LOG_NOTICE
Definition: logger.h:263
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
static void sms_log(sms_t *h, char status)
Log the output, and remove file.
Definition: app_sms.c:774
Structure used to handle boolean flags.
Definition: utils.h:199
int udl
Definition: app_sms.c:232
void ast_deactivate_generator(struct ast_channel *chan)
Definition: channel.c:2902
unsigned char err
Definition: app_sms.c:220
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:369
char da[20]
Definition: app_sms.c:227
unsigned char dcs
Definition: app_sms.c:230
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
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:446
Data structure associated with a single frame of data.
char oa[20]
Definition: app_sms.c:226
union ast_frame::@263 data
enum ast_frame_type frametype
static struct test_options options
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define is8bit(dcs)
Definition: app_sms.c:282
unsigned char pid
Definition: app_sms.c:229
int protocol
Definition: app_sms.c:274
#define AST_APP_ARG(name)
Define an application argument.
unsigned char udh[SMSLEN]
Definition: app_sms.c:239

◆ sms_generate()

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

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

1605 {
1606  struct ast_frame f = { 0 };
1607 #define MAXSAMPLES (800)
1608  output_t *buf;
1609  sms_t *h = data;
1610  int i, res;
1611 
1612  if (samples > MAXSAMPLES) {
1613  ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
1614  MAXSAMPLES, samples);
1615  samples = MAXSAMPLES;
1616  }
1617  len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET;
1618  buf = ast_alloca(len);
1619 
1622  f.datalen = samples * sizeof(*buf);
1624  f.mallocd = 0;
1625  f.data.ptr = buf;
1626  f.samples = samples;
1627  f.src = "app_sms";
1628  /* create a buffer containing the digital sms pattern */
1629  for (i = 0; i < samples; i++) {
1630  buf[i] = wave_out[0]; /* default is silence */
1631 
1632  if (h->opause) {
1633  h->opause--;
1634  } else if (h->obyten || h->osync) { /* sending data */
1635  buf[i] = wave_out[h->ophase];
1636  h->ophase += (h->obyte & 1) ? 13 : 21; /* compute next phase */
1637  if (h->ophase >= 80)
1638  h->ophase -= 80;
1639  if ((h->ophasep += 12) >= 80) { /* time to send the next bit */
1640  h->ophasep -= 80;
1641  if (h->oseizure > 0) { /* sending channel seizure (proto 2) */
1642  h->oseizure--;
1643  h->obyte ^= 1; /* toggle low bit */
1644  } else if (h->osync) {
1645  h->obyte = 1; /* send mark as sync bit */
1646  h->osync--; /* sending sync bits */
1647  if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
1648  h->obytep = h->obyten = 0; /* we are done */
1649  }
1650  } else {
1651  h->obitp++;
1652  if (h->obitp == 1) {
1653  h->obyte = 0; /* start bit; */
1654  } else if (h->obitp == 2) {
1655  h->obyte = h->omsg[h->obytep];
1656  } else if (h->obitp == 10) {
1657  h->obyte = 1; /* stop bit */
1658  h->obitp = 0;
1659  h->obytep++;
1660  if (h->obytep == h->obyten) {
1661  h->obytep = h->obyten = 0; /* sent */
1662  h->osync = 10; /* trailing marks */
1663  }
1664  } else {
1665  h->obyte >>= 1;
1666  }
1667  }
1668  }
1669  }
1670  }
1671  res = ast_write(chan, &f);
1672  ast_frfree(&f);
1673  if (res < 0) {
1674  ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
1675  return -1;
1676  }
1677  return 0;
1678 #undef MAXSAMPLES
1679 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
unsigned char obyten
Definition: app_sms.c:248
unsigned char ophase
Definition: app_sms.c:241
#define LOG_WARNING
Definition: logger.h:274
unsigned char obitp
Definition: app_sms.c:245
unsigned char osync
Definition: app_sms.c:246
Definition: app_sms.c:218
struct ast_frame_subclass subclass
unsigned char omsg[256]
Definition: app_sms.c:249
#define ast_log
Definition: astobj2.c:42
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
const char * src
unsigned char obyte
Definition: app_sms.c:243
static const output_t * wave_out
Definition: app_sms.c:148
signed short output_t
Definition: app_sms.c:147
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
unsigned char ophasep
Definition: app_sms.c:242
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
unsigned char obytep
Definition: app_sms.c:247
#define __OUT_FMT
Definition: app_sms.c:149
int oseizure
Definition: app_sms.c:275
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:5189
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
unsigned int opause
Definition: app_sms.c:244
Data structure associated with a single frame of data.
union ast_frame::@263 data
enum ast_frame_type frametype
struct ast_format * format
#define MAXSAMPLES
int protocol
Definition: app_sms.c:274

◆ sms_handleincoming()

static unsigned char sms_handleincoming ( sms_t h)
static

handle the incoming message

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

1113 {
1114  unsigned char p = 3;
1115  if (h->smsc) { /* SMSC */
1116  if ((h->imsg[2] & 3) == 1) { /* SMS-SUBMIT */
1117  h->udhl = h->udl = 0;
1118  h->vp = 0;
1119  h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1120  h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1121  h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1122  ast_copy_string(h->oa, h->cli, sizeof(h->oa));
1123  h->scts = ast_tvnow();
1124  h->mr = h->imsg[p++];
1125  p += unpackaddress(h->da, h->imsg + p);
1126  h->pid = h->imsg[p++];
1127  h->dcs = h->imsg[p++];
1128  if ((h->imsg[2] & 0x18) == 0x10) { /* relative VP */
1129  if (h->imsg[p] < 144) {
1130  h->vp = (h->imsg[p] + 1) * 5;
1131  } else if (h->imsg[p] < 168) {
1132  h->vp = 720 + (h->imsg[p] - 143) * 30;
1133  } else if (h->imsg[p] < 197) {
1134  h->vp = (h->imsg[p] - 166) * 1440;
1135  } else {
1136  h->vp = (h->imsg[p] - 192) * 10080;
1137  }
1138  p++;
1139  } else if (h->imsg[2] & 0x18) {
1140  p += 7; /* ignore enhanced / absolute VP */
1141  }
1142  p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1143  h->rx = 1; /* received message */
1144  sms_writefile(h); /* write the file */
1145  if (p != h->imsg[1] + 2) {
1146  ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1147  return 0xFF; /* duh! */
1148  }
1149  } else {
1150  ast_log(LOG_WARNING, "Unknown message type %02hhX\n", h->imsg[2]);
1151  return 0xFF;
1152  }
1153  } else { /* client */
1154  if (!(h->imsg[2] & 3)) { /* SMS-DELIVER */
1155  *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
1156  h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1157  h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1158  h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1159  h->mr = -1;
1160  p += unpackaddress(h->oa, h->imsg + p);
1161  h->pid = h->imsg[p++];
1162  h->dcs = h->imsg[p++];
1163  h->scts = unpackdate(h->imsg + p);
1164  p += 7;
1165  p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1166  h->rx = 1; /* received message */
1167  sms_writefile(h); /* write the file */
1168  if (p != h->imsg[1] + 2) {
1169  ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1170  return 0xFF; /* duh! */
1171  }
1172  } else {
1173  ast_log(LOG_WARNING, "Unknown message type %02hhX\n", h->imsg[2]);
1174  return 0xFF;
1175  }
1176  }
1177  return 0; /* no error */
1178 }
unsigned int vp
Definition: app_sms.c:237
int udhl
Definition: app_sms.c:233
#define LOG_WARNING
Definition: logger.h:274
unsigned char rx
Definition: app_sms.c:223
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
static unsigned char unpackaddress(char *o, unsigned char *i)
unpack an address from i, return byte length, unpack to o
Definition: app_sms.c:728
unsigned char imsg[250]
Definition: app_sms.c:250
unsigned char udhi
Definition: app_sms.c:235
struct timeval scts
Definition: app_sms.c:228
#define ast_log
Definition: astobj2.c:42
unsigned char srr
Definition: app_sms.c:234
static void sms_writefile(sms_t *h)
white a received text message to a file
Definition: app_sms.c:998
unsigned char smsc
Definition: app_sms.c:222
unsigned char rp
Definition: app_sms.c:236
char cli[20]
Definition: app_sms.c:240
unsigned short ud[SMSLEN]
Definition: app_sms.c:238
short mr
Definition: app_sms.c:231
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:712
int udl
Definition: app_sms.c:232
static struct timeval unpackdate(unsigned char *i)
unpack a date and return
Definition: app_sms.c:579
char da[20]
Definition: app_sms.c:227
unsigned char dcs
Definition: app_sms.c:230
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char oa[20]
Definition: app_sms.c:226
unsigned char pid
Definition: app_sms.c:229
unsigned char udh[SMSLEN]
Definition: app_sms.c:239

◆ sms_handleincoming_proto2()

static int sms_handleincoming_proto2 ( sms_t h)
static

sms_handleincoming_proto2: handle the incoming message

Definition at line 1262 of file app_sms.c.

References ast_copy_string(), ast_localtime(), ast_mktime(), ast_tvnow(), ast_verb, c, sms_s::da, sms_s::imsg, MAX_DEBUG_LEN, NULL, sms_s::oa, sms_s::omsg, sms_s::rx, sms_s::scts, sms_hexdump(), sms_messagetx(), sms_nextoutgoing(), 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().

1263 {
1264  int f, i, sz = 0;
1265  int msg, msgsz;
1266  struct ast_tm tm;
1267  struct timeval now = { 0, 0 };
1268  char debug_buf[MAX_DEBUG_LEN * 3 + 1];
1269 
1270  sz = h->imsg[1] + 2;
1271  /* ast_verb(3, "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg, sz, debug_buf)); */
1272 
1273  /* Parse message body (called payload) */
1274  now = h->scts = ast_tvnow();
1275  for (f = 4; f < sz; ) {
1276  msg = h->imsg[f++];
1277  msgsz = h->imsg[f++];
1278  msgsz += (h->imsg[f++] * 256);
1279  switch (msg) {
1280  case 0x13: /* Body */
1281  ast_verb(3, "SMS-P2 Body#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
1282  if (msgsz >= sizeof(h->ud)) {
1283  msgsz = sizeof(h->ud) - 1;
1284  }
1285  for (i = 0; i < msgsz; i++) {
1286  h->ud[i] = h->imsg[f + i];
1287  }
1288  h->udl = msgsz;
1289  break;
1290  case 0x14: /* Date SCTS */
1291  now = h->scts = ast_tvnow();
1292  ast_localtime(&now, &tm, NULL);
1293  tm.tm_mon = ( (h->imsg[f] * 10) + h->imsg[f + 1] ) - 1;
1294  tm.tm_mday = ( (h->imsg[f + 2] * 10) + h->imsg[f + 3] );
1295  tm.tm_hour = ( (h->imsg[f + 4] * 10) + h->imsg[f + 5] );
1296  tm.tm_min = ( (h->imsg[f + 6] * 10) + h->imsg[f + 7] );
1297  tm.tm_sec = 0;
1298  h->scts = ast_mktime(&tm, NULL);
1299  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);
1300  break;
1301  case 0x15: /* Calling line (from SMSC) */
1302  if (msgsz >= 20) {
1303  msgsz = 20 - 1;
1304  }
1305  ast_verb(3, "SMS-P2 Origin#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
1306  ast_copy_string(h->oa, (char *)(&h->imsg[f]), msgsz + 1);
1307  break;
1308  case 0x18: /* Destination(from TE/phone) */
1309  if (msgsz >= 20) {
1310  msgsz = 20 - 1;
1311  }
1312  ast_verb(3, "SMS-P2 Destination#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
1313  ast_copy_string(h->da, (char *)(&h->imsg[f]), msgsz + 1);
1314  break;
1315  case 0x1C: /* Notify */
1316  ast_verb(3, "SMS-P2 Notify#%02X=%s\n", (unsigned)msg, sms_hexdump(&h->imsg[f], 3, debug_buf));
1317  break;
1318  default:
1319  ast_verb(3, "SMS-P2 Par#%02X [%d]: %s\n", (unsigned)msg, msgsz, sms_hexdump(&h->imsg[f], msgsz, debug_buf));
1320  break;
1321  }
1322  f+=msgsz; /* Skip to next */
1323  }
1324  h->rx = 1; /* received message */
1325  sms_writefile(h); /* write the file */
1326  return 0; /* no error */
1327 }
unsigned char rx
Definition: app_sms.c:223
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:1739
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
unsigned char imsg[250]
Definition: app_sms.c:250
#define ast_verb(level,...)
Definition: logger.h:463
struct timeval scts
Definition: app_sms.c:228
static void sms_writefile(sms_t *h)
white a received text message to a file
Definition: app_sms.c:998
unsigned short ud[SMSLEN]
Definition: app_sms.c:238
static char * sms_hexdump(unsigned char buf[], int size, char *s)
Definition: app_sms.c:1249
#define MAX_DEBUG_LEN
Definition: app_sms.c:1248
int udl
Definition: app_sms.c:232
char da[20]
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:2357
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char oa[20]
Definition: app_sms.c:226

◆ sms_hexdump()

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

Definition at line 1249 of file app_sms.c.

References MAX_DEBUG_LEN.

Referenced by sms_handleincoming_proto2().

1250 {
1251  char *p;
1252  int f;
1253 
1254  for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3) {
1255  sprintf(p, "%02hhX ", (unsigned char)buf[f]);
1256  }
1257  return(s);
1258 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define MAX_DEBUG_LEN
Definition: app_sms.c:1248

◆ sms_log()

static void sms_log ( sms_t h,
char  status 
)
static

Log the output, and remove file.

Definition at line 774 of file app_sms.c.

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

Referenced by sms_exec(), sms_messagerx(), and sms_messagerx2().

775 {
776  int o;
777 
778  if (*h->oa == '\0' && *h->da == '\0') {
779  return;
780  }
781  o = open(log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE);
782  if (o >= 0) {
783  char line[1000], mrs[3] = "", *p;
784  char buf[30];
785  unsigned char n;
786 
787  if (h->mr >= 0) {
788  snprintf(mrs, sizeof(mrs), "%02hhX", (unsigned char)h->mr);
789  }
790  snprintf(line, sizeof(line), "%s %c%c%c%s %s %s %s ",
791  isodate(time(NULL), buf, sizeof(buf)),
792  status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue,
793  S_OR(h->oa, "-"), S_OR(h->da, "-") );
794  p = line + strlen(line);
795 
796  if (h->nolog) {
797  p += snprintf(p, 1000 - strlen(line), "udl=%d", h->udl);
798  } else {
799  for (n = 0; n < h->udl; n++) {
800  if (h->ud[n] == '\\') {
801  *p++ = '\\';
802  *p++ = '\\';
803  } else if (h->ud[n] == '\n') {
804  *p++ = '\\';
805  *p++ = 'n';
806  } else if (h->ud[n] == '\r') {
807  *p++ = '\\';
808  *p++ = 'r';
809  } else if (h->ud[n] < 32 || h->ud[n] == 127) {
810  *p++ = 0xbf;
811  } else {
812  *p++ = h->ud[n];
813  }
814  }
815  }
816  *p++ = '\n';
817  *p = 0;
818  if (write(o, line, strlen(line)) < 0) {
819  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
820  }
821  close(o);
822  }
823  *h->oa = *h->da = h->udl = 0;
824 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
unsigned char rx
Definition: app_sms.c:223
#define NULL
Definition: resample.c:96
#define AST_FILE_MODE
Definition: asterisk.h:32
#define ast_log
Definition: astobj2.c:42
char queue[30]
Definition: app_sms.c:225
static char * isodate(time_t t, char *buf, int len)
static, return a date/time in ISO format
Definition: app_sms.c:303
unsigned char smsc
Definition: app_sms.c:222
static char log_file[255]
Definition: app_sms.c:122
unsigned char nolog
Definition: app_sms.c:224
int errno
unsigned short ud[SMSLEN]
Definition: app_sms.c:238
short mr
Definition: app_sms.c:231
int udl
Definition: app_sms.c:232
char da[20]
Definition: app_sms.c:227
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
char oa[20]
Definition: app_sms.c:226
jack_status_t status
Definition: app_jack.c:146

◆ sms_messagerx()

static void sms_messagerx ( sms_t h)
static

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

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

◆ sms_messagerx2()

static void sms_messagerx2 ( sms_t h)
static

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

1344 {
1345  int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */
1346  int cause;
1347 
1348 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
1349  switch (p) {
1350  case DLL2_SMS_EST: /* Protocol 2: Connection ready (fake): send message */
1351  sms_nextoutgoing (h);
1352  /* 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 "); */
1353  break;
1354 
1355  case DLL2_SMS_INFO_MO: /* transport SMS_SUBMIT */
1356  case DLL2_SMS_INFO_MT: /* transport SMS_DELIVERY */
1357  cause = sms_handleincoming_proto2(h);
1358  if (!cause) { /* ACK */
1359  sms_log(h, 'Y');
1360  }
1361  h->omsg[0] = DLL2_ACK(h);
1362  h->omsg[1] = 0x06; /* msg len */
1363  h->omsg[2] = 0x04; /* payload len */
1364  h->omsg[3] = 0x00; /* payload len */
1365  h->omsg[4] = 0x1f; /* Response type */
1366  h->omsg[5] = 0x01; /* parameter len */
1367  h->omsg[6] = 0x00; /* parameter len */
1368  h->omsg[7] = cause; /* CONFIRM or error */
1369  sms_messagetx(h);
1370  break;
1371 
1372  case DLL2_SMS_NACK: /* Protocol 2: SMS_NAK */
1373  h->omsg[0] = DLL2_SMS_REL; /* SMS_REL */
1374  h->omsg[1] = 0x00; /* msg len */
1375  sms_messagetx(h);
1376  break;
1377 
1378  case DLL2_SMS_ACK0:
1379  case DLL2_SMS_ACK1:
1380  /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */
1381  if ( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
1382  /* a response to our Release, just hangup */
1383  h->hangup = 1; /* hangup */
1384  } else {
1385  /* XXX depending on what we are.. */
1386  ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY\n");
1387  sms_nextoutgoing (h);
1388  }
1389  break;
1390 
1391  case DLL2_SMS_REL: /* Protocol 2: SMS_REL (hangup req) */
1392  h->omsg[0] = DLL2_ACK(h);
1393  h->omsg[1] = 0;
1394  sms_messagetx(h);
1395  break;
1396  }
1397 }
static void sms_messagetx(sms_t *h)
Definition: app_sms.c:1561
unsigned char hangup
Definition: app_sms.c:219
static int sms_handleincoming_proto2(sms_t *h)
sms_handleincoming_proto2: handle the incoming message
Definition: app_sms.c:1262
unsigned char imsg[250]
Definition: app_sms.c:250
unsigned char omsg[256]
Definition: app_sms.c:249
#define ast_log
Definition: astobj2.c:42
#define DLL2_ACK(h)
#define LOG_NOTICE
Definition: logger.h:263
static void sms_log(sms_t *h, char status)
Log the output, and remove file.
Definition: app_sms.c:774
static void sms_nextoutgoing(sms_t *h)
find and fill in next message, or send a REL if none waiting
Definition: app_sms.c:1442

◆ sms_messagetx()

static void sms_messagetx ( sms_t h)
static

Definition at line 1561 of file app_sms.c.

References c, 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_exec(), sms_handleincoming_proto2(), sms_messagerx(), sms_messagerx2(), sms_nextoutgoing(), and sms_process().

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

◆ sms_nextoutgoing()

static void sms_nextoutgoing ( sms_t h)
static

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

Definition at line 1442 of file app_sms.c.

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

Referenced by sms_handleincoming_proto2(), sms_messagerx(), and sms_messagerx2().

1443 {
1444  char fn[100 + NAME_MAX] = "";
1445  DIR *d;
1446  char more = 0;
1447 
1448  *h->da = *h->oa = '\0'; /* clear destinations */
1449  h->rx = 0; /* outgoing message */
1450  snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? "mttx" : "motx");
1451  ast_mkdir(fn, 0777); /* ensure it exists */
1452  d = opendir(fn);
1453  if (d) {
1454  struct dirent *f = readdirqueue(d, h->queue);
1455  if (f) {
1456  snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", f->d_name);
1457  sms_readfile(h, fn);
1458  if (readdirqueue(d, h->queue)) {
1459  more = 1; /* more to send */
1460  }
1461  }
1462  closedir(d);
1463  }
1464  if (*h->da || *h->oa) { /* message to send */
1465  if (h->protocol == 2) {
1466  sms_compose2(h, more);
1467  } else {
1468  sms_compose1(h, more);
1469  }
1470  } else { /* no message */
1471  if (h->protocol == 2) {
1472  h->omsg[0] = 0x17; /* SMS_REL */
1473  h->omsg[1] = 0;
1474  } else {
1475  h->omsg[0] = 0x94; /* SMS_REL */
1476  h->omsg[1] = 0;
1477  h->sent_rel = 1;
1478  }
1479  }
1480  sms_messagetx(h);
1481 }
static void sms_messagetx(sms_t *h)
Definition: app_sms.c:1561
unsigned char rx
Definition: app_sms.c:223
static struct test_val d
static void sms_compose1(sms_t *h, int more)
compose a message for protocol 1
Definition: app_sms.c:1400
unsigned char omsg[256]
Definition: app_sms.c:249
static void sms_readfile(sms_t *h, char *fn)
parse and delete a file
Definition: app_sms.c:827
static struct dirent * readdirqueue(DIR *d, char *queue)
read dir skipping dot files...
Definition: app_sms.c:1102
static void sms_compose2(sms_t *h, int more)
Definition: app_sms.c:1213
char queue[30]
Definition: app_sms.c:225
unsigned char smsc
Definition: app_sms.c:222
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:154
char da[20]
Definition: app_sms.c:227
char oa[20]
Definition: app_sms.c:226
unsigned char sent_rel
Definition: app_sms.c:221
int protocol
Definition: app_sms.c:274
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: main/utils.c:2231

◆ sms_process()

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

References abs, ast_log, ast_verb, sms_s::err, sms_s::framenumber, sms_s::hangup, sms_s::ibitc, sms_s::ibith, sms_s::ibitl, sms_s::ibitn, sms_s::ibitt, sms_s::ibytec, sms_s::ibytep, sms_s::ibytev, sms_s::idle, sms_s::ierr, sms_s::imag, sms_s::imc0, sms_s::imc1, sms_s::ims0, sms_s::ims1, sms_s::imsg, sms_s::ipc0, sms_s::ipc1, sms_s::iphasep, sms_s::ips0, sms_s::ips1, LOG_NOTICE, sms_s::obyten, sms_s::omsg, sms_s::osync, sms_s::protocol, sms_s::sent_rel, sms_messagerx(), sms_messagetx(), and wave.

Referenced by sms_exec().

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

◆ sms_readfile()

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

parse and delete a file

Definition at line 827 of file app_sms.c.

References ast_log, ast_mktime(), ast_tvnow(), d, sms_s::da, sms_s::dcs, is16bit, is7bit, is8bit, LOG_NOTICE, LOG_WARNING, sms_s::mr, NULL, numcpy(), sms_s::oa, packsms16(), packsms7(), packsms8(), sms_s::pid, sms_s::rp, sms_s::rx, S, sms_s::scts, SMSLEN, sms_s::srr, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, sms_s::udtxt, utf8decode(), and sms_s::vp.

Referenced by sms_nextoutgoing().

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

◆ sms_release()

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

Definition at line 1689 of file app_sms.c.

1690 {
1691  return; /* nothing to do here. */
1692 }

◆ sms_writefile()

static void sms_writefile ( sms_t h)
static

white a received text message to a file

Definition at line 998 of file app_sms.c.

References ast_config_AST_SPOOL_DIR, ast_copy_string(), ast_log, ast_mkdir(), ast_tvnow(), ast_tvzero(), buf, sms_s::da, sms_s::dcs, isodate(), LOG_NOTICE, sms_s::mr, NULL, sms_s::oa, sms_s::pid, sms_s::queue, sms_s::rp, sms_s::rx, sms_s::scts, seq, sms_s::smsc, sms_s::srr, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, and sms_s::vp.

Referenced by sms_exec(), sms_handleincoming(), and sms_handleincoming_proto2().

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

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2078 of file app_sms.c.

References app, and ast_unregister_application().

2079 {
2081 }
static char * app
Definition: app_sms.c:124
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

◆ unpackaddress()

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

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

Definition at line 728 of file app_sms.c.

Referenced by sms_handleincoming().

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

◆ unpackdate()

static struct timeval unpackdate ( unsigned char *  i)
static

unpack a date and return

Definition at line 579 of file app_sms.c.

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

Referenced by sms_handleincoming().

580 {
581  struct ast_tm t;
582 
583  t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
584  t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
585  t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
586  t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
587  t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
588  t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
589  t.tm_isdst = 0;
590  if (i[6] & 0x08) {
591  t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
592  } else {
593  t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
594  }
595 
596  return ast_mktime(&t, NULL);
597 }
#define NULL
Definition: resample.c:96
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:2357

◆ unpacksms()

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

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

Referenced by sms_handleincoming().

713 {
714  int l = *i++;
715  if (is7bit(dcs)) {
716  unpacksms7(i, l, udh, udhl, ud, udl, udhi);
717  l = (l * 7 + 7) / 8; /* adjust length to return */
718  } else if (is8bit(dcs)) {
719  unpacksms8(i, l, udh, udhl, ud, udl, udhi);
720  } else {
721  l += l % 2;
722  unpacksms16(i, l, udh, udhl, ud, udl, udhi);
723  }
724  return l + 1;
725 }
#define is7bit(dcs)
Definition: app_sms.c:281
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:658
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:684
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:602
#define is8bit(dcs)
Definition: app_sms.c:282

◆ unpacksms16()

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

References sms_s::ud.

Referenced by unpacksms().

685 {
686  unsigned short *o = ud;
687  *udhl = 0;
688  if (udhi) {
689  int n = *i;
690  *udhl = n;
691  if (n) {
692  i++;
693  l--;
694  while (l && n) {
695  l--;
696  n--;
697  *udh++ = *i++;
698  }
699  }
700  }
701  while (l--) {
702  int v = *i++;
703  if (l && l--) {
704  v = (v << 8) + *i++;
705  }
706  *o++ = v;
707  }
708  *udl = (o - ud);
709 }

◆ unpacksms7()

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

References b, defaultalphabet, escapes, and sms_s::ud.

Referenced by unpacksms().

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

◆ unpacksms8()

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

References sms_s::ud.

Referenced by unpacksms().

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

◆ utf8decode()

static long utf8decode ( unsigned char **  pp)
static

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

Definition at line 315 of file app_sms.c.

Referenced by sms_exec(), and sms_readfile().

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

Variable Documentation

◆ app

char* app = "SMS"
static

Definition at line 124 of file app_sms.c.

Referenced by load_module(), and unload_module().

◆ defaultalphabet

const unsigned short defaultalphabet[]
static

Definition at line 191 of file app_sms.c.

Referenced by packsms7(), and unpacksms7().

◆ escapes

const unsigned short escapes[]
static

Definition at line 204 of file app_sms.c.

Referenced by packsms7(), and unpacksms7().

◆ log_file

char log_file[255]
static

Definition at line 122 of file app_sms.c.

Referenced by load_module(), and sms_log().

◆ message_ref

volatile unsigned char message_ref
static

Definition at line 119 of file app_sms.c.

Referenced by sms_compose1().

◆ seq

volatile unsigned int seq
static

◆ sms_options

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

Definition at line 1879 of file app_sms.c.

Referenced by sms_exec().

◆ smsgen

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:1604
static void sms_release(struct ast_channel *chan, void *data)
Definition: app_sms.c:1689
static void * sms_alloc(struct ast_channel *chan, void *sms_t_ptr)
Definition: app_sms.c:1684

Definition at line 1694 of file app_sms.c.

◆ wave

const signed short wave[]
static

Definition at line 132 of file app_sms.c.

Referenced by load_module(), and sms_process().

◆ wave_out

const output_t* wave_out = wave
static

Definition at line 148 of file app_sms.c.

Referenced by sms_generate().