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