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