77fecd4ef1eb555b9ad95589e117883c806dd28d
[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           sprintf (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], fn2[200];
517   FILE *o;
518   strcpy (fn, "/var/spool/asterisk/sms");
519   mkdir (fn, 0777);             /* ensure it exists */
520   sprintf (fn + strlen (fn), "/%s.%s", h->smsc ? "me-sc" : "sc-me", h->queue);
521   mkdir (fn, 0777);             /* ensure it exists */
522   strcpy (fn2, fn);
523   strftime (fn2 + strlen (fn2), 30, "/%Y-%m-%d_%H:%M:%S", localtime (&h->scts));
524   sprintf (fn2 + strlen (fn2), "-%02X", h->mr);
525   sprintf (fn + strlen (fn), "/.%s", fn2 + strlen (fn) + 1);
526   o = fopen (fn, "w");
527   if (o)
528     {
529       fprintf (o, "mr=%d\n", h->mr);
530       if (*h->oa)
531         fprintf (o, "oa=%s\n", h->oa);
532       if (*h->da)
533         fprintf (o, "da=%s\n", h->da);
534       if (h->pid)
535         fprintf (o, "pid=%d\n", h->pid);
536       if (h->dcs != 0xF1)
537         fprintf (o, "dcs=%d\n", h->dcs);
538       if (h->vp)
539         fprintf (o, "srr=%d\n", h->vp);
540       if (h->srr)
541         fprintf (o, "srr=1\n");
542       if (h->rp)
543         fprintf (o, "rp=1\n");
544       if (h->scts)
545         fprintf (o, "scts=%s\n", isodate (h->scts));
546       if (h->udl)
547         {
548           unsigned int p;
549           for (p = 0; p < h->udl && ((h->ud[p] >= 32 && h->ud[p] != 127) || h->ud[p] == '\n' || h->ud[p] == '\r'); p++);
550           if (p < h->udl)
551             {                   // use a hex format as unprintable characters
552               fprintf (o, "ud#");
553               for (p = 0; p < h->udl; p++)
554                 fprintf (o, "%02X", h->ud[p]);
555               fprintf (o, "\n;");
556               /* followed by commented line using printable characters */
557             }
558           fprintf (o, "ud=");
559           for (p = 0; p < h->udl; p++)
560             {
561               if (h->ud[p] == '\\')
562                 fprintf (o, "\\\\");
563               else if (h->ud[p] == '\r')
564                 fprintf (o, "\\r");
565               else if (h->ud[p] == '\n')
566                 fprintf (o, "\\n");
567               else if (h->ud[p] < 32 || h->ud[p] == 127)
568                 fputc (191, o);
569               else
570                 fputc (h->ud[p], o);
571             }
572           fprintf (o, "\n");
573         }
574       fclose (o);
575       if (rename (fn, fn2))
576         unlink (fn);
577       else
578         ast_log (LOG_EVENT, "Received to %s\n", fn2);
579     }
580 }
581
582 /* read dir skipping dot files... */
583 static struct dirent *
584 readdirdot (DIR * d)
585 {
586   struct dirent *f;
587   do
588     {
589       f = readdir (d);
590     }
591   while (f && *f->d_name == '.');
592   return f;
593 }
594
595 /* handle the incoming message */
596 static unsigned char
597 sms_handleincoming (sms_t * h)
598 {
599   unsigned char p = 3;
600   if (h->smsc)
601     {                           /* SMSC */
602       if ((h->imsg[2] & 3) == 1)
603         {                       /* SMS-SUBMIT */
604           h->vp = 0;
605           h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
606           h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
607           strcpy (h->oa, h->cli);
608           h->scts = time (0);
609           h->mr = h->imsg[p++];
610           p += unpackaddress (h->da, h->imsg + p);
611           h->pid = h->imsg[p++];
612           h->dcs = h->imsg[p++];
613           if ((h->imsg[2] & 0x18) == 0x10)
614             {                   /* relative VP */
615               if (h->imsg[p] < 144)
616                 h->vp = (h->imsg[p] + 1) * 5;
617               else if (h->imsg[p] < 168)
618                 h->vp = 720 + (h->imsg[p] - 143) * 30;
619               else if (h->imsg[p] < 197)
620                 h->vp = (h->imsg[p] - 166) * 1440;
621               else
622                 h->vp = (h->imsg[p] - 192) * 10080;
623               p++;
624             }
625           else if (h->imsg[2] & 0x18)
626             p += 7;             /* ignore enhanced / absolute VP */
627           h->udl = h->imsg[p++];
628           if (h->udl)
629             {
630               if (h->dcs & 4)
631                 {
632                   memcpy (h->ud, h->imsg + p, h->udl);
633                   p += h->udl;
634                 }
635               else
636                 p += unpack7 (h->ud, h->imsg + p, h->udl);
637             }
638           sms_writefile (h);    /* write the file */
639           if (p != h->imsg[1] + 2)
640             return 0xFF;        /* duh! */
641         }
642       else
643         {
644           ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
645           return 0xFF;
646         }
647     }
648   else
649     {                           /* client */
650       if (!(h->imsg[2] & 3))
651         {                       /* SMS-DELIVER */
652           *h->da = h->srr = h->rp = h->vp = 0;
653           h->mr = message_ref++;
654           p += unpackaddress (h->oa, h->imsg + p);
655           h->pid = h->imsg[p++];
656           h->dcs = h->imsg[p++];
657           h->scts = unpackdate (h->imsg + p);
658           p += 7;
659           h->udl = h->imsg[p++];
660           if (h->udl)
661             {
662               if (h->dcs & 4)
663                 {
664                   memcpy (h->ud, h->imsg + p, h->udl);
665                   p += h->udl;
666                 }
667               else
668                 p += unpack7 (h->ud, h->imsg + p, h->udl);
669             }
670           sms_writefile (h);    /* write the file */
671           if (p != h->imsg[1] + 2)
672             return 0xFF;        /* duh! */
673         }
674       else
675         {
676           ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
677           return 0xFF;
678         }
679     }
680   return 0;                     /* no error */
681 }
682
683 static void
684 sms_nextoutgoing (sms_t * h)
685 {                               /* find and fill in next message, or send a REL if none waiting */
686   char fn[100 + NAME_MAX];
687   DIR *d;
688   char more = 0;
689   strcpy (fn, "/var/spool/asterisk/sms");
690   mkdir (fn, 0777);             /* ensure it exists */
691   sprintf (fn + strlen (fn), "/%s.%s", h->smsc ? "sc-me" : "me-sc", h->queue);
692   mkdir (fn, 0777);             /* ensure it exists */
693   d = opendir (fn);
694   if (d)
695     {
696       struct dirent *f = readdirdot (d);
697       if (f)
698         {
699           sprintf (fn + strlen (fn), "/%s", f->d_name);
700           sms_readfile (h, fn);
701           if (readdirdot (d))
702             more = 1;           /* more to send */
703         }
704       closedir (d);
705     }
706   if (*h->da || *h->oa)
707     {                           /* message to send */
708       unsigned char p = 2;
709       h->omsg[0] = 0x91;        /* SMS_DATA */
710       if (h->smsc)
711         {                       /* deliver */
712           h->omsg[p++] = (more ? 4 : 0);
713           p += packaddress (h->omsg + p, h->oa);
714           h->omsg[p++] = h->pid;
715           h->omsg[p++] = h->dcs;
716           packdate (h->omsg + p, h->scts);
717           p += 7;
718           h->omsg[p++] = h->udl;
719           if (h->udl)
720             {
721               if (h->dcs & 4)
722                 {
723                   memcpy (h->omsg + p, h->ud, h->udl);
724                   p += h->udl;
725                 }
726               else
727                 p += pack7 (h->omsg + p, h->ud, h->udl);
728             }
729         }
730       else
731         {                       /* submit */
732           h->omsg[p++] = 0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0);
733           h->omsg[p++] = h->mr;
734           p += packaddress (h->omsg + p, h->da);
735           h->omsg[p++] = h->pid;
736           h->omsg[p++] = h->dcs;
737           if (h->vp)
738             {                   /* relative VP */
739               if (h->vp < 720)
740                 h->omsg[p++] = (h->vp + 4) / 5 - 1;
741               else if (h->vp < 1440)
742                 h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
743               else if (h->vp < 43200)
744                 h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
745               else if (h->vp < 635040)
746                 h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
747               else
748                 h->omsg[p++] = 255;     /* max */
749             }
750           h->omsg[p++] = h->udl;
751           if (h->udl)
752             {
753               if (h->dcs & 4)
754                 {
755                   memcpy (h->omsg + p, h->ud, h->udl);
756                   p += h->udl;
757                 }
758               else
759                 p += pack7 (h->omsg + p, h->ud, h->udl);
760             }
761         }
762       h->omsg[1] = p - 2;
763       sms_messagetx (h);
764     }
765   else
766     {                           /* no message */
767       h->omsg[0] = 0x94;        /* SMS_REL */
768       h->omsg[1] = 0;
769       sms_messagetx (h);
770     }
771 }
772
773 static void
774 sms_messagerx (sms_t * h)
775 {
776   ast_verbose (VERBOSE_PREFIX_3 "SMS RX %02X %02X %02X %02X %02X %02X...\n", h->imsg[0], h->imsg[1], h->imsg[2],
777                h->imsg[3], h->imsg[4], h->imsg[5]);
778   /* testing */
779   switch (h->imsg[0])
780     {
781     case 0x91:                  /* SMS_DATA */
782       {
783         unsigned char cause = sms_handleincoming (h);
784         if (!cause)
785           {
786             sms_log (h, 'Y');
787             h->omsg[0] = 0x95;  /* SMS_ACK */
788             h->omsg[1] = 0x02;
789             h->omsg[2] = 0x00;  /* deliver report */
790             h->omsg[3] = 0x00;  /* no parameters */
791           }
792         else
793           {                     /* NACK */
794             sms_log (h, 'N');
795             h->omsg[0] = 0x96;  /* SMS_NACK */
796             h->omsg[1] = 3;
797             h->omsg[2] = 0;     /* delivery report */
798             h->omsg[3] = cause; /* cause */
799             h->omsg[4] = 0;     /* no parameters */
800           }
801         sms_messagetx (h);
802       }
803       break;
804     case 0x92:                  /* SMS_ERROR */
805       sms_messagetx (h);        /* send whatever we sent again */
806       break;
807     case 0x93:                  /* SMS_EST */
808       sms_nextoutgoing (h);
809       break;
810     case 0x94:                  /* SMS_REL */
811       h->hangup = 1;            /* hangup */
812       break;
813     case 0x95:                  /* SMS_ACK */
814       sms_log (h, 'Y');
815       sms_nextoutgoing (h);
816       break;
817     case 0x96:                  /* SMS_NACK */
818       sms_log (h, 'N');
819       sms_nextoutgoing (h);
820       break;
821     default:                    /* Unknown */
822       h->omsg[0] = 0x92;        /* SMS_ERROR */
823       h->omsg[1] = 1;
824       h->omsg[2] = 3;           /* unknown message type; */
825       sms_messagetx (h);
826       break;
827     }
828 }
829
830 static void
831 sms_messagetx (sms_t * h)
832 {
833   unsigned char c = 0, p;
834   for (p = 0; p < h->omsg[1] + 2; p++)
835     c += h->omsg[p];
836   h->omsg[h->omsg[1] + 2] = 0 - c;
837   ast_verbose (VERBOSE_PREFIX_3 "SMS TX %02X %02X %02X %02X %02X %02X...\n", h->omsg[0], h->omsg[1], h->omsg[2],
838                h->omsg[3], h->omsg[4], h->omsg[5]);
839   h->obyte = 1;
840   h->opause = 200;
841   if (h->omsg[0] == 0x93)
842     h->opause = 2400;           /* initial message delay 300ms (for BT) */
843   h->obytep = 0;
844   h->obitp = 0;
845   h->osync = 80;
846   h->obyten = h->omsg[1] + 3;
847 }
848
849
850 static int
851 sms_generate (struct ast_channel *chan, void *data, int len, int samples)
852 {
853   struct ast_frame f;
854   unsigned char waste[AST_FRIENDLY_OFFSET];
855   signed short buf[800];
856   sms_t *h = data;
857   int i;
858
859   if (len > sizeof (buf))
860     {
861       ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
862       len = sizeof (buf);
863       samples = len / 2;
864     }
865   waste[0] = 0;                 /* make compiler happy */
866   f.frametype = AST_FRAME_VOICE;
867   f.subclass = AST_FORMAT_SLINEAR;
868   f.offset = AST_FRIENDLY_OFFSET;
869   f.mallocd = 0;
870   f.data = buf;
871   f.datalen = samples * 2;
872   f.samples = samples;
873   f.src = "app_sms";
874   /* create a buffer containing the digital sms pattern */
875   for (i = 0; i < samples; i++)
876     {
877       buf[i] = 0;
878       if (h->opause)
879         h->opause--;
880       else if (h->obyten || h->osync)
881         {                       /* sending data */
882           buf[i] = wave[h->ophase];
883           if ((h->ophase += ((h->obyte & 1) ? 13 : 21)) >= 80)
884             h->ophase -= 80;
885           if ((h->ophasep += 12) >= 80)
886             {                   /* next bit */
887               h->ophasep -= 80;
888               if (h->osync)
889                 h->osync--;     /* sending sync bits */
890               else
891                 {
892                   h->obyte >>= 1;
893                   h->obitp++;
894                   if (h->obitp == 1)
895                     h->obyte = 0;       /* start bit; */
896                   else if (h->obitp == 2)
897                     h->obyte = h->omsg[h->obytep];
898                   else if (h->obitp == 10)
899                     {
900                       h->obyte = 1;     /* stop bit */
901                       h->obitp = 0;
902                       h->obytep++;
903                       if (h->obytep == h->obyten)
904                         {
905                           h->obytep = h->obyten = 0;    /* sent */
906                           h->osync = 10;        /* trailing marks */
907                         }
908                     }
909                 }
910             }
911         }
912     }
913   if (ast_write (chan, &f) < 0)
914     {
915       ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror (errno));
916       return -1;
917     }
918   return 0;
919 }
920
921 static void
922 sms_process (sms_t * h, int samples, signed short *data)
923 {
924   if (h->obyten || h->osync)
925     return;                     /* sending */
926   while (samples--)
927     {
928       unsigned long long m0, m1;
929       if (abs (*data) > h->imag)
930         h->imag = abs (*data);
931       else
932         h->imag = h->imag * 7 / 8;
933       if (h->imag > 500)
934         {
935           h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
936           h->idle = 0;
937           h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
938           h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
939           h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
940           m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
941           m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
942           if ((h->ips0 += 21) >= 80)
943             h->ips0 -= 80;
944           if ((h->ipc0 += 21) >= 80)
945             h->ipc0 -= 80;
946           if ((h->ips1 += 13) >= 80)
947             h->ips1 -= 80;
948           if ((h->ipc1 += 13) >= 80)
949             h->ipc1 -= 80;
950           {
951             char bit;
952             h->ibith <<= 1;
953             if (m1 > m0)
954               h->ibith |= 1;
955             if (h->ibith & 8)
956               h->ibitt--;
957             if (h->ibith & 1)
958               h->ibitt++;
959             bit = ((h->ibitt > 1) ? 1 : 0);
960             if (bit != h->ibitl)
961               h->ibitc = 1;
962             else
963               h->ibitc++;
964             h->ibitl = bit;
965             if (!h->ibitn && h->ibitc == 4 && !bit)
966               {
967                 h->ibitn = 1;
968                 h->iphasep = 0;
969               }
970             if (bit && h->ibitc == 200)
971               {                 /* sync, restart message */
972                 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
973               }
974             if (h->ibitn)
975               {
976                 h->iphasep += 12;
977                 if (h->iphasep >= 80)
978                   {             /* next bit */
979                     h->iphasep -= 80;
980                     if (h->ibitn++ == 9)
981                       {         /* end of byte */
982                         if (!bit)       /* bad stop bit */
983                           h->ierr = 0xFF;       /* unknown error */
984                         else
985                           {
986                             if (h->ibytep < sizeof (h->imsg))
987                               {
988                                 h->imsg[h->ibytep] = h->ibytev;
989                                 h->ibytec += h->ibytev;
990                                 h->ibytep++;
991                               }
992                             else if (h->ibytep == sizeof (h->imsg))
993                               h->ierr = 2;      /* bad message length */
994                             if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr)
995                               {
996                                 if (!h->ibytec)
997                                   sms_messagerx (h);
998                                 else
999                                   h->ierr = 1;  /* bad checksum */
1000                               }
1001                           }
1002                         h->ibitn = 0;
1003                       }
1004                     h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
1005                   }
1006               }
1007           }
1008         }
1009       else
1010         {                       /* lost carrier */
1011           if (h->idle++ == 80000)
1012             {                   /* nothing happening */
1013               ast_log (LOG_EVENT, "No data, hanging up\n");
1014               h->hangup = 1;
1015             }
1016           if (h->ierr)
1017             {                   /* error */
1018               h->omsg[0] = 0x92;        /* error */
1019               h->omsg[1] = 1;
1020               h->omsg[2] = h->ierr;
1021               sms_messagetx (h);        /* send error */
1022             }
1023           h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1024         }
1025       data++;
1026     }
1027 }
1028
1029 static struct ast_generator smsgen = {
1030 alloc:sms_alloc,
1031 release:sms_release,
1032 generate:sms_generate,
1033 };
1034
1035 static int
1036 sms_exec (struct ast_channel *chan, void *data)
1037 {
1038   int res = -1;
1039   struct localuser *u;
1040   struct ast_frame *f;
1041   sms_t h = { 0 };
1042   h.ipc0 = h.ipc1 = 20;         /* phase for cosine */
1043   h.dcs = 0xF1;                 /* default */
1044   if (!data)
1045     {
1046       ast_log (LOG_ERROR, "Requires queue name at least\n");
1047       return -1;
1048     }
1049
1050   if (chan->callerid)
1051     {                           /* get caller ID. Used as originating address on sc side receives */
1052       char temp[256], *name, *num;
1053       strncpy (temp, chan->callerid, sizeof (temp));
1054       ast_callerid_parse (temp, &name, &num);
1055       if (!num)
1056         num = temp;
1057       ast_shrink_phone_number (num);
1058       if (strlen (num) < sizeof (h.cli))
1059         strcpy (h.cli, num);
1060     }
1061
1062   {
1063     char *d = data, *p, answer = 0;
1064     if (!*d || *d == '|')
1065       {
1066         ast_log (LOG_ERROR, "Requires queue name\n");
1067         return -1;
1068       }
1069     for (p = d; *p && *p != '|'; p++);
1070     if (p - d >= sizeof (h.queue))
1071       {
1072         ast_log (LOG_ERROR, "Queue name too long\n");
1073         return -1;
1074       }
1075     strncpy (h.queue, d, p - d);
1076     if (*p == '|')
1077       p++;
1078     d = p;
1079     for (p = h.queue; *p; p++)
1080       if (!isalnum (*p))
1081         *p = '-';               /* make very safe for filenames */
1082     while (*d && *d != '|')
1083       {
1084         switch (*d)
1085           {
1086           case 'a':             /* we have to send the initial FSK sequence */
1087             answer = 1;
1088             break;
1089           case 's':             /* we are acting as a service centre talking to a phone */
1090             h.smsc = 1;
1091             break;
1092             /* the following apply if there is an arg3/4 and apply to the created message file */
1093           case 'r':
1094             h.srr = 1;
1095             break;
1096           case 'o':
1097             h.dcs |= 4;         /* octets */
1098             break;
1099           case '1':
1100           case '2':
1101           case '3':
1102           case '4':
1103           case '5':
1104           case '6':
1105           case '7':             /* set the pid for saved local message */
1106             h.pid = 0x40 + (*d & 0xF);
1107             break;
1108           }
1109         d++;
1110       }
1111     if (*d == '|')
1112       {                         /* submitting a message, not taking call. */
1113         d++;
1114         h.scts = time (0);
1115         for (p = d; *p && *p != '|'; p++);
1116         if (*p)
1117           *p++ = 0;
1118         if (strlen (d) >= sizeof (h.oa))
1119           {
1120             ast_log (LOG_ERROR, "Address too long %s\n", d);
1121             return 0;
1122           }
1123         strcpy (h.smsc ? h.oa : h.da, d);
1124         if (!h.smsc)
1125           strcpy (h.oa, h.cli);
1126         d = p;
1127         if (!(h.dcs & 4) && check7 (h.udl, h.ud))
1128           ast_log (LOG_WARNING, "Invalid GSM characters in %.*s\n", h.udl, h.ud);
1129         if (strlen (d) > ((h.dcs & 4) ? 140 : 160))
1130           {
1131             ast_log (LOG_ERROR, "Message too long %s\n", d);
1132             h.udl = ((h.dcs & 4) ? 140 : 160);
1133           }
1134         else
1135           h.udl = strlen (d);
1136         if (h.udl)
1137           memcpy (h.ud, d, h.udl);
1138         h.smsc = !h.smsc;       /* file woul go in wrong directory otherwise... */
1139         sms_writefile (&h);
1140         return 0;
1141       }
1142
1143     if (answer)
1144       {                         /* set up SMS_EST initial message */
1145         h.omsg[0] = 0x93;
1146         h.omsg[1] = 0;
1147         sms_messagetx (&h);
1148       }
1149   }
1150
1151   LOCAL_USER_ADD (u);
1152   if (chan->_state != AST_STATE_UP)
1153     ast_answer (chan);
1154
1155   res = ast_set_write_format (chan, AST_FORMAT_SLINEAR);
1156   if (res >= 0)
1157     res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
1158   if (res < 0)
1159     {
1160       LOCAL_USER_REMOVE (u);
1161       ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
1162       return -1;
1163     }
1164
1165   if (ast_activate_generator (chan, &smsgen, &h) < 0)
1166     {
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     {
1175       f = ast_read (chan);
1176       if (!f)
1177         break;
1178       if (f->frametype == AST_FRAME_VOICE)
1179         {
1180           sms_process (&h, f->samples, f->data);
1181         }
1182
1183       ast_frfree (f);
1184     }
1185
1186   sms_log (&h, '?');            /* log incomplete message */
1187
1188   LOCAL_USER_REMOVE (u);
1189   return h.hangup;
1190 }
1191
1192 int
1193 unload_module (void)
1194 {
1195   STANDARD_HANGUP_LOCALUSERS;
1196   return ast_unregister_application (app);
1197 }
1198
1199 int
1200 load_module (void)
1201 {
1202   {                             /* fill in sms8to7 from sms7to8 */
1203     int p;
1204     for (p = 0; p < 256; p++)
1205       sms8to7[p] = 0xE0;        /* inverted question mark and invalid */
1206     for (p = 0; p < 128; p++)
1207       sms8to7[sms7to8[p]] = p;
1208   }
1209   return ast_register_application (app, sms_exec, synopsis, descrip);
1210 }
1211
1212 char *
1213 description (void)
1214 {
1215   return tdesc;
1216 }
1217
1218 int
1219 usecount (void)
1220 {
1221   int res;
1222   STANDARD_USECOUNT (res);
1223   return res;
1224 }
1225
1226 char *
1227 key ()
1228 {
1229   return ASTERISK_GPL_KEY;
1230 }