x86-64 compile fixes and cleanups
[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, 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/callerid.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <dirent.h>
28 #include <ctype.h>
29
30 #include <pthread.h>
31
32 /* ToDo */
33 /* When acting as SC and answering, should check for messages and send instead of sending EST as first packet */
34 /* Add full VP support */
35 /* Handle status report messages (generation and reception) */
36 /* Log to show oa and da with no spaces to allow parsing */
37 /* USC2 coding */
38
39 static unsigned char message_ref;       /* arbitary message ref */
40
41 static char *tdesc = "SMS/PSTN handler";
42
43 static char *app = "SMS";
44
45 static char *synopsis = "Communicates with SMS service centres and SMS capable analogue phones";
46
47 static char *descrip =
48   "  SMS(name|[a][s]):  SMS handles exchange of SMS data with a call to/from SMS capabale\n"
49   "phone or SMS PSTN service centre. Can send and/or receive SMS messages.\n"
50   "Returns 0 if call handled correctly, or -1 if there were any problems.\n"
51   "Works to ETSI ES 201 912 compatible with BT SMS PSTN service in UK\n"
52   "Typical usage is to use to handle called from the SMS service centre CLI,\n"
53   "or to set up a call using 'outgoing' or manager interface to connect service centre to SMS()\n"
54   "name is the name of the queue used in /var/spool/asterisk/sms\n"
55   "Argument 'a' means answer, i.e. send initial FSK packet.\n"
56   "Argument 's' means act as service centre talking to a phone.\n"
57   "Messages are processed as per text file message queues.\n"
58   "Can also call as SMS(name|[s]|number|message) to queue a message.\n";
59
60 static signed short wave[] =
61   { 0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
62   5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
63   0, -392, -782, -1167,
64   -1545, -1913, -2270, -2612, -2939, -3247, -3536, -3802, -4045, -4263, -4455, -4619, -4755, -4862, -4938, -4985, -5000,
65   -4985, -4938, -4862,
66   -4755, -4619, -4455, -4263, -4045, -3802, -3536, -3247, -2939, -2612, -2270, -1913, -1545, -1167, -782, -392
67 };
68
69 STANDARD_LOCAL_USER;
70
71 LOCAL_USER_DECL;
72
73 /* SMS 7 bit character mapping */
74 /* Note that some greek characters are simply coded as 191 (inverted question mark) as ISO-8859-1 does not do greek */
75 /* Note 27 (escape) is to be displayed as a space as per GSM 03.38 */
76 static unsigned char sms7to8[] = {
77   '@', 163, '$', 165, 232, 233, 249, 236, 242, 199, 10, 216, 248, 13, 197, 229,
78   191, '_', 191, 191, 191, 191, 191, 191, 191, 191, 191, ' ', 198, 230, 223, 201,
79   ' ', '!', '"', '#', 164, '%', '&', 39, '(', ')', '*', '+', ',', '-', '.', '/',
80   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
81   161, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
82   'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 196, 214, 209, 220, 167,
83   191, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
84   'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 228, 246, 241, 252, 224,
85 };
86 unsigned char sms8to7[256];
87
88 typedef struct sms_s
89 {
90   unsigned char hangup;         /* we are done... */
91   unsigned char smsc;           /* we are SMSC */
92   char queue[30];               /* queue name */
93   char oa[20];                  /* originating address */
94   char da[20];                  /* destination address */
95   time_t scts;                  /* time stamp */
96   unsigned char pid;            /* protocol ID */
97   unsigned char dcs;            /* data coding scheme */
98   unsigned char mr;             /* message reference */
99   unsigned char udl;            /* user date length */
100   unsigned char srr:1;          /* Status Report request */
101   unsigned char rp:1;           /* Reply Path */
102   unsigned int vp;              /* validity period in minutes, 0 for not set */
103   unsigned char ud[160];        /* user data (message) */
104   unsigned char cli[20];        /* caller ID */
105   unsigned char ophase;         /* phase (0-79) for 0 and 1 frequencies (1300Hz and 2100Hz) */
106   unsigned char ophasep;        /* phase (0-79) for 1200 bps */
107   unsigned char obyte;          /* byte being sent */
108   unsigned int opause;          /* silent pause before sending (in sample periods) */
109   unsigned char obitp;          /* bit in byte */
110   unsigned char osync;          /* sync bits to send */
111   unsigned char obytep;         /* byte in data */
112   unsigned char obyten;         /* bytes in data */
113   unsigned char omsg[256];      /* data buffer (out) */
114   unsigned char imsg[200];      /* data buffer (in) */
115   signed long long ims0, imc0, ims1, imc1;      /* magnitude averages sin/cos 0/1 */
116   unsigned int idle;
117   unsigned short imag;          /* signal level */
118   unsigned char ips0, ips1, ipc0, ipc1; /* phase sin/cos 0/1 */
119   unsigned char ibitl;          /* last bit */
120   unsigned char ibitc;          /* bit run length count */
121   unsigned char iphasep;        /* bit phase (0-79) for 1200 bps */
122   unsigned char ibitn;          /* bit number in byte being received */
123   unsigned char ibytev;         /* byte value being received */
124   unsigned char ibytep;         /* byte pointer in messafe */
125   unsigned char ibytec;         /* byte checksum for message */
126   unsigned char ierr;           /* error flag */
127   unsigned char ibith;          /* history of last bits */
128   unsigned char ibitt;          /* total of 1's in last 3 bites */
129   /* more to go here */
130 } sms_t;
131
132 static void *
133 sms_alloc (struct ast_channel *chan, void *params)
134 {
135   return params;
136 }
137
138 static void
139 sms_release (struct ast_channel *chan, void *data)
140 {
141   return;
142 }
143
144 static void sms_messagetx (sms_t * h);
145
146 /* copy number, skipping non digits apart from leading + */
147 static void
148 numcpy (char *d, char *s)
149 {
150   if (*s == '+')
151     *d++ = *s++;
152   while (*s)
153     {
154       if (isdigit (*s))
155         *d++ = *s;
156       s++;
157     }
158   *d = 0;
159 }
160
161 static char *
162 isodate (time_t t)
163 {                               /* static, return a date/time in ISO format */
164   static char date[20];
165   strftime (date, sizeof (date), "%Y-%m-%d %H:%M:%S", localtime (&t));
166   return date;
167 }
168
169 /* pack n bytes from i to o and return number of bytes */
170 static unsigned char
171 pack7 (unsigned char *o, unsigned char *i, unsigned char n)
172 {
173   unsigned char p = 0, b = 0;
174   /* fixup - map character set perhaps... */
175   o[0] = 0;
176   while (n--)
177     {
178       o[p] |= ((sms8to7[*i] & 0x7F) << b);
179       b += 7;
180       if (b >= 8)
181         {
182           b -= 8;
183           p++;
184           o[p] = ((sms8to7[*i] & 0x7F) >> (7 - b));
185         }
186       i++;
187     }
188   if (b)
189     p++;
190   return p;
191 }
192
193 /* check if all characters are valid 7 bit coding characters */
194 static unsigned char
195 check7 (unsigned char l, unsigned char *p)
196 {
197   while (l--)
198     if (sms8to7[*p++] & 0x80)
199       return 1;
200   return 0;
201 }
202
203 /* pack a date and return */
204 static void
205 packdate (unsigned char *o, time_t w)
206 {
207   struct tm *t = localtime (&w);
208 #if defined(__FreeBSD__) || defined(__OpenBSD__)
209   int z = - t->tm_gmtoff / 3600 / 15;
210 #else
211   int z = timezone / 3600 / 15;
212 #endif
213   *o++ = ((t->tm_year % 10) << 4) + (t->tm_year % 100) / 10;
214   *o++ = (((t->tm_mon + 1) % 10) << 4) + (t->tm_mon + 1) / 10;
215   *o++ = ((t->tm_mday % 10) << 4) + t->tm_mday / 10;
216   *o++ = ((t->tm_hour % 10) << 4) + t->tm_hour / 10;
217   *o++ = ((t->tm_min % 10) << 4) + t->tm_min / 10;
218   *o++ = ((t->tm_sec % 10) << 4) + t->tm_sec / 10;
219   if (z < 0)
220     *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
221   else
222     *o++ = ((z % 10) << 4) + z / 10;
223 }
224
225 /* unpack a date and return */
226 static time_t
227 unpackdate (unsigned char *i)
228 {
229   struct tm t;
230   t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
231   t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
232   t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
233   t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
234   t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
235   t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
236   t.tm_isdst = 0;
237   if (i[6] & 0x08)
238     t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
239   else
240     t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
241   return mktime (&t);
242 }
243
244 /* unpack bytes from i to o and return number of source bytes. */
245 static unsigned char
246 unpack7 (unsigned char *o, unsigned char *i, unsigned char l)
247 {
248   unsigned char b = 0, p = 0;
249   while (l--)
250     {
251       if (b < 2)
252         *o++ = sms7to8[((i[p] >> b) & 0x7F)];
253       else
254         *o++ = sms7to8[((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F)];
255       b += 7;
256       if (b >= 8)
257         {
258           b -= 8;
259           p++;
260         }
261     }
262   if (b)
263     p++;
264   return p;
265 }
266
267 /* unpack an address from i, return byte length, unpack to o */
268 static unsigned char
269 unpackaddress (char *o, unsigned char *i)
270 {
271   unsigned char l = i[0], p;
272   if (i[1] == 0x91)
273     *o++ = '+';
274   for (p = 0; p < l; p++)
275     {
276       if (p & 1)
277         *o++ = (i[2 + p / 2] >> 4) + '0';
278       else
279         *o++ = (i[2 + p / 2] & 0xF) + '0';
280     }
281   *o = 0;
282   return (l + 5) / 2;
283 }
284
285 /* store an address at o, and return number of bytes used */
286 static unsigned char
287 packaddress (unsigned char *o, char *i)
288 {
289   unsigned char p = 2;
290   o[0] = 0;
291   if (*i == '+')
292     {
293       i++;
294       o[1] = 0x91;
295     }
296   else
297     o[1] = 0x81;
298   while (*i)
299     if (isdigit (*i))
300       {
301         if (o[0] & 1)
302           o[p++] |= ((*i & 0xF) << 4);
303         else
304           o[p] = (*i & 0xF);
305         o[0]++;
306         i++;
307       }
308     else
309       i++;
310   if (o[0] & 1)
311     o[p++] |= 0xF0;             /* pad */
312   return p;
313 }
314
315 static void
316 sms_log (sms_t * h, char status)
317 {                               /* log the output, and remove file */
318   if (*h->oa || *h->da)
319     {
320       int o = open ("/var/log/asterisk/sms", O_CREAT | O_APPEND | O_WRONLY, 0666);
321       if (o >= 0)
322         {
323           char line[1000], *p;
324           unsigned char n;
325           sprintf (line, "%s %c %s %s %s ", isodate (time (0)), status, h->queue, *h->oa ? h->oa : "-",
326                    *h->da ? h->da : "-");
327           p = line + strlen (line);
328           for (n = 0; n < h->udl; n++)
329             if (h->ud[n] == '\\')
330               {
331                 *p++ = '\\';
332                 *p++ = '\\';
333               }
334             else if (h->ud[n] == '\n')
335               {
336                 *p++ = '\\';
337                 *p++ = 'n';
338               }
339             else if (h->ud[n] == '\r')
340               {
341                 *p++ = '\\';
342                 *p++ = 'r';
343               }
344             else if (h->ud[n] < 32 || h->ud[n] == 127)
345               *p++ = 191;
346             else
347               *p++ = h->ud[n];
348           *p++ = '\n';
349           *p = 0;
350           write (o, line, strlen (line));
351           close (o);
352         }
353       *h->oa = *h->da = h->udl = 0;
354     }
355 }
356
357 /* parse and delete a file */
358 static void
359 sms_readfile (sms_t * h, char *fn)
360 {
361   char line[1000];
362   FILE *s;
363   char dcsset = 0;              /* if DSC set */
364   ast_log (LOG_EVENT, "Sending %s\n", fn);
365   h->udl = *h->oa = *h->da = h->pid = h->srr = h->rp = h->vp = 0;
366   h->dcs = 0xF1;                /* normal messages class 1 */
367   h->scts = time (0);
368   h->mr = message_ref++;
369   s = fopen (fn, "r");
370   if (s)
371     {
372       if (unlink (fn))
373         {                       /* concurrent access, we lost */
374           fclose (s);
375           return;
376         }
377       while (fgets (line, sizeof (line), s))
378         {                       /* process line in file */
379           char *p;
380           for (p = line; *p && *p != '\n' && *p != '\r'; p++);
381           *p = 0;               /* strip eoln */
382           //ast_log (LOG_EVENT, "Line %s\n", line);
383           p = line;
384           if (!*p || *p == ';')
385             continue;           /* blank line or comment, ignore */
386           while (isalnum (*p))
387             {
388               *p = tolower (*p);
389               p++;
390             }
391           while (isspace (*p))
392             *p++ = 0;
393           if (*p == '=')
394             {
395               *p++ = 0;
396               if (!strcmp (line, "ud"))
397                 {               /* parse message */
398                   unsigned char o = 0;
399                   while (*p && o < 160)
400                     {
401                       if (*p == '\\')
402                         {
403                           p++;
404                           if (*p == '\\')
405                             h->ud[o++] = *p++;
406                           else if (*p == 'n')
407                             {
408                               h->ud[o++] = '\n';
409                               p++;
410                             }
411                           else if (*p == 'r')
412                             {
413                               h->ud[o++] = '\r';
414                               p++;
415                             }
416                         }
417                       else
418                         h->ud[o++] = *p++;
419                     }
420                   h->udl = o;
421                   if (*p)
422                     ast_log (LOG_WARNING, "UD too long in %s\n", fn);
423                 }
424               else
425                 {
426                   while (isspace (*p))
427                     p++;
428                   if (!strcmp (line, "oa") && strlen (p) < sizeof (h->oa))
429                     numcpy (h->oa, p);
430                   else if (!strcmp (line, "da") && strlen (p) < sizeof (h->oa))
431                     numcpy (h->da, p);
432                   else if (!strcmp (line, "pid"))
433                     h->pid = atoi (p);
434                   else if (!strcmp (line, "dcs"))
435                     {
436                       h->dcs = atoi (p);
437                       dcsset = 1;
438                     }
439                   else if (!strcmp (line, "mr"))
440                     h->mr = atoi (p);
441                   else if (!strcmp (line, "srr"))
442                     h->srr = (atoi (p) ? 1 : 0);
443                   else if (!strcmp (line, "vp"))
444                     h->vp = atoi (p);
445                   else if (!strcmp (line, "rp"))
446                     h->rp = (atoi (p) ? 1 : 0);
447                   else if (!strcmp (line, "scts"))
448                     {           /* get date/time */
449                       int Y, m, d, H, M, S;
450                       if (sscanf (p, "%d-%d-%d %d:%d:%d", &Y, &m, &d, &H, &M, &S) == 6)
451                         {
452                           struct tm t;
453                           t.tm_year = Y - 1900;
454                           t.tm_mon = m - 1;
455                           t.tm_mday = d;
456                           t.tm_hour = H;
457                           t.tm_min = M;
458                           t.tm_sec = S;
459                           t.tm_isdst = -1;
460                           h->scts = mktime (&t);
461                           if (h->scts == (time_t) - 1)
462                             ast_log (LOG_WARNING, "Bad date/timein %s: %s", fn, p);
463                         }
464                     }
465                   else
466                     ast_log (LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
467                 }
468             }
469           else if (*p == '#')
470             {                   /* raw hex format */
471               *p++ = 0;
472               if (!strcmp (line, "ud"))
473                 {
474                   unsigned char o = 0;
475                   while (*p && o < 160)
476                     {
477                       if (isxdigit (*p) && isxdigit (p[1]))
478                         {
479                           h->ud[o] =
480                             (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
481                           o++;
482                           p += 2;
483                         }
484                       else
485                         break;
486                     }
487                   h->udl = o;
488                   if (*p)
489                     ast_log (LOG_WARNING, "UD too long / invalid hex in %s\n", fn);
490                 }
491               else
492                 ast_log (LOG_WARNING, "Only ud can use 8 bit key format with # instead of =\n");
493             }
494           else
495             ast_log (LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
496         }
497       fclose (s);
498       if (!dcsset && h->udl <= 140 && check7 (h->udl, h->ud))
499         {
500           h->dcs = 0xF5;        // default to 8 bit
501           ast_log (LOG_WARNING, "Sending in 8 bit format because of illegal characters %s\n", fn);
502         }
503       if ((h->dcs & 4) && h->udl > 140)
504         {
505           ast_log (LOG_WARNING, "8 bit data too long, truncated %s\n", fn);
506           h->udl = 140;
507         }
508       else if (!(h->dcs & 4) && check7 (h->udl, h->ud))
509         ast_log (LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
510     }
511   //ast_log (LOG_EVENT, "Loaded %s\n", fn);
512 }
513
514 /* white a received text message to a file */
515 static void
516 sms_writefile (sms_t * h)
517 {
518   char fn[200], fn2[200];
519   FILE *o;
520   strcpy (fn, "/var/spool/asterisk/sms");
521   mkdir (fn, 0777);             /* ensure it exists */
522   sprintf (fn + strlen (fn), "/%s.%s", h->smsc ? "me-sc" : "sc-me", h->queue);
523   mkdir (fn, 0777);             /* ensure it exists */
524   strcpy (fn2, fn);
525   strftime (fn2 + strlen (fn2), 30, "/%Y-%m-%d_%H:%M:%S", localtime (&h->scts));
526   sprintf (fn2 + strlen (fn2), "-%02X", h->mr);
527   sprintf (fn + strlen (fn), "/.%s", fn2 + strlen (fn) + 1);
528   o = fopen (fn, "w");
529   if (o)
530     {
531       fprintf (o, "mr=%d\n", h->mr);
532       if (*h->oa)
533         fprintf (o, "oa=%s\n", h->oa);
534       if (*h->da)
535         fprintf (o, "da=%s\n", h->da);
536       if (h->pid)
537         fprintf (o, "pid=%d\n", h->pid);
538       if (h->dcs != 0xF1)
539         fprintf (o, "dcs=%d\n", h->dcs);
540       if (h->vp)
541         fprintf (o, "srr=%d\n", h->vp);
542       if (h->srr)
543         fprintf (o, "srr=1\n");
544       if (h->rp)
545         fprintf (o, "rp=1\n");
546       if (h->scts)
547         fprintf (o, "scts=%s\n", isodate (h->scts));
548       if (h->udl)
549         {
550           unsigned int p;
551           for (p = 0; p < h->udl && ((h->ud[p] >= 32 && h->ud[p] != 127) || h->ud[p] == '\n' || h->ud[p] == '\r'); p++);
552           if (p < h->udl)
553             {                   // use a hex format as unprintable characters
554               fprintf (o, "ud#");
555               for (p = 0; p < h->udl; p++)
556                 fprintf (o, "%02X", h->ud[p]);
557               fprintf (o, "\n;");
558               /* followed by commented line using printable characters */
559             }
560           fprintf (o, "ud=");
561           for (p = 0; p < h->udl; p++)
562             {
563               if (h->ud[p] == '\\')
564                 fprintf (o, "\\\\");
565               else if (h->ud[p] == '\r')
566                 fprintf (o, "\\r");
567               else if (h->ud[p] == '\n')
568                 fprintf (o, "\\n");
569               else if (h->ud[p] < 32 || h->ud[p] == 127)
570                 fputc (191, o);
571               else
572                 fputc (h->ud[p], o);
573             }
574           fprintf (o, "\n");
575         }
576       fclose (o);
577       if (rename (fn, fn2))
578         unlink (fn);
579       else
580         ast_log (LOG_EVENT, "Received to %s\n", fn2);
581     }
582 }
583
584 /* read dir skipping dot files... */
585 static struct dirent *
586 readdirdot (DIR * d)
587 {
588   struct dirent *f;
589   do
590     {
591       f = readdir (d);
592     }
593   while (f && *f->d_name == '.');
594   return f;
595 }
596
597 /* handle the incoming message */
598 static unsigned char
599 sms_handleincoming (sms_t * h)
600 {
601   unsigned char p = 3;
602   if (h->smsc)
603     {                           /* SMSC */
604       if ((h->imsg[2] & 3) == 1)
605         {                       /* SMS-SUBMIT */
606           h->vp = 0;
607           h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
608           h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
609           strcpy (h->oa, h->cli);
610           h->scts = time (0);
611           h->mr = h->imsg[p++];
612           p += unpackaddress (h->da, h->imsg + p);
613           h->pid = h->imsg[p++];
614           h->dcs = h->imsg[p++];
615           if ((h->imsg[2] & 0x18) == 0x10)
616             {                   /* relative VP */
617               if (h->imsg[p] < 144)
618                 h->vp = (h->imsg[p] + 1) * 5;
619               else if (h->imsg[p] < 168)
620                 h->vp = 720 + (h->imsg[p] - 143) * 30;
621               else if (h->imsg[p] < 197)
622                 h->vp = (h->imsg[p] - 166) * 1440;
623               else
624                 h->vp = (h->imsg[p] - 192) * 10080;
625               p++;
626             }
627           else if (h->imsg[2] & 0x18)
628             p += 7;             /* ignore enhanced / absolute VP */
629           h->udl = h->imsg[p++];
630           if (h->udl)
631             {
632               if (h->dcs & 4)
633                 {
634                   memcpy (h->ud, h->imsg + p, h->udl);
635                   p += h->udl;
636                 }
637               else
638                 p += unpack7 (h->ud, h->imsg + p, h->udl);
639             }
640           sms_writefile (h);    /* write the file */
641           if (p != h->imsg[1] + 2)
642             return 0xFF;        /* duh! */
643         }
644       else
645         {
646           ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
647           return 0xFF;
648         }
649     }
650   else
651     {                           /* client */
652       if (!(h->imsg[2] & 3))
653         {                       /* SMS-DELIVER */
654           *h->da = h->srr = h->rp = h->vp = 0;
655           h->mr = message_ref++;
656           p += unpackaddress (h->oa, h->imsg + p);
657           h->pid = h->imsg[p++];
658           h->dcs = h->imsg[p++];
659           h->scts = unpackdate (h->imsg + p);
660           p += 7;
661           h->udl = h->imsg[p++];
662           if (h->udl)
663             {
664               if (h->dcs & 4)
665                 {
666                   memcpy (h->ud, h->imsg + p, h->udl);
667                   p += h->udl;
668                 }
669               else
670                 p += unpack7 (h->ud, h->imsg + p, h->udl);
671             }
672           sms_writefile (h);    /* write the file */
673           if (p != h->imsg[1] + 2)
674             return 0xFF;        /* duh! */
675         }
676       else
677         {
678           ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
679           return 0xFF;
680         }
681     }
682   return 0;                     /* no error */
683 }
684
685 static void
686 sms_nextoutgoing (sms_t * h)
687 {                               /* find and fill in next message, or send a REL if none waiting */
688   char fn[100 + NAME_MAX];
689   DIR *d;
690   char more = 0;
691   strcpy (fn, "/var/spool/asterisk/sms");
692   mkdir (fn, 0777);             /* ensure it exists */
693   sprintf (fn + strlen (fn), "/%s.%s", h->smsc ? "sc-me" : "me-sc", h->queue);
694   mkdir (fn, 0777);             /* ensure it exists */
695   d = opendir (fn);
696   if (d)
697     {
698       struct dirent *f = readdirdot (d);
699       if (f)
700         {
701           sprintf (fn + strlen (fn), "/%s", f->d_name);
702           sms_readfile (h, fn);
703           if (readdirdot (d))
704             more = 1;           /* more to send */
705         }
706       closedir (d);
707     }
708   if (*h->da || *h->oa)
709     {                           /* message to send */
710       unsigned char p = 2;
711       h->omsg[0] = 0x91;        /* SMS_DATA */
712       if (h->smsc)
713         {                       /* deliver */
714           h->omsg[p++] = (more ? 4 : 0);
715           p += packaddress (h->omsg + p, h->oa);
716           h->omsg[p++] = h->pid;
717           h->omsg[p++] = h->dcs;
718           packdate (h->omsg + p, h->scts);
719           p += 7;
720           h->omsg[p++] = h->udl;
721           if (h->udl)
722             {
723               if (h->dcs & 4)
724                 {
725                   memcpy (h->omsg + p, h->ud, h->udl);
726                   p += h->udl;
727                 }
728               else
729                 p += pack7 (h->omsg + p, h->ud, h->udl);
730             }
731         }
732       else
733         {                       /* submit */
734           h->omsg[p++] = 0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0);
735           h->omsg[p++] = h->mr;
736           p += packaddress (h->omsg + p, h->da);
737           h->omsg[p++] = h->pid;
738           h->omsg[p++] = h->dcs;
739           if (h->vp)
740             {                   /* relative VP */
741               if (h->vp < 720)
742                 h->omsg[p++] = (h->vp + 4) / 5 - 1;
743               else if (h->vp < 1440)
744                 h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
745               else if (h->vp < 43200)
746                 h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
747               else if (h->vp < 635040)
748                 h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
749               else
750                 h->omsg[p++] = 255;     /* max */
751             }
752           h->omsg[p++] = h->udl;
753           if (h->udl)
754             {
755               if (h->dcs & 4)
756                 {
757                   memcpy (h->omsg + p, h->ud, h->udl);
758                   p += h->udl;
759                 }
760               else
761                 p += pack7 (h->omsg + p, h->ud, h->udl);
762             }
763         }
764       h->omsg[1] = p - 2;
765       sms_messagetx (h);
766     }
767   else
768     {                           /* no message */
769       h->omsg[0] = 0x94;        /* SMS_REL */
770       h->omsg[1] = 0;
771       sms_messagetx (h);
772     }
773 }
774
775 static void
776 sms_messagerx (sms_t * h)
777 {
778   ast_verbose (VERBOSE_PREFIX_3 "SMS RX %02X %02X %02X %02X %02X %02X...\n", h->imsg[0], h->imsg[1], h->imsg[2],
779                h->imsg[3], h->imsg[4], h->imsg[5]);
780   /* testing */
781   switch (h->imsg[0])
782     {
783     case 0x91:                  /* SMS_DATA */
784       {
785         unsigned char cause = sms_handleincoming (h);
786         if (!cause)
787           {
788             sms_log (h, 'Y');
789             h->omsg[0] = 0x95;  /* SMS_ACK */
790             h->omsg[1] = 0x02;
791             h->omsg[2] = 0x00;  /* deliver report */
792             h->omsg[3] = 0x00;  /* no parameters */
793           }
794         else
795           {                     /* NACK */
796             sms_log (h, 'N');
797             h->omsg[0] = 0x96;  /* SMS_NACK */
798             h->omsg[1] = 3;
799             h->omsg[2] = 0;     /* delivery report */
800             h->omsg[3] = cause; /* cause */
801             h->omsg[4] = 0;     /* no parameters */
802           }
803         sms_messagetx (h);
804       }
805       break;
806     case 0x92:                  /* SMS_ERROR */
807       sms_messagetx (h);        /* send whatever we sent again */
808       break;
809     case 0x93:                  /* SMS_EST */
810       sms_nextoutgoing (h);
811       break;
812     case 0x94:                  /* SMS_REL */
813       h->hangup = 1;            /* hangup */
814       break;
815     case 0x95:                  /* SMS_ACK */
816       sms_log (h, 'Y');
817       sms_nextoutgoing (h);
818       break;
819     case 0x96:                  /* SMS_NACK */
820       sms_log (h, 'N');
821       sms_nextoutgoing (h);
822       break;
823     default:                    /* Unknown */
824       h->omsg[0] = 0x92;        /* SMS_ERROR */
825       h->omsg[1] = 1;
826       h->omsg[2] = 3;           /* unknown message type; */
827       sms_messagetx (h);
828       break;
829     }
830 }
831
832 static void
833 sms_messagetx (sms_t * h)
834 {
835   unsigned char c = 0, p;
836   for (p = 0; p < h->omsg[1] + 2; p++)
837     c += h->omsg[p];
838   h->omsg[h->omsg[1] + 2] = 0 - c;
839   ast_verbose (VERBOSE_PREFIX_3 "SMS TX %02X %02X %02X %02X %02X %02X...\n", h->omsg[0], h->omsg[1], h->omsg[2],
840                h->omsg[3], h->omsg[4], h->omsg[5]);
841   h->obyte = 1;
842   h->opause = 200;
843   if (h->omsg[0] == 0x93)
844     h->opause = 2400;           /* initial message delay 300ms (for BT) */
845   h->obytep = 0;
846   h->obitp = 0;
847   h->osync = 80;
848   h->obyten = h->omsg[1] + 3;
849 }
850
851
852 static int
853 sms_generate (struct ast_channel *chan, void *data, int len, int samples)
854 {
855   struct ast_frame f;
856   unsigned char waste[AST_FRIENDLY_OFFSET];
857   signed short buf[800];
858   sms_t *h = data;
859   int i;
860
861   if (len > sizeof (buf))
862     {
863       ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
864       len = sizeof (buf);
865       samples = len / 2;
866     }
867   waste[0] = 0;                 /* make compiler happy */
868   f.frametype = AST_FRAME_VOICE;
869   f.subclass = AST_FORMAT_SLINEAR;
870   f.offset = AST_FRIENDLY_OFFSET;
871   f.mallocd = 0;
872   f.data = buf;
873   f.datalen = samples * 2;
874   f.samples = samples;
875   f.src = "app_sms";
876   /* create a buffer containing the digital sms pattern */
877   for (i = 0; i < samples; i++)
878     {
879       buf[i] = 0;
880       if (h->opause)
881         h->opause--;
882       else if (h->obyten || h->osync)
883         {                       /* sending data */
884           buf[i] = wave[h->ophase];
885           if ((h->ophase += ((h->obyte & 1) ? 13 : 21)) >= 80)
886             h->ophase -= 80;
887           if ((h->ophasep += 12) >= 80)
888             {                   /* next bit */
889               h->ophasep -= 80;
890               if (h->osync)
891                 h->osync--;     /* sending sync bits */
892               else
893                 {
894                   h->obyte >>= 1;
895                   h->obitp++;
896                   if (h->obitp == 1)
897                     h->obyte = 0;       /* start bit; */
898                   else if (h->obitp == 2)
899                     h->obyte = h->omsg[h->obytep];
900                   else if (h->obitp == 10)
901                     {
902                       h->obyte = 1;     /* stop bit */
903                       h->obitp = 0;
904                       h->obytep++;
905                       if (h->obytep == h->obyten)
906                         {
907                           h->obytep = h->obyten = 0;    /* sent */
908                           h->osync = 10;        /* trailing marks */
909                         }
910                     }
911                 }
912             }
913         }
914     }
915   if (ast_write (chan, &f) < 0)
916     {
917       ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror (errno));
918       return -1;
919     }
920   return 0;
921 }
922
923 static void
924 sms_process (sms_t * h, int samples, signed short *data)
925 {
926   if (h->obyten || h->osync)
927     return;                     /* sending */
928   while (samples--)
929     {
930       unsigned long long m0, m1;
931       if (abs (*data) > h->imag)
932         h->imag = abs (*data);
933       else
934         h->imag = h->imag * 7 / 8;
935       if (h->imag > 500)
936         {
937           h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
938           h->idle = 0;
939           h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
940           h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
941           h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
942           m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
943           m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
944           if ((h->ips0 += 21) >= 80)
945             h->ips0 -= 80;
946           if ((h->ipc0 += 21) >= 80)
947             h->ipc0 -= 80;
948           if ((h->ips1 += 13) >= 80)
949             h->ips1 -= 80;
950           if ((h->ipc1 += 13) >= 80)
951             h->ipc1 -= 80;
952           {
953             char bit;
954             h->ibith <<= 1;
955             if (m1 > m0)
956               h->ibith |= 1;
957             if (h->ibith & 8)
958               h->ibitt--;
959             if (h->ibith & 1)
960               h->ibitt++;
961             bit = ((h->ibitt > 1) ? 1 : 0);
962             if (bit != h->ibitl)
963               h->ibitc = 1;
964             else
965               h->ibitc++;
966             h->ibitl = bit;
967             if (!h->ibitn && h->ibitc == 4 && !bit)
968               {
969                 h->ibitn = 1;
970                 h->iphasep = 0;
971               }
972             if (bit && h->ibitc == 200)
973               {                 /* sync, restart message */
974                 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
975               }
976             if (h->ibitn)
977               {
978                 h->iphasep += 12;
979                 if (h->iphasep >= 80)
980                   {             /* next bit */
981                     h->iphasep -= 80;
982                     if (h->ibitn++ == 9)
983                       {         /* end of byte */
984                         if (!bit)       /* bad stop bit */
985                           h->ierr = 0xFF;       /* unknown error */
986                         else
987                           {
988                             if (h->ibytep < sizeof (h->imsg))
989                               {
990                                 h->imsg[h->ibytep] = h->ibytev;
991                                 h->ibytec += h->ibytev;
992                                 h->ibytep++;
993                               }
994                             else if (h->ibytep == sizeof (h->imsg))
995                               h->ierr = 2;      /* bad message length */
996                             if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr)
997                               {
998                                 if (!h->ibytec)
999                                   sms_messagerx (h);
1000                                 else
1001                                   h->ierr = 1;  /* bad checksum */
1002                               }
1003                           }
1004                         h->ibitn = 0;
1005                       }
1006                     h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
1007                   }
1008               }
1009           }
1010         }
1011       else
1012         {                       /* lost carrier */
1013           if (h->idle++ == 80000)
1014             {                   /* nothing happening */
1015               ast_log (LOG_EVENT, "No data, hanging up\n");
1016               h->hangup = 1;
1017             }
1018           if (h->ierr)
1019             {                   /* error */
1020               h->omsg[0] = 0x92;        /* error */
1021               h->omsg[1] = 1;
1022               h->omsg[2] = h->ierr;
1023               sms_messagetx (h);        /* send error */
1024             }
1025           h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1026         }
1027       data++;
1028     }
1029 }
1030
1031 static struct ast_generator smsgen = {
1032 alloc:sms_alloc,
1033 release:sms_release,
1034 generate:sms_generate,
1035 };
1036
1037 static int
1038 sms_exec (struct ast_channel *chan, void *data)
1039 {
1040   int res = -1;
1041   struct localuser *u;
1042   struct ast_frame *f;
1043   sms_t h = { 0 };
1044   h.ipc0 = h.ipc1 = 20;         /* phase for cosine */
1045   h.dcs = 0xF1;                 /* default */
1046   if (!data)
1047     {
1048       ast_log (LOG_ERROR, "Requires queue name at least\n");
1049       return -1;
1050     }
1051
1052   if (chan->callerid)
1053     {                           /* get caller ID. Used as originating address on sc side receives */
1054       char temp[256], *name, *num;
1055       strncpy (temp, chan->callerid, sizeof (temp));
1056       ast_callerid_parse (temp, &name, &num);
1057       if (!num)
1058         num = temp;
1059       ast_shrink_phone_number (num);
1060       if (strlen (num) < sizeof (h.cli))
1061         strcpy (h.cli, num);
1062     }
1063
1064   {
1065     char *d = data, *p, answer = 0;
1066     if (!*d || *d == '|')
1067       {
1068         ast_log (LOG_ERROR, "Requires queue name\n");
1069         return -1;
1070       }
1071     for (p = d; *p && *p != '|'; p++);
1072     if (p - d >= sizeof (h.queue))
1073       {
1074         ast_log (LOG_ERROR, "Queue name too long\n");
1075         return -1;
1076       }
1077     strncpy (h.queue, d, p - d);
1078     if (*p == '|')
1079       p++;
1080     d = p;
1081     for (p = h.queue; *p; p++)
1082       if (!isalnum (*p))
1083         *p = '-';               /* make very safe for filenames */
1084     while (*d && *d != '|')
1085       {
1086         switch (*d)
1087           {
1088           case 'a':             /* we have to send the initial FSK sequence */
1089             answer = 1;
1090             break;
1091           case 's':             /* we are acting as a service centre talking to a phone */
1092             h.smsc = 1;
1093             break;
1094             /* the following apply if there is an arg3/4 and apply to the created message file */
1095           case 'r':
1096             h.srr = 1;
1097             break;
1098           case 'o':
1099             h.dcs |= 4;         /* octets */
1100             break;
1101           case '1':
1102           case '2':
1103           case '3':
1104           case '4':
1105           case '5':
1106           case '6':
1107           case '7':             /* set the pid for saved local message */
1108             h.pid = 0x40 + (*d & 0xF);
1109             break;
1110           }
1111         d++;
1112       }
1113     if (*d == '|')
1114       {                         /* submitting a message, not taking call. */
1115         d++;
1116         h.scts = time (0);
1117         for (p = d; *p && *p != '|'; p++);
1118         if (*p)
1119           *p++ = 0;
1120         if (strlen (d) >= sizeof (h.oa))
1121           {
1122             ast_log (LOG_ERROR, "Address too long %s\n", d);
1123             return 0;
1124           }
1125         strcpy (h.smsc ? h.oa : h.da, d);
1126         if (!h.smsc)
1127           strcpy (h.oa, h.cli);
1128         d = p;
1129         if (!(h.dcs & 4) && check7 (h.udl, h.ud))
1130           ast_log (LOG_WARNING, "Invalid GSM characters in %.*s\n", h.udl, h.ud);
1131         if (strlen (d) > ((h.dcs & 4) ? 140 : 160))
1132           {
1133             ast_log (LOG_ERROR, "Message too long %s\n", d);
1134             h.udl = ((h.dcs & 4) ? 140 : 160);
1135           }
1136         else
1137           h.udl = strlen (d);
1138         if (h.udl)
1139           memcpy (h.ud, d, h.udl);
1140         h.smsc = !h.smsc;       /* file woul go in wrong directory otherwise... */
1141         sms_writefile (&h);
1142         return 0;
1143       }
1144
1145     if (answer)
1146       {                         /* set up SMS_EST initial message */
1147         h.omsg[0] = 0x93;
1148         h.omsg[1] = 0;
1149         sms_messagetx (&h);
1150       }
1151   }
1152
1153   LOCAL_USER_ADD (u);
1154   if (chan->_state != AST_STATE_UP)
1155     ast_answer (chan);
1156
1157   res = ast_set_write_format (chan, AST_FORMAT_SLINEAR);
1158   if (res >= 0)
1159     res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
1160   if (res < 0)
1161     {
1162       LOCAL_USER_REMOVE (u);
1163       ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
1164       return -1;
1165     }
1166
1167   if (ast_activate_generator (chan, &smsgen, &h) < 0)
1168     {
1169       LOCAL_USER_REMOVE (u);
1170       ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
1171       return -1;
1172     }
1173
1174   /* Do our thing here */
1175   while (ast_waitfor (chan, -1) > -1 && !h.hangup)
1176     {
1177       f = ast_read (chan);
1178       if (!f)
1179         break;
1180       if (f->frametype == AST_FRAME_VOICE)
1181         {
1182           sms_process (&h, f->samples, f->data);
1183         }
1184
1185       ast_frfree (f);
1186     }
1187
1188   sms_log (&h, '?');            /* log incomplete message */
1189
1190   LOCAL_USER_REMOVE (u);
1191   return h.hangup;
1192 }
1193
1194 int
1195 unload_module (void)
1196 {
1197   STANDARD_HANGUP_LOCALUSERS;
1198   return ast_unregister_application (app);
1199 }
1200
1201 int
1202 load_module (void)
1203 {
1204   {                             /* fill in sms8to7 from sms7to8 */
1205     int p;
1206     for (p = 0; p < 256; p++)
1207       sms8to7[p] = 0xE0;        /* inverted question mark and invalid */
1208     for (p = 0; p < 128; p++)
1209       sms8to7[sms7to8[p]] = p;
1210   }
1211   return ast_register_application (app, sms_exec, synopsis, descrip);
1212 }
1213
1214 char *
1215 description (void)
1216 {
1217   return tdesc;
1218 }
1219
1220 int
1221 usecount (void)
1222 {
1223   int res;
1224   STANDARD_USECOUNT (res);
1225   return res;
1226 }
1227
1228 char *
1229 key ()
1230 {
1231   return ASTERISK_GPL_KEY;
1232 }