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