401d20fea36ee7fc349b79dafa82037c39b53d77
[asterisk/asterisk.git] / apps / app_sms.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * SMS application - ETSI ES 201 912 protocol 1 implimentation
5  * 
6  * Copyright (C) 2004 - 2005, Adrian Kennard, rights assigned to Digium
7  *
8  * This program is free software, distributed under the terms of
9  * the GNU General Public License
10  */
11
12 #include "asterisk/lock.h"
13 #include "asterisk/file.h"
14 #include "asterisk/logger.h"
15 #include "asterisk/options.h"
16 #include "asterisk/channel.h"
17 #include "asterisk/pbx.h"
18 #include "asterisk/module.h"
19 #include "asterisk/alaw.h"
20 #include "asterisk/callerid.h"
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <dirent.h>
29 #include <ctype.h>
30 #include "astconf.h"
31
32 /* output using Alaw rather than linear */
33 /*#define OUTALAW */
34
35 /* ToDo */
36 /* Add full VP support */
37 /* Handle status report messages (generation and reception) */
38 /* Time zones on time stamps */
39 /* user ref field */
40
41 static volatile unsigned char message_ref;      /* arbitary message ref */
42 static volatile unsigned int seq;       /* arbitrary message sequence number for unqiue files */
43
44 static char log_file[255];
45 static char spool_dir[255];
46
47 static char *tdesc = "SMS/PSTN handler";
48
49 static char *app = "SMS";
50
51 static char *synopsis = "Communicates with SMS service centres and SMS capable analogue phones";
52
53 static char *descrip =
54    "  SMS(name|[a][s]):  SMS handles exchange of SMS data with a call to/from SMS capabale\n"
55    "phone or SMS PSTN service centre. Can send and/or receive SMS messages.\n"
56    "Returns 0 if call handled correctly, or -1 if there were any problems.\n"
57    "Works to ETSI ES 201 912 compatible with BT SMS PSTN service in UK\n"
58    "Typical usage is to use to handle called from the SMS service centre CLI,\n"
59    "or to set up a call using 'outgoing' or manager interface to connect service centre to SMS()\n"
60    "name is the name of the queue used in /var/spool/asterisk/sms\n"
61    "Argument 'a' means answer, i.e. send initial FSK packet.\n"
62    "Argument 's' means act as service centre talking to a phone.\n"
63    "Messages are processed as per text file message queues.\n" "smsq is a command to generate message queues and send messages.\n";
64
65 static signed short wave[] =
66    { 0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
67    5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
68    0, -392, -782, -1167,
69    -1545, -1913, -2270, -2612, -2939, -3247, -3536, -3802, -4045, -4263, -4455, -4619, -4755, -4862, -4938, -4985, -5000,
70    -4985, -4938, -4862,
71    -4755, -4619, -4455, -4263, -4045, -3802, -3536, -3247, -2939, -2612, -2270, -1913, -1545, -1167, -782, -392
72 };
73
74 #ifdef OUTALAW
75 static unsigned char wavea[80];
76 #endif
77
78 STANDARD_LOCAL_USER;
79
80 LOCAL_USER_DECL;
81
82 /* SMS 7 bit character mapping to UCS-2 */
83 static const unsigned short defaultalphabet[] = {
84    0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
85    0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
86    0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
87    0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
88    ' ', '!', '"', '#', 164, '%', '&', 39, '(', ')', '*', '+', ',', '-', '.', '/',
89    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
90    161, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
91    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 196, 214, 209, 220, 167,
92    191, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
93    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 228, 246, 241, 252, 224,
94 };
95
96 static const unsigned short escapes[] = {
97    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x000C, 0, 0, 0, 0, 0,
98    0, 0, 0, 0, 0x005E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99    0, 0, 0, 0, 0, 0, 0, 0, 0x007B, 0x007D, 0, 0, 0, 0, 0, 0x005C,
100    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x005B, 0x007E, 0x005D, 0,
101    0x007C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103    0, 0, 0, 0, 0, 0x20AC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 };
106
107 #define SMSLEN 160              /* max SMS length */
108
109 typedef struct sms_s
110 {
111    unsigned char hangup;        /* we are done... */
112    unsigned char err;           /* set for any errors */
113    unsigned char smsc:1;        /* we are SMSC */
114    unsigned char rx:1;          /* this is a received message */
115    char queue[30];              /* queue name */
116    char oa[20];                 /* originating address */
117    char da[20];                 /* destination address */
118    time_t scts;                 /* time stamp, UTC */
119    unsigned char pid;           /* protocol ID */
120    unsigned char dcs;           /* data coding scheme */
121    short mr;                    /* message reference - actually a byte, but usde -1 for not set */
122    int udl;                     /* user data length */
123    int udhl;                    /* user data header length */
124    unsigned char srr:1;         /* Status Report request */
125    unsigned char udhi:1;        /* User Data Header required, even if length 0 */
126    unsigned char rp:1;          /* Reply Path */
127    unsigned int vp;             /* validity period in minutes, 0 for not set */
128    unsigned short ud[SMSLEN];   /* user data (message), UCS-2 coded */
129    unsigned char udh[SMSLEN];   /* user data header */
130    unsigned char cli[20];       /* caller ID */
131    unsigned char ophase;        /* phase (0-79) for 0 and 1 frequencies (1300Hz and 2100Hz) */
132    unsigned char ophasep;       /* phase (0-79) for 1200 bps */
133    unsigned char obyte;         /* byte being sent */
134    unsigned int opause;         /* silent pause before sending (in sample periods) */
135    unsigned char obitp;         /* bit in byte */
136    unsigned char osync;         /* sync bits to send */
137    unsigned char obytep;        /* byte in data */
138    unsigned char obyten;        /* bytes in data */
139    unsigned char omsg[256];     /* data buffer (out) */
140    unsigned char imsg[200];     /* data buffer (in) */
141    signed long long ims0,
142      imc0,
143      ims1,
144      imc1;                      /* magnitude averages sin/cos 0/1 */
145    unsigned int idle;
146    unsigned short imag;         /* signal level */
147    unsigned char ips0,
148      ips1,
149      ipc0,
150      ipc1;                      /* phase sin/cos 0/1 */
151    unsigned char ibitl;         /* last bit */
152    unsigned char ibitc;         /* bit run length count */
153    unsigned char iphasep;       /* bit phase (0-79) for 1200 bps */
154    unsigned char ibitn;         /* bit number in byte being received */
155    unsigned char ibytev;        /* byte value being received */
156    unsigned char ibytep;        /* byte pointer in messafe */
157    unsigned char ibytec;        /* byte checksum for message */
158    unsigned char ierr;          /* error flag */
159    unsigned char ibith;         /* history of last bits */
160    unsigned char ibitt;         /* total of 1's in last 3 bites */
161    /* more to go here */
162 } sms_t;
163
164 /* different types of encoding */
165 #define is7bit(dcs) (((dcs)&0xC0)?(!((dcs)&4)):(!((dcs)&12)))
166 #define is8bit(dcs) (((dcs)&0xC0)?(((dcs)&4)):(((dcs)&12)==4))
167 #define is16bit(dcs) (((dcs)&0xC0)?0:(((dcs)&12)==8))
168
169 static void *
170 sms_alloc (struct ast_channel *chan, void *params)
171 {
172    return params;
173 }
174
175 static void
176 sms_release (struct ast_channel *chan, void *data)
177 {
178    return;
179 }
180
181 static void sms_messagetx (sms_t * h);
182
183 /* copy number, skipping non digits apart from leading + */
184 static void
185 numcpy (char *d, char *s)
186 {
187    if (*s == '+')
188       *d++ = *s++;
189    while (*s)
190    {
191       if (isdigit (*s))
192          *d++ = *s;
193       s++;
194    }
195    *d = 0;
196 }
197
198 static char *
199 isodate (time_t t)
200 {                               /* static, return a date/time in ISO format */
201    static char date[20];
202    strftime (date, sizeof (date), "%Y-%m-%dT%H:%M:%S", localtime (&t));
203    return date;
204 }
205
206 /* reads next UCS character from null terminated UTF-8 string and advanced pointer */
207 /* for non valid UTF-8 sequences, returns character as is */
208 /* Does not advance pointer for null termination */
209 static long
210 utf8decode (unsigned char **pp)
211 {
212    unsigned char *p = *pp;
213    if (!*p)
214       return 0;                 /* null termination of string */
215    (*pp)++;
216    if (*p < 0xC0)
217       return *p;                /* ascii or continuation character */
218    if (*p < 0xE0)
219    {
220       if (*p < 0xC2 || (p[1] & 0xC0) != 0x80)
221          return *p;             /* not valid UTF-8 */
222       (*pp)++;
223       return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
224    }
225    if (*p < 0xF0)
226    {
227       if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80)
228          return *p;             /* not valid UTF-8 */
229       (*pp) += 2;
230       return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
231    }
232    if (*p < 0xF8)
233    {
234       if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80)
235          return *p;             /* not valid UTF-8 */
236       (*pp) += 3;
237       return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
238    }
239    if (*p < 0xFC)
240    {
241       if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
242           || (p[4] & 0xC0) != 0x80)
243          return *p;             /* not valid UTF-8 */
244       (*pp) += 4;
245       return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
246    }
247    if (*p < 0xFE)
248    {
249       if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
250           || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80)
251          return *p;             /* not valid UTF-8 */
252       (*pp) += 5;
253       return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) +
254          (p[5] & 0x3F);
255    }
256    return *p;                   /* not sensible */
257 }
258
259 /* This 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 */
260 /* The return value is the number of septets packed in to o, which is internally limited to SMSLEN */
261 /* o can be null, in which case this is used to validate or count only */
262 /* if the input contains invalid characters then the return value is -1 */
263 static int
264 packsms7 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
265 {
266    unsigned char p = 0,
267       b = 0,
268       n = 0;
269    if (udhl)
270    {                            /* header */
271       if (o)
272          o[p++] = udhl;
273       b = 1;
274       n = 1;
275       while (udhl--)
276       {
277          if (o)
278             o[p++] = *udh++;
279          b += 8;
280          while (b >= 7)
281          {
282             b -= 7;
283             n++;
284          }
285          if (n >= SMSLEN)
286             return n;
287       }
288       if (b)
289       {
290          b = 7 - b;
291          if (++n >= SMSLEN)
292             return n;
293       };                        /* filling to septet boundary */
294    }
295    if (o)
296       o[p] = 0;
297    /* message */
298    while (udl--)
299    {
300       long u;
301       unsigned char v;
302       u = *ud++;
303       for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
304       if (v == 128 && u && n + 1 < SMSLEN)
305       {
306          for (v = 0; v < 128 && escapes[v] != u; v++);
307          if (v < 128)
308          {                      /* escaped sequence */
309             if (o)
310                o[p] |= (27 << b);
311             b += 7;
312             if (b >= 8)
313             {
314                b -= 8;
315                p++;
316                if (o)
317                   o[p] = (27 >> (7 - b));
318             }
319             n++;
320          }
321       }
322       if (v == 128)
323          return -1;             /* invalid character */
324       if (o)
325          o[p] |= (v << b);
326       b += 7;
327       if (b >= 8)
328       {
329          b -= 8;
330          p++;
331          if (o)
332             o[p] = (v >> (7 - b));
333       }
334       if (++n >= SMSLEN)
335          return n;
336    }
337    return n;
338 }
339
340 /* This 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 */
341 /* The return value is the number of bytes packed in to o, which is internally limited to 140 */
342 /* o can be null, in which case this is used to validate or count only */
343 /* if the input contains invalid characters then the return value is -1 */
344 static int
345 packsms8 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
346 {
347    unsigned char p = 0;
348    /* header - no encoding */
349    if (udhl)
350    {
351       if (o)
352          o[p++] = udhl;
353       while (udhl--)
354       {
355          if (o)
356             o[p++] = *udh++;
357          if (p >= 140)
358             return p;
359       }
360    }
361    while (udl--)
362    {
363       long u;
364       u = *ud++;
365       if (u < 0 || u > 0xFF)
366          return -1;             /* not valid */
367       if (o)
368          o[p++] = u;
369       if (p >= 140)
370          return p;
371    }
372    return p;
373 }
374
375 /* This 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 */
376 /* The return value is the number of bytes packed in to o, which is internally limited to 140 */
377 /* o can be null, in which case this is used to validate or count only */
378 /* if the input contains invalid characters then the return value is -1 */
379 static int
380 packsms16 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
381 {
382    unsigned char p = 0;
383    /* header - no encoding */
384    if (udhl)
385    {
386       if (o)
387          o[p++] = udhl;
388       while (udhl--)
389       {
390          if (o)
391             o[p++] = *udh++;
392          if (p >= 140)
393             return p;
394       }
395    }
396    while (udl--)
397    {
398       long u;
399       u = *ud++;
400       if (o)
401          o[p++] = (u >> 8);
402       if (p >= 140)
403          return p - 1;          /* could not fit last character */
404       if (o)
405          o[p++] = u;
406       if (p >= 140)
407          return p;
408    }
409    return p;
410 }
411
412 /* general pack, with length and data, returns number of bytes of target used */
413 static int
414 packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
415 {
416    unsigned char *p = base;
417    if (udl)
418    {
419       int l = 0;
420       if (is7bit (dcs))
421       {                         /* 7 bit */
422          l = packsms7 (p + 1, udhl, udh, udl, ud);
423          if (l < 0)
424             l = 0;
425          *p++ = l;
426          p += (l * 7 + 7) / 8;
427       } else if (is8bit (dcs))
428       {                         /* 8 bit */
429          l = packsms8 (p + 1, udhl, udh, udl, ud);
430          if (l < 0)
431             l = 0;
432          *p++ = l;
433          p += l;
434       } else
435       {                         /* UCS-2 */
436          l = packsms16 (p + 1, udhl, udh, udl, ud);
437          if (l < 0)
438             l = 0;
439          *p++ = l;
440          p += l;
441       }
442    } else
443       *p++ = 0;                 /* no user data */
444    return p - base;
445 }
446
447
448 /* pack a date and return */
449 static void
450 packdate (unsigned char *o, time_t w)
451 {
452    struct tm *t = localtime (&w);
453 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
454    int z = -t->tm_gmtoff / 60 / 15;
455 #else
456    int z = timezone / 60 / 15;
457 #endif
458    *o++ = ((t->tm_year % 10) << 4) + (t->tm_year % 100) / 10;
459    *o++ = (((t->tm_mon + 1) % 10) << 4) + (t->tm_mon + 1) / 10;
460    *o++ = ((t->tm_mday % 10) << 4) + t->tm_mday / 10;
461    *o++ = ((t->tm_hour % 10) << 4) + t->tm_hour / 10;
462    *o++ = ((t->tm_min % 10) << 4) + t->tm_min / 10;
463    *o++ = ((t->tm_sec % 10) << 4) + t->tm_sec / 10;
464    if (z < 0)
465       *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
466    else
467       *o++ = ((z % 10) << 4) + z / 10;
468 }
469
470 /* unpack a date and return */
471 static time_t
472 unpackdate (unsigned char *i)
473 {
474    struct tm t;
475    t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
476    t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
477    t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
478    t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
479    t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
480    t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
481    t.tm_isdst = 0;
482    if (i[6] & 0x08)
483       t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
484    else
485       t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
486    return mktime (&t);
487 }
488
489 /* 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 */
490 static void
491 unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
492 {
493    unsigned char b = 0,
494       p = 0;
495    unsigned short *o = ud;
496    *udhl = 0;
497    if (udhi && l)
498    {                            /* header */
499       int h = i[p];
500       *udhl = h;
501       if (h)
502       {
503          b = 1;
504          p++;
505          l--;
506          while (h-- && l)
507          {
508             *udh++ = i[p++];
509             b += 8;
510             while (b >= 7)
511             {
512                b -= 7;
513                l--;
514                if (!l)
515                   break;
516             }
517          }
518          /* adjust for fill, septets */
519          if (b)
520          {
521             b = 7 - b;
522             l--;
523          }
524       }
525    }
526    while (l--)
527    {
528       unsigned char v;
529       if (b < 2)
530          v = ((i[p] >> b) & 0x7F);
531       else
532          v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
533       b += 7;
534       if (b >= 8)
535       {
536          b -= 8;
537          p++;
538       }
539       if (o > ud && o[-1] == 0x00A0 && escapes[v])
540          o[-1] = escapes[v];
541       else
542          *o++ = defaultalphabet[v];
543    }
544    *udl = (o - ud);
545 }
546
547 /* 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 */
548 static void
549 unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
550 {
551    unsigned short *o = ud;
552    *udhl = 0;
553    if (udhi)
554    {
555       int n = *i;
556       *udhl = n;
557       if (n)
558       {
559          i++;
560          l--;
561          while (l && n)
562          {
563             l--;
564             n--;
565             *udh++ = *i++;
566          }
567       }
568    }
569    while (l--)
570       *o++ = *i++;              /* not to UTF-8 as explicitely 8 bit coding in DCS */
571    *udl = (o - ud);
572 }
573
574 /* 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 */
575 static void
576 unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
577 {
578    unsigned short *o = ud;
579    *udhl = 0;
580    if (udhi)
581    {
582       int n = *i;
583       *udhl = n;
584       if (n)
585       {
586          i++;
587          l--;
588          while (l && n)
589          {
590             l--;
591             n--;
592             *udh++ = *i++;
593          }
594       }
595    }
596    while (l--)
597    {
598       int v = *i++;
599       if (l--)
600          v = (v << 8) + *i++;
601       *o++ = v;
602    }
603    *udl = (o - ud);
604 }
605
606 /* general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length */
607 static int
608 unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
609 {
610    int l = *i++;
611    if (is7bit (dcs))
612    {
613       unpacksms7 (i, l, udh, udhl, ud, udl, udhi);
614       l = (l * 7 + 7) / 8;      /* adjust length to return */
615    } else if (is8bit (dcs))
616       unpacksms8 (i, l, udh, udhl, ud, udl, udhi);
617    else
618       unpacksms16 (i, l, udh, udhl, ud, udl, udhi);
619    return l + 1;
620 }
621
622 /* unpack an address from i, return byte length, unpack to o */
623 static unsigned char
624 unpackaddress (char *o, unsigned char *i)
625 {
626    unsigned char l = i[0],
627       p;
628    if (i[1] == 0x91)
629       *o++ = '+';
630    for (p = 0; p < l; p++)
631    {
632       if (p & 1)
633          *o++ = (i[2 + p / 2] >> 4) + '0';
634       else
635          *o++ = (i[2 + p / 2] & 0xF) + '0';
636    }
637    *o = 0;
638    return (l + 5) / 2;
639 }
640
641 /* store an address at o, and return number of bytes used */
642 static unsigned char
643 packaddress (unsigned char *o, char *i)
644 {
645    unsigned char p = 2;
646    o[0] = 0;
647    if (*i == '+')
648    {
649       i++;
650       o[1] = 0x91;
651    } else
652       o[1] = 0x81;
653    while (*i)
654       if (isdigit (*i))
655       {
656          if (o[0] & 1)
657             o[p++] |= ((*i & 0xF) << 4);
658          else
659             o[p] = (*i & 0xF);
660          o[0]++;
661          i++;
662       } else
663          i++;
664    if (o[0] & 1)
665       o[p++] |= 0xF0;           /* pad */
666    return p;
667 }
668
669 static void
670 sms_log (sms_t * h, char status)
671 {                               /* log the output, and remove file */
672    if (*h->oa || *h->da)
673    {
674       int o = open (log_file, O_CREAT | O_APPEND | O_WRONLY, 0666);
675       if (o >= 0)
676       {
677          char line[1000],
678            mrs[3] = "",
679             *p;
680          unsigned char n;
681          if (h->mr >= 0)
682             snprintf (mrs, sizeof (mrs), "%02X", h->mr);
683          snprintf (line, sizeof (line), "%s %c%c%c%s %s %s %s ",
684                    isodate (time (0)), status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue, *h->oa ? h->oa : "-",
685                    *h->da ? h->da : "-");
686          p = line + strlen (line);
687          for (n = 0; n < h->udl; n++)
688             if (h->ud[n] == '\\')
689             {
690                *p++ = '\\';
691                *p++ = '\\';
692             } else if (h->ud[n] == '\n')
693             {
694                *p++ = '\\';
695                *p++ = 'n';
696             } else if (h->ud[n] == '\r')
697             {
698                *p++ = '\\';
699                *p++ = 'r';
700             } else if (h->ud[n] < 32 || h->ud[n] == 127)
701                *p++ = 191;
702             else
703                *p++ = h->ud[n];
704          *p++ = '\n';
705          *p = 0;
706          write (o, line, strlen (line));
707          close (o);
708       }
709       *h->oa = *h->da = h->udl = 0;
710    }
711 }
712
713 /* parse and delete a file */
714 static void
715 sms_readfile (sms_t * h, char *fn)
716 {
717    char line[1000];
718    FILE *s;
719    char dcsset = 0;             /* if DSC set */
720    ast_log (LOG_EVENT, "Sending %s\n", fn);
721    h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
722    h->mr = -1;
723    h->dcs = 0xF1;               /* normal messages class 1 */
724    h->scts = time (0);
725    s = fopen (fn, "r");
726    if (s)
727    {
728       if (unlink (fn))
729       {                         /* concurrent access, we lost */
730          fclose (s);
731          return;
732       }
733       while (fgets (line, sizeof (line), s))
734       {                         /* process line in file */
735          unsigned char *p;
736          for (p = line; *p && *p != '\n' && *p != '\r'; p++);
737          *p = 0;                /* strip eoln */
738          p = line;
739          if (!*p || *p == ';')
740             continue;           /* blank line or comment, ignore */
741          while (isalnum (*p))
742          {
743             *p = tolower (*p);
744             p++;
745          }
746          while (isspace (*p))
747             *p++ = 0;
748          if (*p == '=')
749          {
750             *p++ = 0;
751             if (!strcmp (line, "ud"))
752             {                   /* parse message (UTF-8) */
753                unsigned char o = 0;
754                while (*p && o < SMSLEN)
755                   h->ud[o++] = utf8decode (&p);
756                h->udl = o;
757                if (*p)
758                   ast_log (LOG_WARNING, "UD too long in %s\n", fn);
759             } else
760             {
761                while (isspace (*p))
762                   p++;
763                if (!strcmp (line, "oa") && strlen (p) < sizeof (h->oa))
764                   numcpy (h->oa, p);
765                else if (!strcmp (line, "da") && strlen (p) < sizeof (h->oa))
766                   numcpy (h->da, p);
767                else if (!strcmp (line, "pid"))
768                   h->pid = atoi (p);
769                else if (!strcmp (line, "dcs"))
770                {
771                   h->dcs = atoi (p);
772                   dcsset = 1;
773                } else if (!strcmp (line, "mr"))
774                   h->mr = atoi (p);
775                else if (!strcmp (line, "srr"))
776                   h->srr = (atoi (p) ? 1 : 0);
777                else if (!strcmp (line, "vp"))
778                   h->vp = atoi (p);
779                else if (!strcmp (line, "rp"))
780                   h->rp = (atoi (p) ? 1 : 0);
781                else if (!strcmp (line, "scts"))
782                {                /* get date/time */
783                   int Y,
784                     m,
785                     d,
786                     H,
787                     M,
788                     S;
789                   if (sscanf (p, "%d-%d-%dT%d:%d:%d", &Y, &m, &d, &H, &M, &S) == 6)
790                   {
791                      struct tm t;
792                      t.tm_year = Y - 1900;
793                      t.tm_mon = m - 1;
794                      t.tm_mday = d;
795                      t.tm_hour = H;
796                      t.tm_min = M;
797                      t.tm_sec = S;
798                      t.tm_isdst = -1;
799                      h->scts = mktime (&t);
800                      if (h->scts == (time_t) - 1)
801                         ast_log (LOG_WARNING, "Bad date/timein %s: %s", fn, p);
802                   }
803                } else
804                   ast_log (LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
805             }
806          } else if (*p == '#')
807          {                      /* raw hex format */
808             *p++ = 0;
809             if (*p == '#')
810             {
811                p++;
812                if (!strcmp (line, "ud"))
813                {                /* user data */
814                   int o = 0;
815                   while (*p && o < SMSLEN)
816                   {
817                      if (isxdigit (*p) && isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3]))
818                      {
819                         h->ud[o++] =
820                            (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 12) +
821                            (((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
822                            (((isalpha (p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha (p[3]) ? 9 : 0) + (p[3] & 0xF));
823                         p += 4;
824                      } else
825                         break;
826                   }
827                   h->udl = o;
828                   if (*p)
829                      ast_log (LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
830                } else
831                   ast_log (LOG_WARNING, "Only ud can use ## format, %s\n", fn);
832             } else if (!strcmp (line, "ud"))
833             {                   /* user data */
834                int o = 0;
835                while (*p && o < SMSLEN)
836                {
837                   if (isxdigit (*p) && isxdigit (p[1]))
838                   {
839                      h->ud[o++] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
840                      p += 2;
841                   } else
842                      break;
843                }
844                h->udl = o;
845                if (*p)
846                   ast_log (LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
847             } else if (!strcmp (line, "udh"))
848             {                   /* user data header */
849                unsigned char o = 0;
850                h->udhi = 1;
851                while (*p && o < SMSLEN)
852                {
853                   if (isxdigit (*p) && isxdigit (p[1]))
854                   {
855                      h->udh[o] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
856                      o++;
857                      p += 2;
858                   } else
859                      break;
860                }
861                h->udhl = o;
862                if (*p)
863                   ast_log (LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
864             } else
865                ast_log (LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
866          } else
867             ast_log (LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
868       }
869       fclose (s);
870       if (!dcsset && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
871       {
872          if (packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
873          {
874             if (packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
875                ast_log (LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
876             else
877             {
878                h->dcs = 0x08;   /* default to 16 bit */
879                ast_log (LOG_WARNING, "Sending in 16 bit format (%s)\n", fn);
880             }
881          } else
882          {
883             h->dcs = 0xF5;      /* default to 8 bit */
884             ast_log (LOG_WARNING, "Sending in 8 bit format (%s)\n", fn);
885          }
886       }
887       if (is7bit (h->dcs) && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
888          ast_log (LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
889       if (is8bit (h->dcs) && packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
890          ast_log (LOG_WARNING, "Invalid 8 bit data %s\n", fn);
891       if (is16bit (h->dcs) && packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
892          ast_log (LOG_WARNING, "Invalid 16 bit data %s\n", fn);
893    }
894 }
895
896 /* white a received text message to a file */
897 static void
898 sms_writefile (sms_t * h)
899 {
900    char fn[200] = "",
901       fn2[200] = "";
902    FILE *o;
903    strncpy (fn, spool_dir, sizeof (fn) - 1);
904    mkdir (fn, 0777);            /* ensure it exists */
905    snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
906    mkdir (fn, 0777);            /* ensure it exists */
907    strncpy (fn2, fn, sizeof (fn2) - 1);
908    snprintf (fn2 + strlen (fn2), sizeof (fn2) - strlen (fn2), "/%s.%s-%d", h->queue, isodate (h->scts), seq++);
909    snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/.%s", fn2 + strlen (fn) + 1);
910    o = fopen (fn, "w");
911    if (o)
912    {
913       if (*h->oa)
914          fprintf (o, "oa=%s\n", h->oa);
915       if (*h->da)
916          fprintf (o, "da=%s\n", h->da);
917       if (h->udhi)
918       {
919          unsigned int p;
920          fprintf (o, "udh#");
921          for (p = 0; p < h->udhl; p++)
922             fprintf (o, "%02X", h->udh[p]);
923          fprintf (o, "\n");
924       }
925       if (h->udl)
926       {
927          unsigned int p;
928          for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
929          if (p < h->udl)
930             fputc (';', o);     /* cannot use ud=, but include as a comment for human readable */
931          fprintf (o, "ud=");
932          for (p = 0; p < h->udl; p++)
933          {
934             unsigned short v = h->ud[p];
935             if (v < 32)
936                fputc (191, o);
937             else if (v < 0x80)
938                fputc (v, o);
939             else if (v < 0x800)
940             {
941                fputc (0xC0 + (v >> 6), o);
942                fputc (0x80 + (v & 0x3F), o);
943             } else
944             {
945                fputc (0xE0 + (v >> 12), o);
946                fputc (0x80 + ((v >> 6) & 0x3F), o);
947                fputc (0x80 + (v & 0x3F), o);
948             }
949          }
950          fprintf (o, "\n");
951          for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
952          if (p < h->udl)
953          {
954             for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
955             if (p == h->udl)
956             {                   /* can write in ucs-1 hex */
957                fprintf (o, "ud#");
958                for (p = 0; p < h->udl; p++)
959                   fprintf (o, "%02X", h->ud[p]);
960                fprintf (o, "\n");
961             } else
962             {                   /* write in UCS-2 */
963                fprintf (o, "ud##");
964                for (p = 0; p < h->udl; p++)
965                   fprintf (o, "%04X", h->ud[p]);
966                fprintf (o, "\n");
967             }
968          }
969       }
970       if (h->scts)
971          fprintf (o, "scts=%s\n", isodate (h->scts));
972       if (h->pid)
973          fprintf (o, "pid=%d\n", h->pid);
974       if (h->dcs != 0xF1)
975          fprintf (o, "dcs=%d\n", h->dcs);
976       if (h->vp)
977          fprintf (o, "vp=%d\n", h->vp);
978       if (h->srr)
979          fprintf (o, "srr=1\n");
980       if (h->mr >= 0)
981          fprintf (o, "mr=%d\n", h->mr);
982       if (h->rp)
983          fprintf (o, "rp=1\n");
984       fclose (o);
985       if (rename (fn, fn2))
986          unlink (fn);
987       else
988          ast_log (LOG_EVENT, "Received to %s\n", fn2);
989    }
990 }
991
992 /* read dir skipping dot files... */
993 static struct dirent *
994 readdirqueue (DIR * d, char *queue)
995 {
996    struct dirent *f;
997    do
998    {
999       f = readdir (d);
1000    }
1001    while (f && (*f->d_name == '.' || strncmp (f->d_name, queue, strlen (queue)) || f->d_name[strlen (queue)] != '.'));
1002    return f;
1003 }
1004
1005 /* handle the incoming message */
1006 static unsigned char
1007 sms_handleincoming (sms_t * h)
1008 {
1009    unsigned char p = 3;
1010    if (h->smsc)
1011    {                            /* SMSC */
1012       if ((h->imsg[2] & 3) == 1)
1013       {                         /* SMS-SUBMIT */
1014          h->udhl = h->udl = 0;
1015          h->vp = 0;
1016          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1017          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1018          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1019          strncpy (h->oa, h->cli, sizeof (h->oa) - 1);
1020          h->scts = time (0);
1021          h->mr = h->imsg[p++];
1022          p += unpackaddress (h->da, h->imsg + p);
1023          h->pid = h->imsg[p++];
1024          h->dcs = h->imsg[p++];
1025          if ((h->imsg[2] & 0x18) == 0x10)
1026          {                      /* relative VP */
1027             if (h->imsg[p] < 144)
1028                h->vp = (h->imsg[p] + 1) * 5;
1029             else if (h->imsg[p] < 168)
1030                h->vp = 720 + (h->imsg[p] - 143) * 30;
1031             else if (h->imsg[p] < 197)
1032                h->vp = (h->imsg[p] - 166) * 1440;
1033             else
1034                h->vp = (h->imsg[p] - 192) * 10080;
1035             p++;
1036          } else if (h->imsg[2] & 0x18)
1037             p += 7;             /* ignore enhanced / absolute VP */
1038          p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1039          h->rx = 1;             /* received message */
1040          sms_writefile (h);     /* write the file */
1041          if (p != h->imsg[1] + 2)
1042          {
1043             ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1044             return 0xFF;        /* duh! */
1045          }
1046       } else
1047       {
1048          ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
1049          return 0xFF;
1050       }
1051    } else
1052    {                            /* client */
1053       if (!(h->imsg[2] & 3))
1054       {                         /* SMS-DELIVER */
1055          *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
1056          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1057          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1058          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1059          h->mr = -1;
1060          p += unpackaddress (h->oa, h->imsg + p);
1061          h->pid = h->imsg[p++];
1062          h->dcs = h->imsg[p++];
1063          h->scts = unpackdate (h->imsg + p);
1064          p += 7;
1065          p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1066          h->rx = 1;             /* received message */
1067          sms_writefile (h);     /* write the file */
1068          if (p != h->imsg[1] + 2)
1069          {
1070             ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1071             return 0xFF;        /* duh! */
1072          }
1073       } else
1074       {
1075          ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
1076          return 0xFF;
1077       }
1078    }
1079    return 0;                    /* no error */
1080 }
1081
1082 #ifdef SOLARIS
1083 #define NAME_MAX 1024
1084 #endif
1085
1086 static void
1087 sms_nextoutgoing (sms_t * h)
1088 {                               /* find and fill in next message, or send a REL if none waiting */
1089    char fn[100 + NAME_MAX] = "";
1090    DIR *d;
1091    char more = 0;
1092    strncpy (fn, spool_dir, sizeof (fn) - 1);
1093    mkdir (fn, 0777);            /* ensure it exists */
1094    h->rx = 0;                   /* outgoing message */
1095    snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? "mttx" : "motx");
1096    mkdir (fn, 0777);            /* ensure it exists */
1097    d = opendir (fn);
1098    if (d)
1099    {
1100       struct dirent *f = readdirqueue (d, h->queue);
1101       if (f)
1102       {
1103          snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", f->d_name);
1104          sms_readfile (h, fn);
1105          if (readdirqueue (d, h->queue))
1106             more = 1;           /* more to send */
1107       }
1108       closedir (d);
1109    }
1110    if (*h->da || *h->oa)
1111    {                            /* message to send */
1112       unsigned char p = 2;
1113       h->omsg[0] = 0x91;        /* SMS_DATA */
1114       if (h->smsc)
1115       {                         /* deliver */
1116          h->omsg[p++] = (more ? 4 : 0);
1117          p += packaddress (h->omsg + p, h->oa);
1118          h->omsg[p++] = h->pid;
1119          h->omsg[p++] = h->dcs;
1120          packdate (h->omsg + p, h->scts);
1121          p += 7;
1122          p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
1123       } else
1124       {                         /* submit */
1125          h->omsg[p++] =
1126             0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
1127          if (h->mr < 0)
1128             h->mr = message_ref++;
1129          h->omsg[p++] = h->mr;
1130          p += packaddress (h->omsg + p, h->da);
1131          h->omsg[p++] = h->pid;
1132          h->omsg[p++] = h->dcs;
1133          if (h->vp)
1134          {                      /* relative VP */
1135             if (h->vp < 720)
1136                h->omsg[p++] = (h->vp + 4) / 5 - 1;
1137             else if (h->vp < 1440)
1138                h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
1139             else if (h->vp < 43200)
1140                h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
1141             else if (h->vp < 635040)
1142                h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
1143             else
1144                h->omsg[p++] = 255;      /* max */
1145          }
1146          p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
1147       }
1148       h->omsg[1] = p - 2;
1149       sms_messagetx (h);
1150    } else
1151    {                            /* no message */
1152       h->omsg[0] = 0x94;        /* SMS_REL */
1153       h->omsg[1] = 0;
1154       sms_messagetx (h);
1155    }
1156 }
1157
1158 static void
1159 sms_debug (char *dir, unsigned char *msg)
1160 {
1161    char txt[259 * 3 + 1],
1162     *p = txt;                   /* always long enough */
1163    int n = msg[1] + 3,
1164       q = 0;
1165    while (q < n && q < 30)
1166    {
1167       sprintf (p, " %02X", msg[q++]);
1168       p += 3;
1169    }
1170    if (q < n)
1171       sprintf (p, "...");
1172    ast_verbose (VERBOSE_PREFIX_3 "SMS %s%s\n", dir, txt);
1173 }
1174
1175 static void
1176 sms_messagerx (sms_t * h)
1177 {
1178    sms_debug ("RX", h->imsg);
1179    /* testing */
1180    switch (h->imsg[0])
1181    {
1182    case 0x91:                  /* SMS_DATA */
1183       {
1184          unsigned char cause = sms_handleincoming (h);
1185          if (!cause)
1186          {
1187             sms_log (h, 'Y');
1188             h->omsg[0] = 0x95;  /* SMS_ACK */
1189             h->omsg[1] = 0x02;
1190             h->omsg[2] = 0x00;  /* deliver report */
1191             h->omsg[3] = 0x00;  /* no parameters */
1192          } else
1193          {                      /* NACK */
1194             sms_log (h, 'N');
1195             h->omsg[0] = 0x96;  /* SMS_NACK */
1196             h->omsg[1] = 3;
1197             h->omsg[2] = 0;     /* delivery report */
1198             h->omsg[3] = cause; /* cause */
1199             h->omsg[4] = 0;     /* no parameters */
1200          }
1201          sms_messagetx (h);
1202       }
1203       break;
1204    case 0x92:                  /* SMS_ERROR */
1205       h->err = 1;
1206       sms_messagetx (h);        /* send whatever we sent again */
1207       break;
1208    case 0x93:                  /* SMS_EST */
1209       sms_nextoutgoing (h);
1210       break;
1211    case 0x94:                  /* SMS_REL */
1212       h->hangup = 1;            /* hangup */
1213       break;
1214    case 0x95:                  /* SMS_ACK */
1215       sms_log (h, 'Y');
1216       sms_nextoutgoing (h);
1217       break;
1218    case 0x96:                  /* SMS_NACK */
1219       h->err = 1;
1220       sms_log (h, 'N');
1221       sms_nextoutgoing (h);
1222       break;
1223    default:                    /* Unknown */
1224       h->omsg[0] = 0x92;        /* SMS_ERROR */
1225       h->omsg[1] = 1;
1226       h->omsg[2] = 3;           /* unknown message type; */
1227       sms_messagetx (h);
1228       break;
1229    }
1230 }
1231
1232 static void
1233 sms_messagetx (sms_t * h)
1234 {
1235    unsigned char c = 0,
1236       p;
1237    for (p = 0; p < h->omsg[1] + 2; p++)
1238       c += h->omsg[p];
1239    h->omsg[h->omsg[1] + 2] = 0 - c;
1240    sms_debug ("TX", h->omsg);
1241    h->obyte = 1;
1242    h->opause = 200;
1243    if (h->omsg[0] == 0x93)
1244       h->opause = 2400;         /* initial message delay 300ms (for BT) */
1245    h->obytep = 0;
1246    h->obitp = 0;
1247    h->osync = 80;
1248    h->obyten = h->omsg[1] + 3;
1249 }
1250
1251 static int
1252 sms_generate (struct ast_channel *chan, void *data, int len, int samples)
1253 {
1254    struct ast_frame f = { 0 };
1255    unsigned char waste[AST_FRIENDLY_OFFSET];
1256 #ifdef OUTALAW
1257    unsigned char buf[800];
1258 #else
1259    signed short buf[800];
1260 #endif
1261    sms_t *h = data;
1262    int i;
1263
1264    if (len > sizeof (buf))
1265    {
1266       ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", sizeof (buf) / sizeof (signed short), len);
1267       len = sizeof (buf);
1268 #ifdef OUTALAW
1269       samples = len;
1270 #else
1271       samples = len / 2;
1272 #endif
1273    }
1274    waste[0] = 0;                /* make compiler happy */
1275    f.frametype = AST_FRAME_VOICE;
1276 #ifdef OUTALAW
1277    f.subclass = AST_FORMAT_ALAW;
1278    f.datalen = samples;
1279 #else
1280    f.subclass = AST_FORMAT_SLINEAR;
1281    f.datalen = samples * 2;
1282 #endif
1283    f.offset = AST_FRIENDLY_OFFSET;
1284    f.mallocd = 0;
1285    f.data = buf;
1286    f.samples = samples;
1287    f.src = "app_sms";
1288    /* create a buffer containing the digital sms pattern */
1289    for (i = 0; i < samples; i++)
1290    {
1291 #ifdef OUTALAW
1292       buf[i] = wavea[0];
1293 #else
1294       buf[i] = wave[0];
1295 #endif
1296       if (h->opause)
1297          h->opause--;
1298       else if (h->obyten || h->osync)
1299       {                         /* sending data */
1300 #ifdef OUTALAW
1301          buf[i] = wavea[h->ophase];
1302 #else
1303          buf[i] = wave[h->ophase];
1304 #endif
1305          if ((h->ophase += ((h->obyte & 1) ? 13 : 21)) >= 80)
1306             h->ophase -= 80;
1307          if ((h->ophasep += 12) >= 80)
1308          {                      /* next bit */
1309             h->ophasep -= 80;
1310             if (h->osync)
1311                h->osync--;      /* sending sync bits */
1312             else
1313             {
1314                h->obyte >>= 1;
1315                h->obitp++;
1316                if (h->obitp == 1)
1317                   h->obyte = 0; /* start bit; */
1318                else if (h->obitp == 2)
1319                   h->obyte = h->omsg[h->obytep];
1320                else if (h->obitp == 10)
1321                {
1322                   h->obyte = 1; /* stop bit */
1323                   h->obitp = 0;
1324                   h->obytep++;
1325                   if (h->obytep == h->obyten)
1326                   {
1327                      h->obytep = h->obyten = 0; /* sent */
1328                      h->osync = 10;     /* trailing marks */
1329                   }
1330                }
1331             }
1332          }
1333       }
1334    }
1335    if (ast_write (chan, &f) < 0)
1336    {
1337       ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror (errno));
1338       return -1;
1339    }
1340    return 0;
1341 }
1342
1343 static void
1344 sms_process (sms_t * h, int samples, signed short *data)
1345 {
1346    if (h->obyten || h->osync)
1347       return;                   /* sending */
1348    while (samples--)
1349    {
1350       unsigned long long m0,
1351         m1;
1352       if (abs (*data) > h->imag)
1353          h->imag = abs (*data);
1354       else
1355          h->imag = h->imag * 7 / 8;
1356       if (h->imag > 500)
1357       {
1358          h->idle = 0;
1359          h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
1360          h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
1361          h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
1362          h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
1363          m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
1364          m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
1365          if ((h->ips0 += 21) >= 80)
1366             h->ips0 -= 80;
1367          if ((h->ipc0 += 21) >= 80)
1368             h->ipc0 -= 80;
1369          if ((h->ips1 += 13) >= 80)
1370             h->ips1 -= 80;
1371          if ((h->ipc1 += 13) >= 80)
1372             h->ipc1 -= 80;
1373          {
1374             char bit;
1375             h->ibith <<= 1;
1376             if (m1 > m0)
1377                h->ibith |= 1;
1378             if (h->ibith & 8)
1379                h->ibitt--;
1380             if (h->ibith & 1)
1381                h->ibitt++;
1382             bit = ((h->ibitt > 1) ? 1 : 0);
1383             if (bit != h->ibitl)
1384                h->ibitc = 1;
1385             else
1386                h->ibitc++;
1387             h->ibitl = bit;
1388             if (!h->ibitn && h->ibitc == 4 && !bit)
1389             {
1390                h->ibitn = 1;
1391                h->iphasep = 0;
1392             }
1393             if (bit && h->ibitc == 200)
1394             {                   /* sync, restart message */
1395                h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1396             }
1397             if (h->ibitn)
1398             {
1399                h->iphasep += 12;
1400                if (h->iphasep >= 80)
1401                {                /* next bit */
1402                   h->iphasep -= 80;
1403                   if (h->ibitn++ == 9)
1404                   {             /* end of byte */
1405                      if (!bit)  /* bad stop bit */
1406                         h->ierr = 0xFF; /* unknown error */
1407                      else
1408                      {
1409                         if (h->ibytep < sizeof (h->imsg))
1410                         {
1411                            h->imsg[h->ibytep] = h->ibytev;
1412                            h->ibytec += h->ibytev;
1413                            h->ibytep++;
1414                         } else if (h->ibytep == sizeof (h->imsg))
1415                            h->ierr = 2; /* bad message length */
1416                         if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr)
1417                         {
1418                            if (!h->ibytec)
1419                               sms_messagerx (h);
1420                            else
1421                               h->ierr = 1;      /* bad checksum */
1422                         }
1423                      }
1424                      h->ibitn = 0;
1425                   }
1426                   h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
1427                }
1428             }
1429          }
1430       } else
1431       {                         /* lost carrier */
1432          if (h->idle++ == 80000)
1433          {                      /* nothing happening */
1434             ast_log (LOG_EVENT, "No data, hanging up\n");
1435             h->hangup = 1;
1436             h->err = 1;
1437          }
1438          if (h->ierr)
1439          {                      /* error */
1440             h->err = 1;
1441             h->omsg[0] = 0x92;  /* error */
1442             h->omsg[1] = 1;
1443             h->omsg[2] = h->ierr;
1444             sms_messagetx (h);  /* send error */
1445          }
1446          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1447       }
1448       data++;
1449    }
1450 }
1451
1452 static struct ast_generator smsgen = {
1453  alloc:sms_alloc,
1454  release:sms_release,
1455  generate:sms_generate,
1456 };
1457
1458 static int
1459 sms_exec (struct ast_channel *chan, void *data)
1460 {
1461    int res = -1;
1462    struct localuser *u;
1463    struct ast_frame *f;
1464    sms_t h = { 0 };
1465    h.ipc0 = h.ipc1 = 20;        /* phase for cosine */
1466    h.dcs = 0xF1;                /* default */
1467    if (!data)
1468    {
1469       ast_log (LOG_ERROR, "Requires queue name at least\n");
1470       return -1;
1471    }
1472
1473    if (chan->cid.cid_num)
1474       strncpy (h.cli, chan->cid.cid_num, sizeof (h.cli) - 1);
1475
1476    {
1477       unsigned char *d = data,
1478          *p,
1479          answer = 0;
1480       if (!*d || *d == '|')
1481       {
1482          ast_log (LOG_ERROR, "Requires queue name\n");
1483          return -1;
1484       }
1485       for (p = d; *p && *p != '|'; p++);
1486       if (p - d >= sizeof (h.queue))
1487       {
1488          ast_log (LOG_ERROR, "Queue name too long\n");
1489          return -1;
1490       }
1491       strncpy (h.queue, d, p - d);
1492       if (*p == '|')
1493          p++;
1494       d = p;
1495       for (p = h.queue; *p; p++)
1496          if (!isalnum (*p))
1497             *p = '-';           /* make very safe for filenames */
1498       while (*d && *d != '|')
1499       {
1500          switch (*d)
1501          {
1502          case 'a':             /* we have to send the initial FSK sequence */
1503             answer = 1;
1504             break;
1505          case 's':             /* we are acting as a service centre talking to a phone */
1506             h.smsc = 1;
1507             break;
1508             /* the following apply if there is an arg3/4 and apply to the created message file */
1509          case 'r':
1510             h.srr = 1;
1511             break;
1512          case 'o':
1513             h.dcs |= 4;         /* octets */
1514             break;
1515          case '1':
1516          case '2':
1517          case '3':
1518          case '4':
1519          case '5':
1520          case '6':
1521          case '7':             /* set the pid for saved local message */
1522             h.pid = 0x40 + (*d & 0xF);
1523             break;
1524          }
1525          d++;
1526       }
1527       if (*d == '|')
1528       {
1529          /* submitting a message, not taking call. */
1530          /* depricated, use smsq instead */
1531          d++;
1532          h.scts = time (0);
1533          for (p = d; *p && *p != '|'; p++);
1534          if (*p)
1535             *p++ = 0;
1536          if (strlen (d) >= sizeof (h.oa))
1537          {
1538             ast_log (LOG_ERROR, "Address too long %s\n", d);
1539             return 0;
1540          }
1541          if (h.smsc)
1542          {
1543             strncpy (h.oa, d, sizeof (h.oa) - 1);
1544          } else
1545          {
1546             strncpy (h.da, d, sizeof (h.da) - 1);
1547          }
1548          if (!h.smsc)
1549             strncpy (h.oa, h.cli, sizeof (h.oa) - 1);
1550          d = p;
1551          h.udl = 0;
1552          while (*p && h.udl < SMSLEN)
1553             h.ud[h.udl++] = utf8decode (&p);
1554          if (is7bit (h.dcs) && packsms7 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
1555             ast_log (LOG_WARNING, "Invalid 7 bit GSM data\n");
1556          if (is8bit (h.dcs) && packsms8 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
1557             ast_log (LOG_WARNING, "Invalid 8 bit data\n");
1558          if (is16bit (h.dcs) && packsms16 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
1559             ast_log (LOG_WARNING, "Invalid 16 bit data\n");
1560          h.rx = 0;              /* sent message */
1561          h.mr = -1;
1562          sms_writefile (&h);
1563          return 0;
1564       }
1565
1566       if (answer)
1567       {
1568          /* set up SMS_EST initial message */
1569          h.omsg[0] = 0x93;
1570          h.omsg[1] = 0;
1571          sms_messagetx (&h);
1572       }
1573    }
1574
1575    LOCAL_USER_ADD (u);
1576    if (chan->_state != AST_STATE_UP)
1577       ast_answer (chan);
1578
1579 #ifdef OUTALAW
1580    res = ast_set_write_format (chan, AST_FORMAT_ALAW);
1581 #else
1582    res = ast_set_write_format (chan, AST_FORMAT_SLINEAR);
1583 #endif
1584    if (res >= 0)
1585       res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
1586    if (res < 0)
1587    {
1588       LOCAL_USER_REMOVE (u);
1589       ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
1590       return -1;
1591    }
1592
1593    if (ast_activate_generator (chan, &smsgen, &h) < 0)
1594    {
1595       LOCAL_USER_REMOVE (u);
1596       ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
1597       return -1;
1598    }
1599
1600    /* Do our thing here */
1601    while (ast_waitfor (chan, -1) > -1 && !h.hangup)
1602    {
1603       f = ast_read (chan);
1604       if (!f)
1605          break;
1606       if (f->frametype == AST_FRAME_VOICE)
1607       {
1608          sms_process (&h, f->samples, f->data);
1609       }
1610
1611       ast_frfree (f);
1612    }
1613
1614    sms_log (&h, '?');           /* log incomplete message */
1615
1616    LOCAL_USER_REMOVE (u);
1617    return (h.err);
1618 }
1619
1620 int
1621 unload_module (void)
1622 {
1623    STANDARD_HANGUP_LOCALUSERS;
1624    return ast_unregister_application (app);
1625 }
1626
1627 int
1628 load_module (void)
1629 {
1630 #ifdef OUTALAW
1631    {
1632       int p;
1633       for (p = 0; p < 80; p++)
1634          wavea[p] = AST_LIN2A (wave[p]);
1635    }
1636 #endif
1637    snprintf (log_file, sizeof (log_file), "%s/sms", ast_config_AST_LOG_DIR);
1638    snprintf (spool_dir, sizeof (spool_dir), "%s/sms", ast_config_AST_SPOOL_DIR);
1639    return ast_register_application (app, sms_exec, synopsis, descrip);
1640 }
1641
1642 char *
1643 description (void)
1644 {
1645    return tdesc;
1646 }
1647
1648 int
1649 usecount (void)
1650 {
1651    int res;
1652    STANDARD_USECOUNT (res);
1653    return res;
1654 }
1655
1656 char *
1657 key ()
1658 {
1659    return ASTERISK_GPL_KEY;
1660 }