Wed Jan 8 2020 09:49:40

Asterisk developer's documentation


app_sms.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2005, Adrian Kennard, rights assigned to Digium
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16 
17 /*! \file
18  *
19  * \brief SMS application - ETSI ES 201 912 protocol 1 implementation
20  *
21  * \par Development notes
22  * \note The ETSI standards are available free of charge from ETSI at
23  * http://pda.etsi.org/pda/queryform.asp
24  * Among the relevant documents here we have:
25  *
26  * ES 201 912 SMS for PSTN/ISDN
27  * TS 123 040 Technical realization of SMS
28  *
29  *
30  * \ingroup applications
31  *
32  * \author Adrian Kennard (for the original protocol 1 code)
33  * \author Filippo Grassilli (Hyppo) - protocol 2 support
34  * Not fully tested, under development
35  */
36 
37 /*** MODULEINFO
38  <support_level>extended</support_level>
39  ***/
40 
41 #include "asterisk.h"
42 
43 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
44 
45 #include <dirent.h>
46 #include <ctype.h>
47 #include <sys/stat.h>
48 
49 #include "asterisk/paths.h" /* use ast_config_AST_SPOOL_DIR and LOG_DIR */
50 #include "asterisk/lock.h"
51 #include "asterisk/file.h"
52 #include "asterisk/channel.h"
53 #include "asterisk/pbx.h"
54 #include "asterisk/module.h"
55 #include "asterisk/alaw.h"
56 #include "asterisk/callerid.h"
57 #include "asterisk/utils.h"
58 #include "asterisk/app.h"
59 
60 /*** DOCUMENTATION
61  <application name="SMS" language="en_US">
62  <synopsis>
63  Communicates with SMS service centres and SMS capable analogue phones.
64  </synopsis>
65  <syntax>
66  <parameter name="name" required="true">
67  <para>The name of the queue used in <filename>/var/spool/asterisk/sms</filename></para>
68  </parameter>
69  <parameter name="options">
70  <optionlist>
71  <option name="a">
72  <para>Answer, i.e. send initial FSK packet.</para>
73  </option>
74  <option name="s">
75  <para>Act as service centre talking to a phone.</para>
76  </option>
77  <option name="t">
78  <para>Use protocol 2 (default used is protocol 1).</para>
79  </option>
80  <option name="p">
81  <para>Set the initial delay to N ms (default is <literal>300</literal>).
82  addr and body are a deprecated format to send messages out.</para>
83  </option>
84  <option name="r">
85  <para>Set the Status Report Request (SRR) bit.</para>
86  </option>
87  <option name="o">
88  <para>The body should be coded as octets not 7-bit symbols.</para>
89  </option>
90  </optionlist>
91  </parameter>
92  <parameter name="addr" />
93  <parameter name="body" />
94  </syntax>
95  <description>
96  <para>SMS handles exchange of SMS data with a call to/from SMS capable phone or SMS PSTN service center.
97  Can send and/or receive SMS messages. Works to ETSI ES 201 912; compatible with BT SMS PSTN service in
98  UK and Telecom Italia in Italy.</para>
99  <para>Typical usage is to use to handle calls from the SMS service centre CLI, or to set up a call using
100  <literal>outgoing</literal> or manager interface to connect service centre to SMS().</para>
101  <para>"Messages are processed as per text file message queues. smsq (a separate software) is a command to
102  generate message queues and send messages.</para>
103  <note><para>The protocol has tight delay bounds. Please use short frames and disable/keep short the
104  jitter buffer on the ATA to make sure that respones (ACK etc.) are received in time.</para></note>
105  </description>
106  </application>
107  ***/
108 
109 /* #define OUTALAW */ /* enable this to output Alaw rather than linear */
110 
111 /* ToDo */
112 /* Add full VP support */
113 /* Handle status report messages (generation and reception) */
114 /* Time zones on time stamps */
115 /* user ref field */
116 
117 static volatile unsigned char message_ref; /* arbitary message ref */
118 static volatile unsigned int seq; /* arbitrary message sequence number for unqiue files */
119 
120 static char log_file[255];
121 
122 static char *app = "SMS";
123 
124 /*
125  * 80 samples of a single period of the wave. At 8000 Hz, it means these
126  * are the samples of a 100 Hz signal.
127  * To pick the two carriers (1300Hz for '1' and 2100 Hz for '0') used by
128  * the modulation, we should take one every 13 and 21 samples respectively.
129  */
130 static const signed short wave[] = {
131  0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
132  5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
133  0, -392, -782, -1167,
134  -1545, -1913, -2270, -2612, -2939, -3247, -3536, -3802, -4045, -4263, -4455, -4619, -4755, -4862, -4938, -4985, -5000,
135  -4985, -4938, -4862,
136  -4755, -4619, -4455, -4263, -4045, -3802, -3536, -3247, -2939, -2612, -2270, -1913, -1545, -1167, -782, -392
137 };
138 
139 #ifdef OUTALAW
140 static unsigned char wavea[80];
141 typedef unsigned char output_t;
142 static const output_t *wave_out = wavea; /* outgoing samples */
143 #define __OUT_FMT AST_FORMAT_ALAW;
144 #else
145 typedef signed short output_t;
146 static const output_t *wave_out = wave; /* outgoing samples */
147 #define __OUT_FMT AST_FORMAT_SLINEAR
148 #endif
149 
150 #define OSYNC_BITS 80 /* initial sync bits */
151 
152 /*!
153  * The SMS spec ETSI ES 201 912 defines two protocols with different message types.
154  * Also note that the high bit is used to indicate whether the message
155  * is complete or not, but in two opposite ways:
156  * for Protocol 1, 0x80 means that the message is complete;
157  * for Protocol 2, 0x00 means that the message is complete;
158  */
160  DLL_SMS_MASK = 0x7f, /* mask for the valid bits */
161 
162  /* Protocol 1 values */
163  DLL1_SMS_DATA = 0x11, /* data packet */
165  DLL1_SMS_EST = 0x13, /* start the connection */
166  DLL1_SMS_REL = 0x14, /* end the connection */
167  DLL1_SMS_ACK = 0x15,
169 
170  DLL1_SMS_COMPLETE = 0x80, /* packet is complete */
171  DLL1_SMS_MORE = 0x00, /* more data to follow */
172 
173  /* Protocol 2 values */
174  DLL2_SMS_EST = 0x7f, /* magic number. No message body */
179  DLL2_SMS_ACK0 = 0x14, /* ack even-numbered frame */
180  DLL2_SMS_ACK1 = 0x15, /* ack odd-numbered frame */
181  DLL2_SMS_ENQ = 0x16,
182  DLL2_SMS_REL = 0x17, /* end the connection */
183 
184  DLL2_SMS_COMPLETE = 0x00, /* packet is complete */
185  DLL2_SMS_MORE = 0x80, /* more data to follow */
186 };
187 
188 /* SMS 7 bit character mapping to UCS-2 */
189 static const unsigned short defaultalphabet[] = {
190  0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
191  0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
192  0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
193  0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
194  ' ', '!', '"', '#', 164, '%', '&', 39, '(', ')', '*', '+', ',', '-', '.', '/',
195  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
196  161, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
197  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 196, 214, 209, 220, 167,
198  191, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
199  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 228, 246, 241, 252, 224,
200 };
201 
202 static const unsigned short escapes[] = {
203  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x000C, 0, 0, 0, 0, 0,
204  0, 0, 0, 0, 0x005E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
205  0, 0, 0, 0, 0, 0, 0, 0, 0x007B, 0x007D, 0, 0, 0, 0, 0, 0x005C,
206  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x005B, 0x007E, 0x005D, 0,
207  0x007C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
209  0, 0, 0, 0, 0, 0x20AC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
210  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
211 };
212 
213 #define SMSLEN 160 /*!< max SMS length */
214 #define SMSLEN_8 140 /*!< max SMS length for 8-bit char */
215 
216 typedef struct sms_s {
217  unsigned char hangup; /*!< we are done... */
218  unsigned char err; /*!< set for any errors */
219  unsigned char sent_rel:1; /*!< have sent REL message... */
220  unsigned char smsc:1; /*!< we are SMSC */
221  unsigned char rx:1; /*!< this is a received message */
222  char queue[30]; /*!< queue name */
223  char oa[20]; /*!< originating address */
224  char da[20]; /*!< destination address */
225  struct timeval scts; /*!< time stamp, UTC */
226  unsigned char pid; /*!< protocol ID */
227  unsigned char dcs; /*!< data coding scheme */
228  short mr; /*!< message reference - actually a byte, but use -1 for not set */
229  int udl; /*!< user data length */
230  int udhl; /*!< user data header length */
231  unsigned char srr:1; /*!< Status Report request */
232  unsigned char udhi:1; /*!< User Data Header required, even if length 0 */
233  unsigned char rp:1; /*!< Reply Path */
234  unsigned int vp; /*!< validity period in minutes, 0 for not set */
235  unsigned short ud[SMSLEN]; /*!< user data (message), UCS-2 coded */
236  unsigned char udh[SMSLEN]; /*!< user data header */
237  char cli[20]; /*!< caller ID */
238  unsigned char ophase; /*!< phase (0-79) for 0 and 1 frequencies (1300Hz and 2100Hz) */
239  unsigned char ophasep; /*!< phase (0-79) for 1200 bps */
240  unsigned char obyte; /*!< byte being sent */
241  unsigned int opause; /*!< silent pause before sending (in sample periods) */
242  unsigned char obitp; /*!< bit in byte */
243  unsigned char osync; /*!< sync bits to send */
244  unsigned char obytep; /*!< byte in data */
245  unsigned char obyten; /*!< bytes in data */
246  unsigned char omsg[256]; /*!< data buffer (out) */
247  unsigned char imsg[250]; /*!< data buffer (in) */
248  signed long long ims0,
249  imc0,
250  ims1,
251  imc1; /*!< magnitude averages sin/cos 0/1 */
252  unsigned int idle;
253  unsigned short imag; /*!< signal level */
254  unsigned char ips0; /*!< phase sin for bit 0, start at 0 inc by 21 mod 80 */
255  unsigned char ips1; /*!< phase cos for bit 0, start at 20 inc by 21 mod 80 */
256  unsigned char ipc0; /*!< phase sin for bit 1, start at 0 inc by 13 mod 80 */
257  unsigned char ipc1; /*!< phase cos for bit 1, start at 20 inc by 13 mod 80 */
258  unsigned char ibitl; /*!< last bit */
259  unsigned char ibitc; /*!< bit run length count */
260  unsigned char iphasep; /*!< bit phase (0-79) for 1200 bps */
261  unsigned char ibitn; /*!< bit number in byte being received */
262  unsigned char ibytev; /*!< byte value being received */
263  unsigned char ibytep; /*!< byte pointer in message */
264  unsigned char ibytec; /*!< byte checksum for message */
265  unsigned char ierr; /*!< error flag */
266  unsigned char ibith; /*!< history of last bits */
267  unsigned char ibitt; /*!< total of 1's in last 3 bytes */
268  /* more to go here */
269 
270  int opause_0; /*!< initial delay in ms, p() option */
271  int protocol; /*!< ETSI SMS protocol to use (passed at app call) */
272  int oseizure; /*!< protocol 2: channel seizure bits to send */
273  int framenumber; /*!< protocol 2: frame number (for sending ACK0 or ACK1) */
274  char udtxt[SMSLEN]; /*!< user data (message), PLAIN text */
275 } sms_t;
276 
277 /* different types of encoding */
278 #define is7bit(dcs) ( ((dcs) & 0xC0) ? (!((dcs) & 4) ) : (((dcs) & 0xc) == 0) )
279 #define is8bit(dcs) ( ((dcs) & 0xC0) ? ( ((dcs) & 4) ) : (((dcs) & 0xc) == 4) )
280 #define is16bit(dcs) ( ((dcs) & 0xC0) ? 0 : (((dcs) & 0xc) == 8) )
281 
282 static void sms_messagetx(sms_t *h);
283 
284 /*! \brief copy number, skipping non digits apart from leading + */
285 static void numcpy(char *d, char *s)
286 {
287  if (*s == '+') {
288  *d++ = *s++;
289  }
290  while (*s) {
291  if (isdigit(*s)) {
292  *d++ = *s;
293  }
294  s++;
295  }
296  *d = 0;
297 }
298 
299 /*! \brief static, return a date/time in ISO format */
300 static char *isodate(time_t t, char *buf, int len)
301 {
302  struct ast_tm tm;
303  struct timeval local = { t, 0 };
304  ast_localtime(&local, &tm, NULL);
305  ast_strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
306  return buf;
307 }
308 
309 /*! \brief Reads next UCS character from NUL terminated UTF-8 string and advance pointer */
310 /* for non valid UTF-8 sequences, returns character as is */
311 /* Does not advance pointer for null termination */
312 static long utf8decode(unsigned char **pp)
313 {
314  unsigned char *p = *pp;
315  if (!*p) {
316  return 0; /* null termination of string */
317  }
318  (*pp)++;
319  if (*p < 0xC0) {
320  return *p; /* ascii or continuation character */
321  }
322  if (*p < 0xE0) {
323  if (*p < 0xC2 || (p[1] & 0xC0) != 0x80) {
324  return *p; /* not valid UTF-8 */
325  }
326  (*pp)++;
327  return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
328  }
329  if (*p < 0xF0) {
330  if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80) {
331  return *p; /* not valid UTF-8 */
332  }
333  (*pp) += 2;
334  return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
335  }
336  if (*p < 0xF8) {
337  if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80) {
338  return *p; /* not valid UTF-8 */
339  }
340  (*pp) += 3;
341  return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
342  }
343  if (*p < 0xFC) {
344  if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
345  || (p[4] & 0xC0) != 0x80) {
346  return *p; /* not valid UTF-8 */
347  }
348  (*pp) += 4;
349  return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
350  }
351  if (*p < 0xFE) {
352  if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
353  || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80) {
354  return *p; /* not valid UTF-8 */
355  }
356  (*pp) += 5;
357  return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
358  }
359  return *p; /* not sensible */
360 }
361 
362 /*! \brief 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 */
363 /* The return value is the number of septets packed in to o, which is internally limited to SMSLEN */
364 /* o can be null, in which case this is used to validate or count only */
365 /* if the input contains invalid characters then the return value is -1 */
366 static int packsms7(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
367 {
368  unsigned char p = 0; /* output pointer (bytes) */
369  unsigned char b = 0; /* bit position */
370  unsigned char n = 0; /* output character count */
371  unsigned char dummy[SMSLEN];
372 
373  if (o == NULL) { /* output to a dummy buffer if o not set */
374  o = dummy;
375  }
376 
377  if (udhl) { /* header */
378  o[p++] = udhl;
379  b = 1;
380  n = 1;
381  while (udhl--) {
382  o[p++] = *udh++;
383  b += 8;
384  while (b >= 7) {
385  b -= 7;
386  n++;
387  }
388  if (n >= SMSLEN)
389  return n;
390  }
391  if (b) {
392  b = 7 - b;
393  if (++n >= SMSLEN)
394  return n;
395  } /* filling to septet boundary */
396  }
397  o[p] = 0;
398  /* message */
399  while (udl--) {
400  long u;
401  unsigned char v;
402  u = *ud++;
403  /* XXX 0 is invalid ? */
404  /* look up in defaultalphabet[]. If found, v is the 7-bit code */
405  for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
406  if (v == 128 /* not found */ && u && n + 1 < SMSLEN) {
407  /* if not found, look in the escapes table (we need 2 bytes) */
408  for (v = 0; v < 128 && escapes[v] != u; v++);
409  if (v < 128) { /* escaped sequence, esc + v */
410  /* store the low (8-b) bits in o[p], the remaining bits in o[p+1] */
411  o[p] |= (27 << b); /* the low bits go into o[p] */
412  b += 7;
413  if (b >= 8) {
414  b -= 8;
415  p++;
416  o[p] = (27 >> (7 - b));
417  }
418  n++;
419  }
420  }
421  if (v == 128)
422  return -1; /* invalid character */
423  /* store, same as above */
424  o[p] |= (v << b);
425  b += 7;
426  if (b >= 8) {
427  b -= 8;
428  p++;
429  o[p] = (v >> (7 - b));
430  }
431  if (++n >= SMSLEN)
432  return n;
433  }
434  return n;
435 }
436 
437 /*! \brief takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud)
438  * and packs in to o using 8 bit character codes.
439  * The return value is the number of bytes packed in to o, which is internally limited to 140.
440  * o can be null, in which case this is used to validate or count only.
441  * if the input contains invalid characters then the return value is -1
442  */
443 static int packsms8(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
444 {
445  unsigned char p = 0;
446  unsigned char dummy[SMSLEN_8];
447 
448  if (o == NULL)
449  o = dummy;
450  /* header - no encoding */
451  if (udhl) {
452  o[p++] = udhl;
453  while (udhl--) {
454  o[p++] = *udh++;
455  if (p >= SMSLEN_8) {
456  return p;
457  }
458  }
459  }
460  while (udl--) {
461  long u;
462  u = *ud++;
463  if (u < 0 || u > 0xFF) {
464  return -1; /* not valid */
465  }
466  o[p++] = u;
467  if (p >= SMSLEN_8) {
468  return p;
469  }
470  }
471  return p;
472 }
473 
474 /*! \brief takes a binary header (udhl bytes at udh) and UCS-2
475  message (udl characters at ud) and packs in to o using 16 bit
476  UCS-2 character codes
477  The return value is the number of bytes packed in to o, which is
478  internally limited to 140
479  o can be null, in which case this is used to validate or count
480  only if the input contains invalid characters then
481  the return value is -1 */
482 static int packsms16(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
483 {
484  unsigned char p = 0;
485  unsigned char dummy[SMSLEN_8];
486 
487  if (o == NULL) {
488  o = dummy;
489  }
490  /* header - no encoding */
491  if (udhl) {
492  o[p++] = udhl;
493  while (udhl--) {
494  o[p++] = *udh++;
495  if (p >= SMSLEN_8) {
496  return p;
497  }
498  }
499  }
500  while (udl--) {
501  long u;
502  u = *ud++;
503  o[p++] = (u >> 8);
504  if (p >= SMSLEN_8) {
505  return p - 1; /* could not fit last character */
506  }
507  o[p++] = u;
508  if (p >= SMSLEN_8) {
509  return p;
510  }
511  }
512  return p;
513 }
514 
515 /*! \brief general pack, with length and data,
516  returns number of bytes of target used */
517 static int packsms(unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
518 {
519  unsigned char *p = base;
520  if (udl == 0) {
521  *p++ = 0; /* no user data */
522  } else {
523 
524  int l = 0;
525  if (is7bit(dcs)) { /* 7 bit */
526  if ((l = packsms7(p + 1, udhl, udh, udl, ud)) < 0) {
527  l = 0;
528  }
529  *p++ = l;
530  p += (l * 7 + 7) / 8;
531  } else if (is8bit(dcs)) { /* 8 bit */
532  if ((l = packsms8(p + 1, udhl, udh, udl, ud)) < 0) {
533  l = 0;
534  }
535  *p++ = l;
536  p += l;
537  } else { /* UCS-2 */
538  if ((l = packsms16(p + 1, udhl, udh, udl, ud)) < 0) {
539  l = 0;
540  }
541  *p++ = l;
542  p += l;
543  }
544  }
545  return p - base;
546 }
547 
548 
549 /*! \brief pack a date and return */
550 static void packdate(unsigned char *o, time_t w)
551 {
552  struct ast_tm t;
553  struct timeval topack = { w, 0 };
554  int z;
555 
556  ast_localtime(&topack, &t, NULL);
557 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
558  z = -t.tm_gmtoff / 60 / 15;
559 #else
560  z = timezone / 60 / 15;
561 #endif
562  *o++ = ((t.tm_year % 10) << 4) + (t.tm_year % 100) / 10;
563  *o++ = (((t.tm_mon + 1) % 10) << 4) + (t.tm_mon + 1) / 10;
564  *o++ = ((t.tm_mday % 10) << 4) + t.tm_mday / 10;
565  *o++ = ((t.tm_hour % 10) << 4) + t.tm_hour / 10;
566  *o++ = ((t.tm_min % 10) << 4) + t.tm_min / 10;
567  *o++ = ((t.tm_sec % 10) << 4) + t.tm_sec / 10;
568  if (z < 0) {
569  *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
570  } else {
571  *o++ = ((z % 10) << 4) + z / 10;
572  }
573 }
574 
575 /*! \brief unpack a date and return */
576 static struct timeval unpackdate(unsigned char *i)
577 {
578  struct ast_tm t;
579 
580  t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
581  t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
582  t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
583  t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
584  t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
585  t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
586  t.tm_isdst = 0;
587  if (i[6] & 0x08) {
588  t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
589  } else {
590  t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
591  }
592 
593  return ast_mktime(&t, NULL);
594 }
595 
596 /*! \brief unpacks bytes (7 bit encoding) at i, len l septets,
597  and places in udh and ud setting udhl and udl. udh not used
598  if udhi not set */
599 static void unpacksms7(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
600 {
601  unsigned char b = 0, p = 0;
602  unsigned short *o = ud;
603  *udhl = 0;
604  if (udhi && l) { /* header */
605  int h = i[p];
606  *udhl = h;
607  if (h) {
608  b = 1;
609  p++;
610  l--;
611  while (h-- && l) {
612  *udh++ = i[p++];
613  b += 8;
614  while (b >= 7) {
615  b -= 7;
616  l--;
617  if (!l) {
618  break;
619  }
620  }
621  }
622  /* adjust for fill, septets */
623  if (b) {
624  b = 7 - b;
625  l--;
626  }
627  }
628  }
629  while (l--) {
630  unsigned char v;
631  if (b < 2) {
632  v = ((i[p] >> b) & 0x7F); /* everything in one byte */
633  } else {
634  v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
635  }
636  b += 7;
637  if (b >= 8) {
638  b -= 8;
639  p++;
640  }
641  /* 0x00A0 is the encoding of ESC (27) in defaultalphabet */
642  if (o > ud && o[-1] == 0x00A0 && escapes[v]) {
643  o[-1] = escapes[v];
644  } else {
645  *o++ = defaultalphabet[v];
646  }
647  }
648  *udl = (o - ud);
649 }
650 
651 /*! \brief unpacks bytes (8 bit encoding) at i, len l septets,
652  * and places in udh and ud setting udhl and udl. udh not used
653  * if udhi not set.
654  */
655 static void unpacksms8(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
656 {
657  unsigned short *o = ud;
658  *udhl = 0;
659  if (udhi) {
660  int n = *i;
661  *udhl = n;
662  if (n) {
663  i++;
664  l--;
665  while (l && n) {
666  l--;
667  n--;
668  *udh++ = *i++;
669  }
670  }
671  }
672  while (l--) {
673  *o++ = *i++; /* not to UTF-8 as explicitly 8 bit coding in DCS */
674  }
675  *udl = (o - ud);
676 }
677 
678 /*! \brief unpacks bytes (16 bit encoding) at i, len l septets,
679  and places in udh and ud setting udhl and udl.
680  udh not used if udhi not set */
681 static void unpacksms16(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
682 {
683  unsigned short *o = ud;
684  *udhl = 0;
685  if (udhi) {
686  int n = *i;
687  *udhl = n;
688  if (n) {
689  i++;
690  l--;
691  while (l && n) {
692  l--;
693  n--;
694  *udh++ = *i++;
695  }
696  }
697  }
698  while (l--) {
699  int v = *i++;
700  if (l && l--) {
701  v = (v << 8) + *i++;
702  }
703  *o++ = v;
704  }
705  *udl = (o - ud);
706 }
707 
708 /*! \brief general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length */
709 static int unpacksms(unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
710 {
711  int l = *i++;
712  if (is7bit(dcs)) {
713  unpacksms7(i, l, udh, udhl, ud, udl, udhi);
714  l = (l * 7 + 7) / 8; /* adjust length to return */
715  } else if (is8bit(dcs)) {
716  unpacksms8(i, l, udh, udhl, ud, udl, udhi);
717  } else {
718  l += l % 2;
719  unpacksms16(i, l, udh, udhl, ud, udl, udhi);
720  }
721  return l + 1;
722 }
723 
724 /*! \brief unpack an address from i, return byte length, unpack to o */
725 static unsigned char unpackaddress(char *o, unsigned char *i)
726 {
727  unsigned char l = i[0], p;
728  if (i[1] == 0x91) {
729  *o++ = '+';
730  }
731  for (p = 0; p < l; p++) {
732  if (p & 1) {
733  *o++ = (i[2 + p / 2] >> 4) + '0';
734  } else {
735  *o++ = (i[2 + p / 2] & 0xF) + '0';
736  }
737  }
738  *o = 0;
739  return (l + 5) / 2;
740 }
741 
742 /*! \brief store an address at o, and return number of bytes used */
743 static unsigned char packaddress(unsigned char *o, char *i)
744 {
745  unsigned char p = 2;
746  o[0] = 0; /* number of bytes */
747  if (*i == '+') { /* record as bit 0 in byte 1 */
748  i++;
749  o[1] = 0x91;
750  } else {
751  o[1] = 0x81;
752  }
753  for ( ; *i ; i++) {
754  if (!isdigit(*i)) { /* ignore non-digits */
755  continue;
756  }
757  if (o[0] & 1) {
758  o[p++] |= ((*i & 0xF) << 4);
759  } else {
760  o[p] = (*i & 0xF);
761  }
762  o[0]++;
763  }
764  if (o[0] & 1) {
765  o[p++] |= 0xF0; /* pad */
766  }
767  return p;
768 }
769 
770 /*! \brief Log the output, and remove file */
771 static void sms_log(sms_t * h, char status)
772 {
773  int o;
774 
775  if (*h->oa == '\0' && *h->da == '\0') {
776  return;
777  }
778  o = open(log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE);
779  if (o >= 0) {
780  char line[1000], mrs[3] = "", *p;
781  char buf[30];
782  unsigned char n;
783 
784  if (h->mr >= 0) {
785  snprintf(mrs, sizeof(mrs), "%02X", (unsigned)h->mr);
786  }
787  snprintf(line, sizeof(line), "%s %c%c%c%s %s %s %s ",
788  isodate(time(NULL), buf, sizeof(buf)),
789  status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue,
790  S_OR(h->oa, "-"), S_OR(h->da, "-") );
791  p = line + strlen(line);
792  for (n = 0; n < h->udl; n++) {
793  if (h->ud[n] == '\\') {
794  *p++ = '\\';
795  *p++ = '\\';
796  } else if (h->ud[n] == '\n') {
797  *p++ = '\\';
798  *p++ = 'n';
799  } else if (h->ud[n] == '\r') {
800  *p++ = '\\';
801  *p++ = 'r';
802  } else if (h->ud[n] < 32 || h->ud[n] == 127) {
803  *p++ = 191;
804  } else {
805  *p++ = h->ud[n];
806  }
807  }
808  *p++ = '\n';
809  *p = 0;
810  if (write(o, line, strlen(line)) < 0) {
811  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
812  }
813  close(o);
814  }
815  *h->oa = *h->da = h->udl = 0;
816 }
817 
818 /*! \brief parse and delete a file */
819 static void sms_readfile(sms_t * h, char *fn)
820 {
821  char line[1000];
822  FILE *s;
823  char dcsset = 0; /* if DSC set */
824  ast_log(LOG_NOTICE, "Sending %s\n", fn);
825  h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
826  h->mr = -1;
827  h->dcs = 0xF1; /* normal messages class 1 */
828  h->scts = ast_tvnow();
829  s = fopen(fn, "r");
830  if (s) {
831  if (unlink(fn)) { /* concurrent access, we lost */
832  fclose(s);
833  return;
834  }
835  while (fgets (line, sizeof(line), s)) { /* process line in file */
836  char *p;
837  void *pp = &p;
838  for (p = line; *p && *p != '\n' && *p != '\r'; p++);
839  *p = 0; /* strip eoln */
840  p = line;
841  if (!*p || *p == ';') {
842  continue; /* blank line or comment, ignore */
843  }
844  while (isalnum(*p)) {
845  *p = tolower (*p);
846  p++;
847  }
848  while (isspace (*p)) {
849  *p++ = 0;
850  }
851  if (*p == '=') {
852  *p++ = 0;
853  if (!strcmp(line, "ud")) { /* parse message (UTF-8) */
854  unsigned char o = 0;
855  memcpy(h->udtxt, p, SMSLEN); /* for protocol 2 */
856  while (*p && o < SMSLEN) {
857  h->ud[o++] = utf8decode(pp);
858  }
859  h->udl = o;
860  if (*p) {
861  ast_log(LOG_WARNING, "UD too long in %s\n", fn);
862  }
863  } else {
864  while (isspace (*p)) {
865  p++;
866  }
867  if (!strcmp(line, "oa") && strlen(p) < sizeof(h->oa)) {
868  numcpy (h->oa, p);
869  } else if (!strcmp(line, "da") && strlen(p) < sizeof(h->oa)) {
870  numcpy (h->da, p);
871  } else if (!strcmp(line, "pid")) {
872  h->pid = atoi(p);
873  } else if (!strcmp(line, "dcs")) {
874  h->dcs = atoi(p);
875  dcsset = 1;
876  } else if (!strcmp(line, "mr")) {
877  h->mr = atoi(p);
878  } else if (!strcmp(line, "srr")) {
879  h->srr = (atoi(p) ? 1 : 0);
880  } else if (!strcmp(line, "vp")) {
881  h->vp = atoi(p);
882  } else if (!strcmp(line, "rp")) {
883  h->rp = (atoi(p) ? 1 : 0);
884  } else if (!strcmp(line, "scts")) { /* get date/time */
885  int Y, m, d, H, M, S;
886  /* XXX Why aren't we using ast_strptime here? */
887  if (sscanf(p, "%4d-%2d-%2dT%2d:%2d:%2d", &Y, &m, &d, &H, &M, &S) == 6) {
888  struct ast_tm t = { 0, };
889  t.tm_year = Y - 1900;
890  t.tm_mon = m - 1;
891  t.tm_mday = d;
892  t.tm_hour = H;
893  t.tm_min = M;
894  t.tm_sec = S;
895  t.tm_isdst = -1;
896  h->scts = ast_mktime(&t, NULL);
897  if (h->scts.tv_sec == 0) {
898  ast_log(LOG_WARNING, "Bad date/timein %s: %s", fn, p);
899  }
900  }
901  } else {
902  ast_log(LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
903  }
904  }
905  } else if (*p == '#') { /* raw hex format */
906  *p++ = 0;
907  if (*p == '#') {
908  p++;
909  if (!strcmp(line, "ud")) { /* user data */
910  int o = 0;
911  while (*p && o < SMSLEN) {
912  if (isxdigit(*p) && isxdigit(p[1]) && isxdigit(p[2]) && isxdigit(p[3])) {
913  h->ud[o++] =
914  (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 12) +
915  (((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
916  (((isalpha(p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha(p[3]) ? 9 : 0) + (p[3] & 0xF));
917  p += 4;
918  } else
919  break;
920  }
921  h->udl = o;
922  if (*p)
923  ast_log(LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
924  } else
925  ast_log(LOG_WARNING, "Only ud can use ## format, %s\n", fn);
926  } else if (!strcmp(line, "ud")) { /* user data */
927  int o = 0;
928  while (*p && o < SMSLEN) {
929  if (isxdigit(*p) && isxdigit(p[1])) {
930  h->ud[o++] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
931  p += 2;
932  } else {
933  break;
934  }
935  }
936  h->udl = o;
937  if (*p) {
938  ast_log(LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
939  }
940  } else if (!strcmp(line, "udh")) { /* user data header */
941  unsigned char o = 0;
942  h->udhi = 1;
943  while (*p && o < SMSLEN) {
944  if (isxdigit(*p) && isxdigit(p[1])) {
945  h->udh[o] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
946  o++;
947  p += 2;
948  } else {
949  break;
950  }
951  }
952  h->udhl = o;
953  if (*p) {
954  ast_log(LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
955  }
956  } else {
957  ast_log(LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
958  }
959  } else {
960  ast_log(LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
961  }
962  }
963  fclose(s);
964  if (!dcsset && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
965  if (packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
966  if (packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
967  ast_log(LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
968  } else {
969  h->dcs = 0x08; /* default to 16 bit */
970  ast_log(LOG_WARNING, "Sending in 16 bit format(%s)\n", fn);
971  }
972  } else {
973  h->dcs = 0xF5; /* default to 8 bit */
974  ast_log(LOG_WARNING, "Sending in 8 bit format(%s)\n", fn);
975  }
976  }
977  if (is7bit(h->dcs) && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
978  ast_log(LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
979  }
980  if (is8bit(h->dcs) && packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
981  ast_log(LOG_WARNING, "Invalid 8 bit data %s\n", fn);
982  }
983  if (is16bit(h->dcs) && packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
984  ast_log(LOG_WARNING, "Invalid 16 bit data %s\n", fn);
985  }
986  }
987 }
988 
989 /*! \brief white a received text message to a file */
990 static void sms_writefile(sms_t * h)
991 {
992  char fn[200] = "", fn2[200] = "";
993  char buf[30];
994  FILE *o;
995 
996  if (ast_tvzero(h->scts)) {
997  h->scts = ast_tvnow();
998  }
999  snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
1000  ast_mkdir(fn, 0777); /* ensure it exists */
1001  ast_copy_string(fn2, fn, sizeof(fn2));
1002  snprintf(fn2 + strlen(fn2), sizeof(fn2) - strlen(fn2), "/%s.%s-%u", h->queue, isodate(h->scts.tv_sec, buf, sizeof(buf)), seq++);
1003  snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/.%s", fn2 + strlen(fn) + 1);
1004  if ((o = fopen(fn, "w")) == NULL) {
1005  return;
1006  }
1007 
1008  if (*h->oa) {
1009  fprintf(o, "oa=%s\n", h->oa);
1010  }
1011  if (*h->da) {
1012  fprintf(o, "da=%s\n", h->da);
1013  }
1014  if (h->udhi) {
1015  unsigned int p;
1016  fprintf(o, "udh#");
1017  for (p = 0; p < h->udhl; p++) {
1018  fprintf(o, "%02X", (unsigned)h->udh[p]);
1019  }
1020  fprintf(o, "\n");
1021  }
1022  if (h->udl) {
1023  unsigned int p;
1024  for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
1025  if (p < h->udl) {
1026  fputc(';', o); /* cannot use ud=, but include as a comment for human readable */
1027  }
1028  fprintf(o, "ud=");
1029  for (p = 0; p < h->udl; p++) {
1030  unsigned short v = h->ud[p];
1031  if (v < 32) {
1032  fputc(191, o);
1033  } else if (v < 0x80) {
1034  fputc(v, o);
1035  } else if (v < 0x800) {
1036  fputc(0xC0 + (v >> 6), o);
1037  fputc(0x80 + (v & 0x3F), o);
1038  } else {
1039  fputc(0xE0 + (v >> 12), o);
1040  fputc(0x80 + ((v >> 6) & 0x3F), o);
1041  fputc(0x80 + (v & 0x3F), o);
1042  }
1043  }
1044  fprintf(o, "\n");
1045  for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
1046  if (p < h->udl) {
1047  for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
1048  if (p == h->udl) { /* can write in ucs-1 hex */
1049  fprintf(o, "ud#");
1050  for (p = 0; p < h->udl; p++) {
1051  fprintf(o, "%02X", (unsigned)h->ud[p]);
1052  }
1053  fprintf(o, "\n");
1054  } else { /* write in UCS-2 */
1055  fprintf(o, "ud##");
1056  for (p = 0; p < h->udl; p++) {
1057  fprintf(o, "%04X", (unsigned)h->ud[p]);
1058  }
1059  fprintf(o, "\n");
1060  }
1061  }
1062  }
1063  if (h->scts.tv_sec) {
1064  char datebuf[30];
1065  fprintf(o, "scts=%s\n", isodate(h->scts.tv_sec, datebuf, sizeof(datebuf)));
1066  }
1067  if (h->pid) {
1068  fprintf(o, "pid=%d\n", h->pid);
1069  }
1070  if (h->dcs != 0xF1) {
1071  fprintf(o, "dcs=%d\n", h->dcs);
1072  }
1073  if (h->vp) {
1074  fprintf(o, "vp=%u\n", h->vp);
1075  }
1076  if (h->srr) {
1077  fprintf(o, "srr=1\n");
1078  }
1079  if (h->mr >= 0) {
1080  fprintf(o, "mr=%d\n", h->mr);
1081  }
1082  if (h->rp) {
1083  fprintf(o, "rp=1\n");
1084  }
1085  fclose(o);
1086  if (rename(fn, fn2)) {
1087  unlink(fn);
1088  } else {
1089  ast_log(LOG_NOTICE, "Received to %s\n", fn2);
1090  }
1091 }
1092 
1093 /*! \brief read dir skipping dot files... */
1094 static struct dirent *readdirqueue(DIR *d, char *queue)
1095 {
1096  struct dirent *f;
1097  do {
1098  f = readdir(d);
1099  } while (f && (*f->d_name == '.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] != '.'));
1100  return f;
1101 }
1102 
1103 /*! \brief handle the incoming message */
1104 static unsigned char sms_handleincoming (sms_t * h)
1105 {
1106  unsigned char p = 3;
1107  if (h->smsc) { /* SMSC */
1108  if ((h->imsg[2] & 3) == 1) { /* SMS-SUBMIT */
1109  h->udhl = h->udl = 0;
1110  h->vp = 0;
1111  h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1112  h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1113  h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1114  ast_copy_string(h->oa, h->cli, sizeof(h->oa));
1115  h->scts = ast_tvnow();
1116  h->mr = h->imsg[p++];
1117  p += unpackaddress(h->da, h->imsg + p);
1118  h->pid = h->imsg[p++];
1119  h->dcs = h->imsg[p++];
1120  if ((h->imsg[2] & 0x18) == 0x10) { /* relative VP */
1121  if (h->imsg[p] < 144) {
1122  h->vp = (h->imsg[p] + 1) * 5;
1123  } else if (h->imsg[p] < 168) {
1124  h->vp = 720 + (h->imsg[p] - 143) * 30;
1125  } else if (h->imsg[p] < 197) {
1126  h->vp = (h->imsg[p] - 166) * 1440;
1127  } else {
1128  h->vp = (h->imsg[p] - 192) * 10080;
1129  }
1130  p++;
1131  } else if (h->imsg[2] & 0x18) {
1132  p += 7; /* ignore enhanced / absolute VP */
1133  }
1134  p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1135  h->rx = 1; /* received message */
1136  sms_writefile(h); /* write the file */
1137  if (p != h->imsg[1] + 2) {
1138  ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1139  return 0xFF; /* duh! */
1140  }
1141  } else {
1142  ast_log(LOG_WARNING, "Unknown message type %02X\n", (unsigned)h->imsg[2]);
1143  return 0xFF;
1144  }
1145  } else { /* client */
1146  if (!(h->imsg[2] & 3)) { /* SMS-DELIVER */
1147  *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
1148  h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1149  h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1150  h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1151  h->mr = -1;
1152  p += unpackaddress(h->oa, h->imsg + p);
1153  h->pid = h->imsg[p++];
1154  h->dcs = h->imsg[p++];
1155  h->scts = unpackdate(h->imsg + p);
1156  p += 7;
1157  p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1158  h->rx = 1; /* received message */
1159  sms_writefile(h); /* write the file */
1160  if (p != h->imsg[1] + 2) {
1161  ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1162  return 0xFF; /* duh! */
1163  }
1164  } else {
1165  ast_log(LOG_WARNING, "Unknown message type %02X\n", (unsigned)h->imsg[2]);
1166  return 0xFF;
1167  }
1168  }
1169  return 0; /* no error */
1170 }
1171 
1172 #ifdef SOLARIS
1173 #define NAME_MAX 1024
1174 #endif
1175 
1176 /*!
1177  * Add data to a protocol 2 message.
1178  * Use the length field (h->omsg[1]) as a pointer to the next free position.
1179  */
1180 static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
1181 {
1182  int x = h->omsg[1] + 2; /* Get current position */
1183  if (x == 2) {
1184  x += 2; /* First: skip Payload length (set later) */
1185  }
1186  h->omsg[x++] = msg; /* Message code */
1187  h->omsg[x++] = (unsigned char)size; /* Data size Low */
1188  h->omsg[x++] = 0; /* Data size Hi */
1189  for (; size > 0 ; size--) {
1190  h->omsg[x++] = *data++;
1191  }
1192  h->omsg[1] = x - 2; /* Frame size */
1193  h->omsg[2] = x - 4; /* Payload length (Lo) */
1194  h->omsg[3] = 0; /* Payload length (Hi) */
1195 }
1196 
1198 {
1199  adddata_proto2(h, 0x10, "\0", 1); /* Media Identifier > SMS */
1200  adddata_proto2(h, 0x11, "\0\0\0\0\0\0", 6); /* Firmware version */
1201  adddata_proto2(h, 0x12, "\2\0\4", 3); /* SMS provider ID */
1202  adddata_proto2(h, 0x13, h->udtxt, h->udl); /* Body */
1203 }
1204 
1205 static void sms_compose2(sms_t *h, int more)
1206 {
1207  struct ast_tm tm;
1208  struct timeval now = h->scts;
1209  char stm[9];
1210 
1211  h->omsg[0] = 0x00; /* set later... */
1212  h->omsg[1] = 0;
1214  if (h->smsc) { /* deliver */
1215  h->omsg[0] = 0x11; /* SMS_DELIVERY */
1216  /* Required: 10 11 12 13 14 15 17 (seems they must be ordered!) */
1217  ast_localtime(&now, &tm, NULL);
1218  sprintf(stm, "%02d%02d%02d%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min); /* Date mmddHHMM */
1219  adddata_proto2(h, 0x14, stm, 8); /* Date */
1220  if (*h->oa == 0) {
1221  strcpy(h->oa, "00000000");
1222  }
1223  adddata_proto2(h, 0x15, h->oa, strlen(h->oa)); /* Originator */
1224  adddata_proto2(h, 0x17, "\1", 1); /* Calling Terminal ID */
1225  } else { /* submit */
1226  h->omsg[0] = 0x10; /* SMS_SUBMIT */
1227  /* Required: 10 11 12 13 17 18 1B 1C (seems they must be ordered!) */
1228  adddata_proto2(h, 0x17, "\1", 1); /* Calling Terminal ID */
1229  if (*h->da == 0) {
1230  strcpy(h->da, "00000000");
1231  }
1232  adddata_proto2(h, 0x18, h->da, strlen(h->da)); /* Originator */
1233  adddata_proto2(h, 0x1B, "\1", 1); /* Called Terminal ID */
1234  adddata_proto2(h, 0x1C, "\0\0\0", 3); /* Notification */
1235  }
1236 }
1237 
1238 static void putdummydata_proto2(sms_t *h);
1239 
1240 #define MAX_DEBUG_LEN 300
1241 static char *sms_hexdump(unsigned char buf[], int size, char *s /* destination */)
1242 {
1243  char *p;
1244  int f;
1245 
1246  for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3) {
1247  sprintf(p, "%02X ", (unsigned)buf[f]);
1248  }
1249  return(s);
1250 }
1251 
1252 
1253 /*! \brief sms_handleincoming_proto2: handle the incoming message */
1255 {
1256  int f, i, sz = 0;
1257  int msg, msgsz;
1258  struct ast_tm tm;
1259  struct timeval now = { 0, 0 };
1260  char debug_buf[MAX_DEBUG_LEN * 3 + 1];
1261 
1262  sz = h->imsg[1] + 2;
1263  /* ast_verb(3, "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg, sz, debug_buf)); */
1264 
1265  /* Parse message body (called payload) */
1266  now = h->scts = ast_tvnow();
1267  for (f = 4; f < sz; ) {
1268  msg = h->imsg[f++];
1269  msgsz = h->imsg[f++];
1270  msgsz += (h->imsg[f++] * 256);
1271  switch (msg) {
1272  case 0x13: /* Body */
1273  ast_verb(3, "SMS-P2 Body#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
1274  if (msgsz >= sizeof(h->ud)) {
1275  msgsz = sizeof(h->ud) - 1;
1276  }
1277  for (i = 0; i < msgsz; i++) {
1278  h->ud[i] = h->imsg[f + i];
1279  }
1280  h->udl = msgsz;
1281  break;
1282  case 0x14: /* Date SCTS */
1283  now = h->scts = ast_tvnow();
1284  ast_localtime(&now, &tm, NULL);
1285  tm.tm_mon = ( (h->imsg[f] * 10) + h->imsg[f + 1] ) - 1;
1286  tm.tm_mday = ( (h->imsg[f + 2] * 10) + h->imsg[f + 3] );
1287  tm.tm_hour = ( (h->imsg[f + 4] * 10) + h->imsg[f + 5] );
1288  tm.tm_min = ( (h->imsg[f + 6] * 10) + h->imsg[f + 7] );
1289  tm.tm_sec = 0;
1290  h->scts = ast_mktime(&tm, NULL);
1291  ast_verb(3, "SMS-P2 Date#%02X=%02d/%02d %02d:%02d\n", (unsigned)msg, tm.tm_mday, tm.tm_mon + 1, tm.tm_hour, tm.tm_min);
1292  break;
1293  case 0x15: /* Calling line (from SMSC) */
1294  if (msgsz >= 20) {
1295  msgsz = 20 - 1;
1296  }
1297  ast_verb(3, "SMS-P2 Origin#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
1298  ast_copy_string(h->oa, (char *)(&h->imsg[f]), msgsz + 1);
1299  break;
1300  case 0x18: /* Destination(from TE/phone) */
1301  if (msgsz >= 20) {
1302  msgsz = 20 - 1;
1303  }
1304  ast_verb(3, "SMS-P2 Destination#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
1305  ast_copy_string(h->da, (char *)(&h->imsg[f]), msgsz + 1);
1306  break;
1307  case 0x1C: /* Notify */
1308  ast_verb(3, "SMS-P2 Notify#%02X=%s\n", (unsigned)msg, sms_hexdump(&h->imsg[f], 3, debug_buf));
1309  break;
1310  default:
1311  ast_verb(3, "SMS-P2 Par#%02X [%d]: %s\n", (unsigned)msg, msgsz, sms_hexdump(&h->imsg[f], msgsz, debug_buf));
1312  break;
1313  }
1314  f+=msgsz; /* Skip to next */
1315  }
1316  h->rx = 1; /* received message */
1317  sms_writefile(h); /* write the file */
1318  return 0; /* no error */
1319 }
1320 
1321 #if 0
1322 static void smssend(sms_t *h, char *c)
1323 {
1324  int f, x;
1325  for (f = 0; f < strlen(c); f++) {
1326  sscanf(&c[f*3], "%x", &x);
1327  h->omsg[f] = x;
1328  }
1329  sms_messagetx(h);
1330 }
1331 #endif
1332 
1333 static void sms_nextoutgoing (sms_t *h);
1334 
1335 static void sms_messagerx2(sms_t * h)
1336 {
1337  int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */
1338  int cause;
1339 
1340 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
1341  switch (p) {
1342  case DLL2_SMS_EST: /* Protocol 2: Connection ready (fake): send message */
1343  sms_nextoutgoing (h);
1344  /* smssend(h,"11 29 27 00 10 01 00 00 11 06 00 00 00 00 00 00 00 12 03 00 02 00 04 13 01 00 41 14 08 00 30 39 31 35 30 02 30 02 15 02 00 39 30 "); */
1345  break;
1346 
1347  case DLL2_SMS_INFO_MO: /* transport SMS_SUBMIT */
1348  case DLL2_SMS_INFO_MT: /* transport SMS_DELIVERY */
1349  cause = sms_handleincoming_proto2(h);
1350  if (!cause) { /* ACK */
1351  sms_log(h, 'Y');
1352  }
1353  h->omsg[0] = DLL2_ACK(h);
1354  h->omsg[1] = 0x06; /* msg len */
1355  h->omsg[2] = 0x04; /* payload len */
1356  h->omsg[3] = 0x00; /* payload len */
1357  h->omsg[4] = 0x1f; /* Response type */
1358  h->omsg[5] = 0x01; /* parameter len */
1359  h->omsg[6] = 0x00; /* parameter len */
1360  h->omsg[7] = cause; /* CONFIRM or error */
1361  sms_messagetx(h);
1362  break;
1363 
1364  case DLL2_SMS_NACK: /* Protocol 2: SMS_NAK */
1365  h->omsg[0] = DLL2_SMS_REL; /* SMS_REL */
1366  h->omsg[1] = 0x00; /* msg len */
1367  sms_messagetx(h);
1368  break;
1369 
1370  case DLL2_SMS_ACK0:
1371  case DLL2_SMS_ACK1:
1372  /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */
1373  if ( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
1374  /* a response to our Release, just hangup */
1375  h->hangup = 1; /* hangup */
1376  } else {
1377  /* XXX depending on what we are.. */
1378  ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY\n");
1379  sms_nextoutgoing (h);
1380  }
1381  break;
1382 
1383  case DLL2_SMS_REL: /* Protocol 2: SMS_REL (hangup req) */
1384  h->omsg[0] = DLL2_ACK(h);
1385  h->omsg[1] = 0;
1386  sms_messagetx(h);
1387  break;
1388  }
1389 }
1390 
1391 /*! \brief compose a message for protocol 1 */
1392 static void sms_compose1(sms_t *h, int more)
1393 {
1394  unsigned int p = 2; /* next byte to write. Skip type and len */
1395 
1396  h->omsg[0] = 0x91; /* SMS_DATA */
1397  if (h->smsc) { /* deliver */
1398  h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
1399  p += packaddress(h->omsg + p, h->oa);
1400  h->omsg[p++] = h->pid;
1401  h->omsg[p++] = h->dcs;
1402  packdate(h->omsg + p, h->scts.tv_sec);
1403  p += 7;
1404  p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
1405  } else { /* submit */
1406  h->omsg[p++] =
1407  0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
1408  if (h->mr < 0) {
1409  h->mr = message_ref++;
1410  }
1411  h->omsg[p++] = h->mr;
1412  p += packaddress(h->omsg + p, h->da);
1413  h->omsg[p++] = h->pid;
1414  h->omsg[p++] = h->dcs;
1415  if (h->vp) { /* relative VP */
1416  if (h->vp < 720) {
1417  h->omsg[p++] = (h->vp + 4) / 5 - 1;
1418  } else if (h->vp < 1440) {
1419  h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
1420  } else if (h->vp < 43200) {
1421  h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
1422  } else if (h->vp < 635040) {
1423  h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
1424  } else {
1425  h->omsg[p++] = 255; /* max */
1426  }
1427  }
1428  p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
1429  }
1430  h->omsg[1] = p - 2;
1431 }
1432 
1433 /*! \brief find and fill in next message, or send a REL if none waiting */
1434 static void sms_nextoutgoing (sms_t * h)
1435 {
1436  char fn[100 + NAME_MAX] = "";
1437  DIR *d;
1438  char more = 0;
1439 
1440  *h->da = *h->oa = '\0'; /* clear destinations */
1441  h->rx = 0; /* outgoing message */
1442  snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? "mttx" : "motx");
1443  ast_mkdir(fn, 0777); /* ensure it exists */
1444  d = opendir(fn);
1445  if (d) {
1446  struct dirent *f = readdirqueue(d, h->queue);
1447  if (f) {
1448  snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", f->d_name);
1449  sms_readfile(h, fn);
1450  if (readdirqueue(d, h->queue)) {
1451  more = 1; /* more to send */
1452  }
1453  }
1454  closedir(d);
1455  }
1456  if (*h->da || *h->oa) { /* message to send */
1457  if (h->protocol == 2) {
1458  sms_compose2(h, more);
1459  } else {
1460  sms_compose1(h, more);
1461  }
1462  } else { /* no message */
1463  if (h->protocol == 2) {
1464  h->omsg[0] = 0x17; /* SMS_REL */
1465  h->omsg[1] = 0;
1466  } else {
1467  h->omsg[0] = 0x94; /* SMS_REL */
1468  h->omsg[1] = 0;
1469  h->sent_rel = 1;
1470  }
1471  }
1472  sms_messagetx(h);
1473 }
1474 
1475 #define DIR_RX 1
1476 #define DIR_TX 2
1477 static void sms_debug (int dir, sms_t *h)
1478 {
1479  char txt[259 * 3 + 1];
1480  char *p = txt; /* always long enough */
1481  unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
1482  int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
1483  int q = 0;
1484  while (q < n && q < 30) {
1485  sprintf(p, " %02X", (unsigned)msg[q++]);
1486  p += 3;
1487  }
1488  if (q < n) {
1489  sprintf(p, "...");
1490  }
1491  ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
1492 }
1493 
1494 
1495 static void sms_messagerx(sms_t * h)
1496 {
1497  int cause;
1498 
1499  sms_debug (DIR_RX, h);
1500  if (h->protocol == 2) {
1501  sms_messagerx2(h);
1502  return;
1503  }
1504  /* parse incoming message for Protocol 1 */
1505  switch (h->imsg[0]) {
1506  case 0x91: /* SMS_DATA */
1507  cause = sms_handleincoming (h);
1508  if (!cause) {
1509  sms_log(h, 'Y');
1510  h->omsg[0] = 0x95; /* SMS_ACK */
1511  h->omsg[1] = 0x02;
1512  h->omsg[2] = 0x00; /* deliver report */
1513  h->omsg[3] = 0x00; /* no parameters */
1514  } else { /* NACK */
1515  sms_log(h, 'N');
1516  h->omsg[0] = 0x96; /* SMS_NACK */
1517  h->omsg[1] = 3;
1518  h->omsg[2] = 0; /* delivery report */
1519  h->omsg[3] = cause; /* cause */
1520  h->omsg[4] = 0; /* no parameters */
1521  }
1522  sms_messagetx(h);
1523  break;
1524 
1525  case 0x92: /* SMS_ERROR */
1526  h->err = 1;
1527  sms_messagetx(h); /* send whatever we sent again */
1528  break;
1529  case 0x93: /* SMS_EST */
1530  sms_nextoutgoing (h);
1531  break;
1532  case 0x94: /* SMS_REL */
1533  h->hangup = 1; /* hangup */
1534  break;
1535  case 0x95: /* SMS_ACK */
1536  sms_log(h, 'Y');
1537  sms_nextoutgoing (h);
1538  break;
1539  case 0x96: /* SMS_NACK */
1540  h->err = 1;
1541  sms_log(h, 'N');
1542  sms_nextoutgoing (h);
1543  break;
1544  default: /* Unknown */
1545  h->omsg[0] = 0x92; /* SMS_ERROR */
1546  h->omsg[1] = 1;
1547  h->omsg[2] = 3; /* unknown message type */
1548  sms_messagetx(h);
1549  break;
1550  }
1551 }
1552 
1553 static void sms_messagetx(sms_t * h)
1554 {
1555  unsigned char c = 0, p;
1556  int len = h->omsg[1] + 2; /* total message length excluding checksum */
1557 
1558  for (p = 0; p < len; p++) { /* compute checksum */
1559  c += h->omsg[p];
1560  }
1561  h->omsg[len] = 0 - c; /* actually, (256 - (c & 0fxx)) & 0xff) */
1562  sms_debug(DIR_TX, h);
1563  h->framenumber++; /* Proto 2 */
1564  h->obytep = 0;
1565  h->obitp = 0;
1566  if (h->protocol == 2) { /* Proto 2: */
1567  h->oseizure = 300; /* 300bits (or more ?) */
1568  h->obyte = 0; /* Seizure starts with space (0) */
1569  if (h->omsg[0] == 0x7F) {
1570  h->opause = 8 * h->opause_0; /* initial message delay */
1571  } else {
1572  h->opause = 400;
1573  }
1574  } else { /* Proto 1: */
1575  h->oseizure = 0; /* No seizure */
1576  h->obyte = 1; /* send mark ('1') at the beginning */
1577  /* Change the initial message delay. BT requires 300ms,
1578  * but for others this might be way too much and the phone
1579  * could time out. XXX make it configurable.
1580  */
1581  if (h->omsg[0] == 0x93) {
1582  h->opause = 8 * h->opause_0; /* initial message delay */
1583  } else {
1584  h->opause = 200;
1585  }
1586  }
1587  /* Note - setting osync triggers the generator */
1588  h->osync = OSYNC_BITS; /* 80 sync bits */
1589  h->obyten = len + 1; /* bytes to send (including checksum) */
1590 }
1591 
1592 /*!
1593  * outgoing data are produced by this generator function, that reads from
1594  * the descriptor whether it has data to send and which ones.
1595  */
1596 static int sms_generate(struct ast_channel *chan, void *data, int len, int samples)
1597 {
1598  struct ast_frame f = { 0 };
1599 #define MAXSAMPLES (800)
1600  output_t *buf;
1601  sms_t *h = data;
1602  int i;
1603 
1604  if (samples > MAXSAMPLES) {
1605  ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
1606  MAXSAMPLES, samples);
1607  samples = MAXSAMPLES;
1608  }
1609  len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET;
1610  buf = ast_alloca(len);
1611 
1613  f.subclass.codec = __OUT_FMT;
1614  f.datalen = samples * sizeof(*buf);
1616  f.mallocd = 0;
1617  f.data.ptr = buf;
1618  f.samples = samples;
1619  f.src = "app_sms";
1620  /* create a buffer containing the digital sms pattern */
1621  for (i = 0; i < samples; i++) {
1622  buf[i] = wave_out[0]; /* default is silence */
1623 
1624  if (h->opause) {
1625  h->opause--;
1626  } else if (h->obyten || h->osync) { /* sending data */
1627  buf[i] = wave_out[h->ophase];
1628  h->ophase += (h->obyte & 1) ? 13 : 21; /* compute next phase */
1629  if (h->ophase >= 80)
1630  h->ophase -= 80;
1631  if ((h->ophasep += 12) >= 80) { /* time to send the next bit */
1632  h->ophasep -= 80;
1633  if (h->oseizure > 0) { /* sending channel seizure (proto 2) */
1634  h->oseizure--;
1635  h->obyte ^= 1; /* toggle low bit */
1636  } else if (h->osync) {
1637  h->obyte = 1; /* send mark as sync bit */
1638  h->osync--; /* sending sync bits */
1639  if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
1640  h->obytep = h->obyten = 0; /* we are done */
1641  }
1642  } else {
1643  h->obitp++;
1644  if (h->obitp == 1) {
1645  h->obyte = 0; /* start bit; */
1646  } else if (h->obitp == 2) {
1647  h->obyte = h->omsg[h->obytep];
1648  } else if (h->obitp == 10) {
1649  h->obyte = 1; /* stop bit */
1650  h->obitp = 0;
1651  h->obytep++;
1652  if (h->obytep == h->obyten) {
1653  h->obytep = h->obyten = 0; /* sent */
1654  h->osync = 10; /* trailing marks */
1655  }
1656  } else {
1657  h->obyte >>= 1;
1658  }
1659  }
1660  }
1661  }
1662  }
1663  if (ast_write(chan, &f) < 0) {
1664  ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
1665  return -1;
1666  }
1667  return 0;
1668 #undef MAXSAMPLES
1669 }
1670 
1671 /*!
1672  * Just return the pointer to the descriptor that we received.
1673  */
1674 static void *sms_alloc(struct ast_channel *chan, void *sms_t_ptr)
1675 {
1676  return sms_t_ptr;
1677 }
1678 
1679 static void sms_release(struct ast_channel *chan, void *data)
1680 {
1681  return; /* nothing to do here. */
1682 }
1683 
1684 static struct ast_generator smsgen = {
1685  .alloc = sms_alloc,
1686  .release = sms_release,
1687  .generate = sms_generate,
1688 };
1689 
1690 /*!
1691  * Process an incoming frame, trying to detect the carrier and
1692  * decode the message. The two frequencies are 1300 and 2100 Hz.
1693  * The decoder detects the amplitude of the signal over the last
1694  * few samples, filtering the absolute values with a lowpass filter.
1695  * If the magnitude (h->imag) is large enough, multiply the signal
1696  * by the two carriers, and compute the amplitudes m0 and m1.
1697  * Record the current sample as '0' or '1' depending on which one is greater.
1698  * The last 3 bits are stored in h->ibith, with the count of '1'
1699  * bits in h->ibitt.
1700  * XXX the rest is to be determined.
1701  */
1702 static void sms_process(sms_t * h, int samples, signed short *data)
1703 {
1704  int bit;
1705 
1706  /*
1707  * Ignore incoming audio while a packet is being transmitted,
1708  * the protocol is half-duplex.
1709  * Unfortunately this means that if the outbound and incoming
1710  * transmission overlap (which is an error condition anyways),
1711  * we may miss some data and this makes debugging harder.
1712  */
1713  if (h->obyten || h->osync) {
1714  return;
1715  }
1716  for ( ; samples-- ; data++) {
1717  unsigned long long m0, m1;
1718  if (abs(*data) > h->imag) {
1719  h->imag = abs(*data);
1720  } else {
1721  h->imag = h->imag * 7 / 8;
1722  }
1723  if (h->imag <= 500) { /* below [arbitrary] threahold: lost carrier */
1724  if (h->idle++ == 80000) { /* nothing happening */
1725  ast_log(LOG_NOTICE, "No data, hanging up\n");
1726  h->hangup = 1;
1727  h->err = 1;
1728  }
1729  if (h->ierr) { /* error */
1730  ast_log(LOG_NOTICE, "Error %d, hanging up\n", h->ierr);
1731  /* Protocol 1 */
1732  h->err = 1;
1733  h->omsg[0] = 0x92; /* error */
1734  h->omsg[1] = 1;
1735  h->omsg[2] = h->ierr;
1736  sms_messagetx(h); /* send error */
1737  }
1738  h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1739  continue;
1740  }
1741  h->idle = 0;
1742 
1743  /* multiply signal by the two carriers. */
1744  h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
1745  h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
1746  h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
1747  h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
1748  /* compute the amplitudes */
1749  m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
1750  m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
1751 
1752  /* advance the sin/cos pointers */
1753  if ((h->ips0 += 21) >= 80) {
1754  h->ips0 -= 80;
1755  }
1756  if ((h->ipc0 += 21) >= 80) {
1757  h->ipc0 -= 80;
1758  }
1759  if ((h->ips1 += 13) >= 80) {
1760  h->ips1 -= 80;
1761  }
1762  if ((h->ipc1 += 13) >= 80) {
1763  h->ipc1 -= 80;
1764  }
1765 
1766  /* set new bit to 1 or 0 depending on which value is stronger */
1767  h->ibith <<= 1;
1768  if (m1 > m0) {
1769  h->ibith |= 1;
1770  }
1771  if (h->ibith & 8) {
1772  h->ibitt--;
1773  }
1774  if (h->ibith & 1) {
1775  h->ibitt++;
1776  }
1777  bit = ((h->ibitt > 1) ? 1 : 0);
1778  if (bit != h->ibitl) {
1779  h->ibitc = 1;
1780  } else {
1781  h->ibitc++;
1782  }
1783  h->ibitl = bit;
1784  if (!h->ibitn && h->ibitc == 4 && !bit) {
1785  h->ibitn = 1;
1786  h->iphasep = 0;
1787  }
1788  if (bit && h->ibitc == 200) { /* sync, restart message */
1789  /* Protocol 2: empty connection ready (I am master) */
1790  if (h->framenumber < 0 && h->ibytec >= 160 && !memcmp(h->imsg, "UUUUUUUUUUUUUUUUUUUU", 20)) {
1791  h->framenumber = 1;
1792  ast_verb(3, "SMS protocol 2 detected\n");
1793  h->protocol = 2;
1794  h->imsg[0] = 0xff; /* special message (fake) */
1795  h->imsg[1] = h->imsg[2] = 0x00;
1796  h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1797  sms_messagerx(h);
1798  }
1799  h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1800  }
1801  if (h->ibitn) {
1802  h->iphasep += 12;
1803  if (h->iphasep >= 80) { /* next bit */
1804  h->iphasep -= 80;
1805  if (h->ibitn++ == 9) { /* end of byte */
1806  if (!bit) { /* bad stop bit */
1807  if (h->sent_rel) {
1808  h->hangup = 1;
1809  } else {
1810  ast_log(LOG_NOTICE, "Bad stop bit\n");
1811  h->ierr = 0xFF; /* unknown error */
1812  }
1813  } else {
1814  if (h->ibytep < sizeof(h->imsg)) {
1815  h->imsg[h->ibytep] = h->ibytev;
1816  h->ibytec += h->ibytev;
1817  h->ibytep++;
1818  } else if (h->ibytep == sizeof(h->imsg)) {
1819  ast_log(LOG_NOTICE, "msg too large\n");
1820  h->ierr = 2; /* bad message length */
1821  }
1822  if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
1823  if (!h->ibytec) {
1824  sms_messagerx(h);
1825  } else {
1826  ast_log(LOG_NOTICE, "bad checksum\n");
1827  h->ierr = 1; /* bad checksum */
1828  }
1829  }
1830  }
1831  h->ibitn = 0;
1832  }
1833  h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
1834  }
1835  }
1836  }
1837 }
1838 
1839 /*
1840  * Standard argument parsing:
1841  * - one enum for the flags we recognise,
1842  * - one enum for argument indexes
1843  * - AST_APP_OPTIONS() to drive the parsing routine
1844  * - in the function, AST_DECLARE_APP_ARGS(...) for the arguments.
1845  */
1847  OPTION_BE_SMSC = (1 << 0), /* act as sms center */
1848  OPTION_ANSWER = (1 << 1), /* answer on incoming calls */
1849  OPTION_TWO = (1 << 2), /* Use Protocol Two */
1850  OPTION_PAUSE = (1 << 3), /* pause before sending data, in ms */
1851  OPTION_SRR = (1 << 4), /* set srr */
1852  OPTION_DCS = (1 << 5), /* set dcs */
1853 };
1854 
1858 };
1859 
1863  AST_APP_OPTION('t', OPTION_TWO),
1864  AST_APP_OPTION('r', OPTION_SRR),
1865  AST_APP_OPTION('o', OPTION_DCS),
1867  } );
1868 
1869 static int sms_exec(struct ast_channel *chan, const char *data)
1870 {
1871  int res = -1;
1872  sms_t h = { 0 };
1873  /* argument parsing support */
1874  struct ast_flags flags = { 0 };
1875  char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, };
1876  char *p;
1877  AST_DECLARE_APP_ARGS(sms_args,
1878  AST_APP_ARG(queue);
1879  AST_APP_ARG(options);
1880  AST_APP_ARG(addr);
1881  AST_APP_ARG(body);
1882  );
1883 
1884  if (!data) {
1885  ast_log(LOG_ERROR, "Requires queue name at least\n");
1886  return -1;
1887  }
1888 
1889  parse = ast_strdupa(data); /* create a local copy */
1890  AST_STANDARD_APP_ARGS(sms_args, parse);
1891  if (sms_args.argc > 1) {
1892  ast_app_parse_options(sms_options, &flags, sms_opts, sms_args.options);
1893  }
1894 
1895  ast_verb(1, "sms argc %u queue <%s> opts <%s> addr <%s> body <%s>\n",
1896  sms_args.argc, S_OR(sms_args.queue, ""),
1897  S_OR(sms_args.options, ""),
1898  S_OR(sms_args.addr, ""),
1899  S_OR(sms_args.body, "") );
1900 
1901  h.ipc0 = h.ipc1 = 20; /* phase for cosine */
1902  h.dcs = 0xF1; /* default */
1903 
1904  ast_copy_string(h.cli,
1905  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
1906  sizeof(h.cli));
1907 
1908  if (ast_strlen_zero(sms_args.queue)) {
1909  ast_log(LOG_ERROR, "Requires queue name\n");
1910  goto done;
1911  }
1912  if (strlen(sms_args.queue) >= sizeof(h.queue)) {
1913  ast_log(LOG_ERROR, "Queue name too long\n");
1914  goto done;
1915  }
1916  ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue));
1917 
1918  for (p = h.queue; *p; p++) {
1919  if (!isalnum(*p)) {
1920  *p = '-'; /* make very safe for filenames */
1921  }
1922  }
1923 
1924  h.smsc = ast_test_flag(&flags, OPTION_BE_SMSC);
1925  h.protocol = ast_test_flag(&flags, OPTION_TWO) ? 2 : 1;
1926  if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE])) {
1927  h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
1928  }
1929  if (h.opause_0 < 25 || h.opause_0 > 2000) {
1930  h.opause_0 = 300; /* default 300ms */
1931  }
1932  ast_verb(1, "initial delay %dms\n", h.opause_0);
1933 
1934 
1935  /* the following apply if there is an arg3/4 and apply to the created message file */
1936  if (ast_test_flag(&flags, OPTION_SRR)) {
1937  h.srr = 1;
1938  }
1939  if (ast_test_flag(&flags, OPTION_DCS)) {
1940  h.dcs = 1;
1941  }
1942 #if 0
1943  case '1':
1944  case '2':
1945  case '3':
1946  case '4':
1947  case '5':
1948  case '6':
1949  case '7': /* set the pid for saved local message */
1950  h.pid = 0x40 + (*d & 0xF);
1951  break;
1952  }
1953 #endif
1954  if (sms_args.argc > 2) {
1955  unsigned char *up;
1956 
1957  /* submitting a message, not taking call. */
1958  /* deprecated, use smsq instead */
1959  h.scts = ast_tvnow();
1960  if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) {
1961  ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr);
1962  goto done;
1963  }
1964  if (h.smsc) {
1965  ast_copy_string(h.oa, sms_args.addr, sizeof(h.oa));
1966  } else {
1967  ast_copy_string(h.da, sms_args.addr, sizeof(h.da));
1968  ast_copy_string(h.oa, h.cli, sizeof(h.oa));
1969  }
1970  h.udl = 0;
1971  if (ast_strlen_zero(sms_args.body)) {
1972  ast_log(LOG_ERROR, "Missing body for %s\n", sms_args.addr);
1973  goto done;
1974  }
1975  up = (unsigned char *)sms_args.body;
1976  while (*up && h.udl < SMSLEN) {
1977  h.ud[h.udl++] = utf8decode(&up);
1978  }
1979  if (is7bit(h.dcs) && packsms7(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1980  ast_log(LOG_WARNING, "Invalid 7 bit GSM data\n");
1981  goto done;
1982  }
1983  if (is8bit(h.dcs) && packsms8(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1984  ast_log(LOG_WARNING, "Invalid 8 bit data\n");
1985  goto done;
1986  }
1987  if (is16bit(h.dcs) && packsms16(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1988  ast_log(LOG_WARNING, "Invalid 16 bit data\n");
1989  goto done;
1990  }
1991  h.rx = 0; /* sent message */
1992  h.mr = -1;
1993  sms_writefile(&h);
1994  res = h.err;
1995  goto done;
1996  }
1997 
1998  if (chan->_state != AST_STATE_UP) { /* make sure channel is answered before any TX */
1999  ast_answer(chan);
2000  }
2001 
2003  h.framenumber = 1; /* Proto 2 */
2004  /* set up SMS_EST initial message */
2005  if (h.protocol == 2) {
2006  h.omsg[0] = DLL2_SMS_EST;
2007  h.omsg[1] = 0;
2008  } else {
2010  h.omsg[1] = 0;
2011  }
2012  sms_messagetx(&h);
2013  }
2014 
2015  res = ast_set_write_format(chan, __OUT_FMT);
2016  if (res >= 0) {
2018  }
2019  if (res < 0) {
2020  ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
2021  goto done;
2022  }
2023 
2024  if ( (res = ast_activate_generator(chan, &smsgen, &h)) < 0) {
2025  ast_log(LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
2026  goto done;
2027  }
2028 
2029  /* Do our thing here */
2030  for (;;) {
2031  struct ast_frame *f;
2032  int i = ast_waitfor(chan, -1);
2033  if (i < 0) {
2034  ast_log(LOG_NOTICE, "waitfor failed\n");
2035  break;
2036  }
2037  if (h.hangup) {
2038  ast_log(LOG_NOTICE, "channel hangup\n");
2039  break;
2040  }
2041  f = ast_read(chan);
2042  if (!f) {
2043  ast_log(LOG_NOTICE, "ast_read failed\n");
2044  break;
2045  }
2046  if (f->frametype == AST_FRAME_VOICE) {
2047  sms_process(&h, f->samples, f->data.ptr);
2048  }
2049 
2050  ast_frfree(f);
2051  }
2052  res = h.err; /* XXX */
2053 
2054  /*
2055  * The SMS generator data is on the stack. We _MUST_ make sure the generator
2056  * is stopped before returning from this function.
2057  */
2059 
2060  sms_log(&h, '?'); /* log incomplete message */
2061 done:
2062  return (res);
2063 }
2064 
2065 static int unload_module(void)
2066 {
2067  return ast_unregister_application(app);
2068 }
2069 
2070 static int load_module(void)
2071 {
2072 #ifdef OUTALAW
2073  int p;
2074  for (p = 0; p < 80; p++) {
2075  wavea[p] = AST_LIN2A(wave[p]);
2076  }
2077 #endif
2078  snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR);
2080 }
2081 
#define is7bit(dcs)
Definition: app_sms.c:278
A-Law to Signed linear conversion.
union ast_frame_subclass subclass
Definition: frame.h:146
static void sms_messagerx(sms_t *h)
Definition: app_sms.c:1495
static void sms_messagetx(sms_t *h)
Definition: app_sms.c:1553
Main Channel structure associated with a channel.
Definition: channel.h:742
static char * app
Definition: app_sms.c:122
static int load_module(void)
Definition: app_sms.c:2070
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
Definition: app.h:732
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
unsigned char hangup
Definition: app_sms.c:217
unsigned char ipc1
Definition: app_sms.c:257
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
Definition: app.h:712
int offset
Definition: frame.h:156
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int opause_0
Definition: app_sms.c:270
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
unsigned int vp
Definition: app_sms.c:234
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
Definition: channel.c:3148
static long utf8decode(unsigned char **pp)
Reads next UCS character from NUL terminated UTF-8 string and advance pointer.
Definition: app_sms.c:312
void * ptr
Definition: frame.h:160
unsigned char obyten
Definition: app_sms.c:245
#define SMSLEN
Definition: app_sms.c:213
unsigned char ophase
Definition: app_sms.c:238
int udhl
Definition: app_sms.c:230
unsigned char ipc0
Definition: app_sms.c:256
#define LOG_WARNING
Definition: logger.h:144
unsigned char rx
Definition: app_sms.c:221
unsigned char obitp
Definition: app_sms.c:242
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
static void packdate(unsigned char *o, time_t w)
pack a date and return
Definition: app_sms.c:550
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
unsigned int flags
Definition: utils.h:201
static unsigned char packaddress(unsigned char *o, char *i)
store an address at o, and return number of bytes used
Definition: app_sms.c:743
static int sms_handleincoming_proto2(sms_t *h)
sms_handleincoming_proto2: handle the incoming message
Definition: app_sms.c:1254
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
static void sms_compose1(sms_t *h, int more)
compose a message for protocol 1
Definition: app_sms.c:1392
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
unsigned char ibitl
Definition: app_sms.c:258
static void sms_debug(int dir, sms_t *h)
Definition: app_sms.c:1477
unsigned char ibytep
Definition: app_sms.c:263
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
static int sms_exec(struct ast_channel *chan, const char *data)
Definition: app_sms.c:1869
unsigned char osync
Definition: app_sms.c:243
static unsigned char unpackaddress(char *o, unsigned char *i)
unpack an address from i, return byte length, unpack to o
Definition: app_sms.c:725
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
format_t codec
Definition: frame.h:137
#define S(e)
unsigned char imsg[250]
Definition: app_sms.c:247
Definition: app_sms.c:216
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
#define AST_FILE_MODE
Definition: asterisk.h:36
int tm_year
Definition: localtime.h:41
unsigned char udhi
Definition: app_sms.c:232
#define ast_verb(level,...)
Definition: logger.h:243
unsigned int idle
Definition: app_sms.c:252
signed long long imc0
Definition: app_sms.c:248
struct timeval scts
Definition: app_sms.c:225
unsigned char omsg[256]
Definition: app_sms.c:246
static void sms_readfile(sms_t *h, char *fn)
parse and delete a file
Definition: app_sms.c:819
Utility functions.
static void sms_process(sms_t *h, int samples, signed short *data)
Definition: app_sms.c:1702
message_types
Definition: app_sms.c:159
#define OSYNC_BITS
Definition: app_sms.c:150
static int sms_generate(struct ast_channel *chan, void *data, int len, int samples)
Definition: app_sms.c:1596
static void unpacksms8(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
unpacks bytes (8 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl...
Definition: app_sms.c:655
unsigned char ibytev
Definition: app_sms.c:262
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
unsigned char ibitt
Definition: app_sms.c:267
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define DIR_RX
Definition: app_sms.c:1475
static struct dirent * readdirqueue(DIR *d, char *queue)
read dir skipping dot files...
Definition: app_sms.c:1094
static volatile unsigned char message_ref
Definition: app_sms.c:117
static void sms_compose2(sms_t *h, int more)
Definition: app_sms.c:1205
General Asterisk PBX channel definitions.
char queue[30]
Definition: app_sms.c:222
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
Asterisk file paths, configured in asterisk.conf.
const char * src
Definition: frame.h:158
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define SMSLEN_8
Definition: app_sms.c:214
static int packsms16(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o ...
Definition: app_sms.c:482
int datalen
Definition: frame.h:148
static char * isodate(time_t t, char *buf, int len)
static, return a date/time in ISO format
Definition: app_sms.c:300
int tm_mon
Definition: localtime.h:40
unsigned char ips0
Definition: app_sms.c:254
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
static void unpacksms16(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
unpacks bytes (16 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl...
Definition: app_sms.c:681
unsigned char srr
Definition: app_sms.c:231
struct sms_s sms_t
unsigned char obyte
Definition: app_sms.c:240
static void sms_release(struct ast_channel *chan, void *data)
Definition: app_sms.c:1679
static const signed short wave[]
Definition: app_sms.c:130
static void * sms_alloc(struct ast_channel *chan, void *sms_t_ptr)
Definition: app_sms.c:1674
static const output_t * wave_out
Definition: app_sms.c:146
signed long long imc1
Definition: app_sms.c:248
int tm_mday
Definition: localtime.h:39
static void sms_writefile(sms_t *h)
white a received text message to a file
Definition: app_sms.c:990
unsigned char smsc
Definition: app_sms.c:220
unsigned short imag
Definition: app_sms.c:253
Core PBX routines and definitions.
static char log_file[255]
Definition: app_sms.c:120
signed short output_t
Definition: app_sms.c:145
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static const unsigned short defaultalphabet[]
Definition: app_sms.c:189
#define LOG_ERROR
Definition: logger.h:155
int framenumber
Definition: app_sms.c:273
unsigned char ierr
Definition: app_sms.c:265
unsigned char rp
Definition: app_sms.c:233
unsigned char ophasep
Definition: app_sms.c:239
#define is16bit(dcs)
Definition: app_sms.c:280
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define DIR_TX
Definition: app_sms.c:1476
unsigned char ibitc
Definition: app_sms.c:259
const ast_string_field name
Definition: channel.h:787
#define DLL2_ACK(h)
char cli[20]
Definition: app_sms.c:237
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_app_option sms_options[128]
Definition: app_sms.c:1867
static struct ast_generator smsgen
Definition: app_sms.c:1684
unsigned char obytep
Definition: app_sms.c:244
unsigned short ud[SMSLEN]
Definition: app_sms.c:235
#define __OUT_FMT
Definition: app_sms.c:147
while(yyssp!=yyss)
Definition: ast_expr2.c:2538
short mr
Definition: app_sms.c:228
#define LOG_NOTICE
Definition: logger.h:133
int oseizure
Definition: app_sms.c:272
const char * ast_config_AST_LOG_DIR
Definition: asterisk.c:263
static char * sms_hexdump(unsigned char buf[], int size, char *s)
Definition: app_sms.c:1241
static int unpacksms(unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
general unpack - starts with length byte (octet or septet) and returns number of bytes used...
Definition: app_sms.c:709
long int tm_gmtoff
Definition: localtime.h:45
void *(* alloc)(struct ast_channel *chan, void *params)
Definition: channel.h:180
int errno
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static int packsms(unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
general pack, with length and data, returns number of bytes of target used
Definition: app_sms.c:517
static void sms_log(sms_t *h, char status)
Log the output, and remove file.
Definition: app_sms.c:771
sms_opt_args
Definition: app_sms.c:1855
sms_flags
Definition: app_sms.c:1846
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
char udtxt[SMSLEN]
Definition: app_sms.c:274
const char * ast_config_AST_SPOOL_DIR
Definition: asterisk.c:259
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2351
int tm_hour
Definition: localtime.h:38
static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
Definition: app_sms.c:1180
Structure used to handle boolean flags.
Definition: utils.h:200
static void sms_messagerx2(sms_t *h)
Definition: app_sms.c:1335
int mallocd
Definition: frame.h:152
#define MAX_DEBUG_LEN
Definition: app_sms.c:1240
int tm_sec
Definition: localtime.h:36
int udl
Definition: app_sms.c:229
void ast_deactivate_generator(struct ast_channel *chan)
Definition: channel.c:3107
unsigned char err
Definition: app_sms.c:218
static volatile unsigned int seq
Definition: app_sms.c:118
unsigned char ibytec
Definition: app_sms.c:264
static struct timeval unpackdate(unsigned char *i)
unpack a date and return
Definition: app_sms.c:576
static int packsms7(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o ...
Definition: app_sms.c:366
static int unload_module(void)
Definition: app_sms.c:2065
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
char da[20]
Definition: app_sms.c:224
unsigned char dcs
Definition: app_sms.c:227
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2185
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
unsigned char ibith
Definition: app_sms.c:266
int tm_isdst
Definition: localtime.h:44
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
unsigned int opause
Definition: app_sms.c:241
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static int packsms8(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o ...
Definition: app_sms.c:443
Data structure associated with a single frame of data.
Definition: frame.h:142
unsigned char ips1
Definition: app_sms.c:255
char oa[20]
Definition: app_sms.c:223
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static void unpacksms7(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
unpacks bytes (7 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl...
Definition: app_sms.c:599
static void putdummydata_proto2(sms_t *h)
Definition: app_sms.c:1197
unsigned char sent_rel
Definition: app_sms.c:219
unsigned char iphasep
Definition: app_sms.c:260
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
#define MAXSAMPLES
union ast_frame::@172 data
signed long long ims0
Definition: app_sms.c:248
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
static void numcpy(char *d, char *s)
copy number, skipping non digits apart from leading +
Definition: app_sms.c:285
#define is8bit(dcs)
Definition: app_sms.c:279
unsigned char pid
Definition: app_sms.c:226
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
int protocol
Definition: app_sms.c:271
int tm_min
Definition: localtime.h:37
unsigned char ibitn
Definition: app_sms.c:261
jack_status_t status
Definition: app_jack.c:143
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int samples
Definition: frame.h:150
static void sms_nextoutgoing(sms_t *h)
find and fill in next message, or send a REL if none waiting
Definition: app_sms.c:1434
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
Definition: app.h:721
#define AST_LIN2A(a)
Definition: alaw.h:50
static const unsigned short escapes[]
Definition: app_sms.c:202
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2151
static unsigned char sms_handleincoming(sms_t *h)
handle the incoming message
Definition: app_sms.c:1104
unsigned char udh[SMSLEN]
Definition: app_sms.c:236
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
signed long long ims1
Definition: app_sms.c:248