8c78b730a7be5b9c2046adde5dbafc012b3b362e
[asterisk/asterisk.git] / apps / app_sms.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2005, Adrian Kennard, rights assigned to Digium
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*! \file
18  *
19  * \brief SMS application - ETSI ES 201 912 protocol 1 implementation
20  * 
21  * \par Development notes
22  * \note The ETSI standards are available free of charge from ETSI at
23  *      http://pda.etsi.org/pda/queryform.asp
24  *      Among the relevant documents here we have:
25  *
26  *      ES 201 912      SMS for PSTN/ISDN
27  *      TS 123 040      Technical realization of SMS
28  *
29  * \note 2006-09-19: ETSI ES 201 912 protocol 2 used in Italy and Spain
30  *                   support added by Filippo Grassilli (Hyppo)
31  *                   <http://hyppo.com> (Hyppo)
32  *                   Not fully tested, under development
33  * 
34  * \ingroup applications
35  *
36  * \author Adrian Kennard (for the original protocol 1 code)
37  */
38
39 #include "asterisk.h"
40
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
42
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <errno.h>
48 #include <dirent.h>
49 #include <ctype.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52
53 #include "asterisk/lock.h"
54 #include "asterisk/file.h"
55 #include "asterisk/logger.h"
56 #include "asterisk/options.h"
57 #include "asterisk/channel.h"
58 #include "asterisk/pbx.h"
59 #include "asterisk/module.h"
60 #include "asterisk/alaw.h"
61 #include "asterisk/callerid.h"
62 #include "asterisk/utils.h"
63 #include "asterisk/app.h"
64
65 /* #define OUTALAW */ /* enable this to output Alaw rather than linear */
66
67 /* ToDo */
68 /* Add full VP support */
69 /* Handle status report messages (generation and reception) */
70 /* Time zones on time stamps */
71 /* user ref field */
72
73 static volatile unsigned char message_ref;      /* arbitary message ref */
74 static volatile unsigned int seq;       /* arbitrary message sequence number for unqiue files */
75
76 static char log_file[255];
77 static char spool_dir[255];
78
79 static char *app = "SMS";
80
81 static char *synopsis = "Communicates with SMS service centres and SMS capable analogue phones";
82
83 static char *descrip =
84         "  SMS(name|[a][s][t][p(d)][r][o]|addr|body):\n"
85         "SMS handles exchange of SMS data with a call to/from SMS capable\n"
86         "phone or SMS PSTN service center. Can send and/or receive SMS messages.\n"
87         "Works to ETSI ES 201 912 compatible with BT SMS PSTN service in UK\n"
88         "and Telecom Italia in Italy.\n"
89         "Typical usage is to use to handle called from the SMS service centre CLI,\n"
90         "or to set up a call using 'outgoing' or manager interface to connect\n"
91         "service centre to SMS()\n"
92         "name is the name of the queue used in /var/spool/asterisk/sms\n"
93         "Arguments:\n"
94         " a: answer, i.e. send initial FSK packet.\n"
95         " s: act as service centre talking to a phone.\n"
96         " t: use protocol 2 (default used is protocol 1).\n"
97         " p(N): set the initial delay to N ms (default is 300).\n"
98         "addr and body are a deprecated format to send messages out.\n"
99         " s: set the Status Report Request (SRR) bit.\n"
100         " o: the body should be coded as octets not 7-bit symbols.\n"
101         "Messages are processed as per text file message queues.\n" 
102         "smsq (a separate software) is a command to generate message\n"
103         "queues and send messages.\n"
104         "NOTE: the protocol has tight delay bounds. Please use short frames\n"
105         "and disable/keep short the jitter buffer on the ATA to make sure that\n"
106         "respones (ACK etc.) are received in time.\n";
107
108 /*
109  * 80 samples of a single period of the wave. At 8000 Hz, it means these
110  * are the samples of a 100 Hz signal.
111  * To pick the two carriers (1300Hz for '1' and 2100 Hz for '0') used by
112  * the modulation, we should take one every 13 and 21 samples respectively.
113  */
114 static signed short wave[] = {
115         0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
116         5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
117         0, -392, -782, -1167,
118          -1545, -1913, -2270, -2612, -2939, -3247, -3536, -3802, -4045, -4263, -4455, -4619, -4755, -4862, -4938, -4985, -5000,
119         -4985, -4938, -4862,
120         -4755, -4619, -4455, -4263, -4045, -3802, -3536, -3247, -2939, -2612, -2270, -1913, -1545, -1167, -782, -392
121 };
122
123 #ifdef OUTALAW
124 static unsigned char wavea[80];
125 typedef unsigned char output_t;
126 static const output_t *wave_out = wavea;        /* outgoing samples */
127 #define __OUT_FMT AST_FORMAT_ALAW;
128 #else
129 typedef signed short output_t;
130 static const output_t *wave_out = wave;         /* outgoing samples */
131 #define __OUT_FMT AST_FORMAT_SLINEAR
132 #endif
133
134 #define OSYNC_BITS      80      /* initial sync bits */
135
136 /*!
137  * The SMS spec ETSI ES 201 912 defines two protocols with different message types.
138  * Also note that the high bit is used to indicate whether the message
139  * is complete or not, but in two opposite ways:
140  * for Protocol 1, 0x80 means that the message is complete;
141  * for Protocol 2, 0x00 means that the message is complete;
142  */
143 enum message_types {
144         DLL_SMS_MASK    = 0x7f, /* mask for the valid bits */
145
146         /* Protocol 1 values */
147         DLL1_SMS_DATA           = 0x11, /* data packet */
148         DLL1_SMS_ERROR          = 0x12,
149         DLL1_SMS_EST            = 0x13, /* start the connection */
150         DLL1_SMS_REL            = 0x14, /* end the connection */
151         DLL1_SMS_ACK            = 0x15,
152         DLL1_SMS_NACK           = 0x16,
153
154         DLL1_SMS_COMPLETE       = 0x80, /* packet is complete */
155         DLL1_SMS_MORE           = 0x00, /* more data to follow */
156
157         /* Protocol 2 values */
158         DLL2_SMS_EST            = 0x7f, /* magic number. No message body */
159         DLL2_SMS_INFO_MO        = 0x10,
160         DLL2_SMS_INFO_MT        = 0x11,
161         DLL2_SMS_INFO_STA       = 0x12,
162         DLL2_SMS_NACK           = 0x13,
163         DLL2_SMS_ACK0           = 0x14, /* ack even-numbered frame */
164         DLL2_SMS_ACK1           = 0x15, /* ack odd-numbered frame */
165         DLL2_SMS_ENQ            = 0x16,
166         DLL2_SMS_REL            = 0x17, /* end the connection */
167
168         DLL2_SMS_COMPLETE       = 0x00, /* packet is complete */
169         DLL2_SMS_MORE           = 0x80, /* more data to follow */
170 };
171
172 /* SMS 7 bit character mapping to UCS-2 */
173 static const unsigned short defaultalphabet[] = {
174         0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
175         0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
176         0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
177         0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
178         ' ', '!', '"', '#', 164, '%', '&', 39, '(', ')', '*', '+', ',', '-', '.', '/',
179         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
180         161, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
181         'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 196, 214, 209, 220, 167,
182         191, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
183         'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 228, 246, 241, 252, 224,
184 };
185
186 static const unsigned short escapes[] = {
187         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x000C, 0, 0, 0, 0, 0,
188         0, 0, 0, 0, 0x005E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
189         0, 0, 0, 0, 0, 0, 0, 0, 0x007B, 0x007D, 0, 0, 0, 0, 0, 0x005C,
190         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x005B, 0x007E, 0x005D, 0,
191         0x007C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
193         0, 0, 0, 0, 0, 0x20AC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
194         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
195 };
196
197 #define SMSLEN 160              /*!< max SMS length */
198
199 typedef struct sms_s {
200         unsigned char hangup;        /*!< we are done... */
201         unsigned char err;           /*!< set for any errors */
202         unsigned char smsc:1;        /*!< we are SMSC */
203         unsigned char rx:1;          /*!< this is a received message */
204         char queue[30];              /*!< queue name */
205         char oa[20];                 /*!< originating address */
206         char da[20];                 /*!< destination address */
207         time_t scts;                 /*!< time stamp, UTC */
208         unsigned char pid;           /*!< protocol ID */
209         unsigned char dcs;           /*!< data coding scheme */
210         short mr;                    /*!< message reference - actually a byte, but use -1 for not set */
211         int udl;                     /*!< user data length */
212         int udhl;                    /*!< user data header length */
213         unsigned char srr:1;         /*!< Status Report request */
214         unsigned char udhi:1;        /*!< User Data Header required, even if length 0 */
215         unsigned char rp:1;          /*!< Reply Path */
216         unsigned int vp;             /*!< validity period in minutes, 0 for not set */
217         unsigned short ud[SMSLEN];   /*!< user data (message), UCS-2 coded */
218         unsigned char udh[SMSLEN];   /*!< user data header */
219         char cli[20];                /*!< caller ID */
220         unsigned char ophase;        /*!< phase (0-79) for 0 and 1 frequencies (1300Hz and 2100Hz) */
221         unsigned char ophasep;       /*!< phase (0-79) for 1200 bps */
222         unsigned char obyte;         /*!< byte being sent */
223         unsigned int opause;         /*!< silent pause before sending (in sample periods) */
224         unsigned char obitp;         /*!< bit in byte */
225         unsigned char osync;         /*!< sync bits to send */
226         unsigned char obytep;        /*!< byte in data */
227         unsigned char obyten;        /*!< bytes in data */
228         unsigned char omsg[256];     /*!< data buffer (out) */
229         unsigned char imsg[250];     /*!< data buffer (in) */
230         signed long long ims0,
231                 imc0,
232                 ims1,
233                 imc1;                      /*!< magnitude averages sin/cos 0/1 */
234         unsigned int idle;
235         unsigned short imag;         /*!< signal level */
236         unsigned char ips0;          /*!< phase sin for bit 0, start at  0 inc by 21 mod 80 */
237         unsigned char ips1;          /*!< phase cos for bit 0, start at 20 inc by 21 mod 80 */
238         unsigned char ipc0;          /*!< phase sin for bit 1, start at  0 inc by 13 mod 80 */
239         unsigned char ipc1;          /*!< phase cos for bit 1, start at 20 inc by 13 mod 80 */
240         unsigned char ibitl;         /*!< last bit */
241         unsigned char ibitc;         /*!< bit run length count */
242         unsigned char iphasep;       /*!< bit phase (0-79) for 1200 bps */
243         unsigned char ibitn;         /*!< bit number in byte being received */
244         unsigned char ibytev;        /*!< byte value being received */
245         unsigned char ibytep;        /*!< byte pointer in message */
246         unsigned char ibytec;        /*!< byte checksum for message */
247         unsigned char ierr;          /*!< error flag */
248         unsigned char ibith;         /*!< history of last bits */
249         unsigned char ibitt;         /*!< total of 1's in last 3 bytes */
250         /* more to go here */
251
252         int     opause_0;               /*!< initial delay in ms, p() option */
253         int protocol;                /*!< ETSI SMS protocol to use (passed at app call) */
254         int oseizure;                /*!< protocol 2: channel seizure bits to send */
255         int framenumber;             /*!< protocol 2: frame number (for sending ACK0 or ACK1) */
256         char udtxt[SMSLEN]; /*!< user data (message), PLAIN text */
257 } sms_t;
258
259 /* different types of encoding */
260 #define is7bit(dcs) (((dcs)&0xC0)?(!((dcs)&4)):(!((dcs)&12)))
261 #define is8bit(dcs) (((dcs)&0xC0)?(((dcs)&4)):(((dcs)&12)==4))
262 #define is16bit(dcs) (((dcs)&0xC0)?0:(((dcs)&12)==8))
263
264 static void sms_messagetx (sms_t * h);
265
266 /*! \brief copy number, skipping non digits apart from leading + */
267 static void numcpy(char *d, char *s)
268 {
269         if (*s == '+')
270                 *d++ = *s++;
271         while (*s) {
272                 if (isdigit (*s))
273                         *d++ = *s;
274                 s++;
275         }
276         *d = 0;
277 }
278
279 /*! \brief static, return a date/time in ISO format */
280 static char * isodate(time_t t, char *buf, int len)
281 {
282         strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime (&t));
283         return buf;
284 }
285
286 /*! \brief Reads next UCS character from NUL terminated UTF-8 string and advance pointer */
287 /* for non valid UTF-8 sequences, returns character as is */
288 /* Does not advance pointer for null termination */
289 static long utf8decode (unsigned char **pp)
290 {
291         unsigned char *p = *pp;
292         if (!*p)
293                 return 0;                 /* null termination of string */
294         (*pp)++;
295         if (*p < 0xC0)
296                 return *p;                /* ascii or continuation character */
297         if (*p < 0xE0) {
298                 if (*p < 0xC2 || (p[1] & 0xC0) != 0x80)
299                         return *p;             /* not valid UTF-8 */
300                 (*pp)++;
301                 return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
302         }
303         if (*p < 0xF0) {
304                 if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80)
305                          return *p;             /* not valid UTF-8 */
306                 (*pp) += 2;
307                 return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
308         }
309         if (*p < 0xF8) {
310                 if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80)
311                         return *p;             /* not valid UTF-8 */
312                 (*pp) += 3;
313                 return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
314         }
315         if (*p < 0xFC) {
316                 if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
317                         || (p[4] & 0xC0) != 0x80)
318                         return *p;             /* not valid UTF-8 */
319                 (*pp) += 4;
320                 return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
321         }
322         if (*p < 0xFE) {
323                 if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
324                         || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80)
325                         return *p;             /* not valid UTF-8 */
326                 (*pp) += 5;
327                 return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
328         }
329         return *p;                   /* not sensible */
330 }
331
332 /*! \brief takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using SMS 7 bit character codes */
333 /* The return value is the number of septets packed in to o, which is internally limited to SMSLEN */
334 /* o can be null, in which case this is used to validate or count only */
335 /* if the input contains invalid characters then the return value is -1 */
336 static int packsms7 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
337 {
338          unsigned char p = 0, b = 0, n = 0;
339
340         if (udhl) {                            /* header */
341                 if (o)
342                         o[p++] = udhl;
343                 b = 1;
344                 n = 1;
345                 while (udhl--) {
346                         if (o)
347                                 o[p++] = *udh++;
348                         b += 8;
349                         while (b >= 7) {
350                                 b -= 7;
351                                 n++;
352                         }
353                         if (n >= SMSLEN)
354                                 return n;
355                 }
356                 if (b) {
357                         b = 7 - b;
358                         if (++n >= SMSLEN)
359                                 return n;
360                         };      /* filling to septet boundary */
361                 }
362                 if (o)
363                         o[p] = 0;
364                 /* message */
365                 while (udl--) {
366                         long u;
367                         unsigned char v;
368                         u = *ud++;
369                         for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
370                         if (v == 128 && u && n + 1 < SMSLEN) {
371                                 for (v = 0; v < 128 && escapes[v] != u; v++);
372                                 if (v < 128) {  /* escaped sequence */
373                                 if (o)
374                                         o[p] |= (27 << b);
375                                 b += 7;
376                                 if (b >= 8) {
377                                         b -= 8;
378                                         p++;
379                                         if (o)
380                                                 o[p] = (27 >> (7 - b));
381                                 }
382                                 n++;
383                         }
384                 }
385                 if (v == 128)
386                         return -1;             /* invalid character */
387                 if (o)
388                         o[p] |= (v << b);
389                 b += 7;
390                 if (b >= 8) {
391                         b -= 8;
392                         p++;
393                         if (o)
394                                 o[p] = (v >> (7 - b));
395                 }
396                 if (++n >= SMSLEN)
397                         return n;
398         }
399         return n;
400 }
401
402 /*! \brief takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 8 bit character codes */
403 /* The return value is the number of bytes packed in to o, which is internally limited to 140 */
404 /* o can be null, in which case this is used to validate or count only */
405 /* if the input contains invalid characters then the return value is -1 */
406 static int packsms8 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
407 {
408         unsigned char p = 0;
409
410         /* header - no encoding */
411         if (udhl) {
412                 if (o)
413                         o[p++] = udhl;
414                 while (udhl--) {
415                         if (o)
416                                 o[p++] = *udh++;
417                         if (p >= 140)
418                                 return p;
419                 }
420         }
421         while (udl--) {
422                 long u;
423                 u = *ud++;
424                 if (u < 0 || u > 0xFF)
425                         return -1;             /* not valid */
426                 if (o)
427                         o[p++] = u;
428                 if (p >= 140)
429                         return p;
430         }
431         return p;
432 }
433
434 /*! \brief takes a binary header (udhl bytes at udh) and UCS-2 
435         message (udl characters at ud) and packs in to o using 16 bit 
436         UCS-2 character codes 
437         The return value is the number of bytes packed in to o, which is 
438         internally limited to 140 
439         o can be null, in which case this is used to validate or count 
440         only if the input contains invalid characters then 
441         the return value is -1 */
442 static int packsms16 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
443 {
444         unsigned char p = 0;
445         /* header - no encoding */
446         if (udhl) {
447                 if (o)
448                         o[p++] = udhl;
449                 while (udhl--) {
450                         if (o)
451                                 o[p++] = *udh++;
452                         if (p >= 140)
453                                 return p;
454                 }
455         }
456         while (udl--) {
457                 long u;
458                 u = *ud++;
459                 if (o)
460                         o[p++] = (u >> 8);
461                 if (p >= 140)
462                         return p - 1;          /* could not fit last character */
463                 if (o)
464                         o[p++] = u;
465                 if (p >= 140)
466                         return p;
467         }
468         return p;
469 }
470
471 /*! \brief general pack, with length and data, 
472         returns number of bytes of target used */
473 static int packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
474 {
475         unsigned char *p = base;
476         if (udl) {
477                 int l = 0;
478                 if (is7bit (dcs)) {              /* 7 bit */
479                         l = packsms7 (p + 1, udhl, udh, udl, ud);
480                         if (l < 0)
481                                 l = 0;
482                         *p++ = l;
483                         p += (l * 7 + 7) / 8;
484                 } else if (is8bit (dcs)) {                                                               /* 8 bit */
485                         l = packsms8 (p + 1, udhl, udh, udl, ud);
486                         if (l < 0)
487                                 l = 0;
488                         *p++ = l;
489                         p += l;
490                 } else {                         /* UCS-2 */
491                         l = packsms16 (p + 1, udhl, udh, udl, ud);
492                         if (l < 0)
493                                 l = 0;
494                         *p++ = l;
495                         p += l;
496                 }
497         } else
498                 *p++ = 0;                         /* no user data */
499         return p - base;
500 }
501
502
503 /*! \brief pack a date and return */
504 static void packdate (unsigned char *o, time_t w)
505 {
506         struct tm *t = localtime (&w);
507 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
508         int z = -t->tm_gmtoff / 60 / 15;
509 #else
510         int z = timezone / 60 / 15;
511 #endif
512         *o++ = ((t->tm_year % 10) << 4) + (t->tm_year % 100) / 10;
513         *o++ = (((t->tm_mon + 1) % 10) << 4) + (t->tm_mon + 1) / 10;
514         *o++ = ((t->tm_mday % 10) << 4) + t->tm_mday / 10;
515         *o++ = ((t->tm_hour % 10) << 4) + t->tm_hour / 10;
516         *o++ = ((t->tm_min % 10) << 4) + t->tm_min / 10;
517         *o++ = ((t->tm_sec % 10) << 4) + t->tm_sec / 10;
518         if (z < 0)
519                 *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
520         else
521                 *o++ = ((z % 10) << 4) + z / 10;
522 }
523
524 /*! \brief unpack a date and return */
525 static time_t unpackdate (unsigned char *i)
526 {
527         struct tm t;
528         t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
529         t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
530         t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
531         t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
532         t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
533         t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
534         t.tm_isdst = 0;
535         if (i[6] & 0x08)
536                 t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
537         else
538                 t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
539         return mktime (&t);
540 }
541
542 /*! \brief unpacks bytes (7 bit encoding) at i, len l septets, 
543         and places in udh and ud setting udhl and udl. udh not used 
544         if udhi not set */
545 static void unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
546 {
547         unsigned char b = 0, p = 0;
548         unsigned short *o = ud;
549         *udhl = 0;
550         if (udhi && l) {                 /* header */
551                 int h = i[p];
552                 *udhl = h;
553                 if (h) {
554                         b = 1;
555                         p++;
556                         l--;
557                         while (h-- && l) {
558                                 *udh++ = i[p++];
559                                 b += 8;
560                                 while (b >= 7) {
561                                         b -= 7;
562                                         l--;
563                                         if (!l)
564                                                 break;
565                                 }
566                         }
567                         /* adjust for fill, septets */
568                         if (b) {
569                                 b = 7 - b;
570                                 l--;
571                         }
572                 }
573         }
574         while (l--) {
575                 unsigned char v;
576                 if (b < 2)
577                         v = ((i[p] >> b) & 0x7F);
578                 else
579                         v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
580                 b += 7;
581                 if (b >= 8) {
582                         b -= 8;
583                         p++;
584                 }
585                 if (o > ud && o[-1] == 0x00A0 && escapes[v])
586                         o[-1] = escapes[v];
587                 else
588                         *o++ = defaultalphabet[v];
589         }
590         *udl = (o - ud);
591 }
592
593 /*! \brief unpacks bytes (8 bit encoding) at i, len l septets, 
594       and places in udh and ud setting udhl and udl. udh not used 
595       if udhi not set */
596 static void unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
597 {
598         unsigned short *o = ud;
599         *udhl = 0;
600         if (udhi) {
601                 int n = *i;
602                 *udhl = n;
603                 if (n) {
604                         i++;
605                         l--;
606                         while (l && n) {
607                                 l--;
608                                 n--;
609                                 *udh++ = *i++;
610                         }
611                 }
612         }
613         while (l--)
614                 *o++ = *i++;      /* not to UTF-8 as explicitly 8 bit coding in DCS */
615         *udl = (o - ud);
616 }
617
618 /*! \brief unpacks bytes (16 bit encoding) at i, len l septets,
619          and places in udh and ud setting udhl and udl. 
620         udh not used if udhi not set */
621 static void unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
622 {
623         unsigned short *o = ud;
624         *udhl = 0;
625         if (udhi) {
626                 int n = *i;
627                 *udhl = n;
628                 if (n) {
629                         i++;
630                         l--;
631                         while (l && n) {
632                                 l--;
633                                 n--;
634                                 *udh++ = *i++;
635                         }
636                 }
637         }
638         while (l--) {
639                 int v = *i++;
640                 if (l--)
641                         v = (v << 8) + *i++;
642                 *o++ = v;
643         }
644         *udl = (o - ud);
645 }
646
647 /*! \brief general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length */
648 static int unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
649 {
650         int l = *i++;
651         if (is7bit (dcs)) {
652                 unpacksms7 (i, l, udh, udhl, ud, udl, udhi);
653                 l = (l * 7 + 7) / 8;            /* adjust length to return */
654         } else if (is8bit (dcs))
655                 unpacksms8 (i, l, udh, udhl, ud, udl, udhi);
656         else
657                 unpacksms16 (i, l, udh, udhl, ud, udl, udhi);
658         return l + 1;
659 }
660
661 /*! \brief unpack an address from i, return byte length, unpack to o */
662 static unsigned char unpackaddress (char *o, unsigned char *i)
663 {
664         unsigned char l = i[0],
665                 p;
666         if (i[1] == 0x91)
667                 *o++ = '+';
668         for (p = 0; p < l; p++) {
669                 if (p & 1)
670                         *o++ = (i[2 + p / 2] >> 4) + '0';
671                 else
672                         *o++ = (i[2 + p / 2] & 0xF) + '0';
673         }
674         *o = 0;
675         return (l + 5) / 2;
676 }
677
678 /*! \brief store an address at o, and return number of bytes used */
679 static unsigned char packaddress (unsigned char *o, char *i)
680 {
681         unsigned char p = 2;
682         o[0] = 0;
683         if (*i == '+') {
684                 i++;
685                 o[1] = 0x91;
686         } else
687                 o[1] = 0x81;
688         while (*i)
689                 if (isdigit (*i)) {
690                         if (o[0] & 1)
691                                 o[p++] |= ((*i & 0xF) << 4);
692                         else
693                                 o[p] = (*i & 0xF);
694                         o[0]++;
695                         i++;
696                 } else
697                         i++;
698         if (o[0] & 1)
699                 o[p++] |= 0xF0;                   /* pad */
700         return p;
701 }
702
703 /*! \brief Log the output, and remove file */
704 static void sms_log (sms_t * h, char status)
705 {
706         if (*h->oa || *h->da) {
707                 int o = open (log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE);
708                 if (o >= 0) {
709                         char line[1000], mrs[3] = "", *p;
710                         char buf[30];
711                         unsigned char n;
712
713                         if (h->mr >= 0)
714                                 snprintf (mrs, sizeof (mrs), "%02X", h->mr);
715                         snprintf (line, sizeof (line), "%s %c%c%c%s %s %s %s ",
716                                 isodate(time(0), buf, sizeof(buf)),
717                                 status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue, *h->oa ? h->oa : "-",
718                                  *h->da ? h->da : "-");
719                         p = line + strlen (line);
720                         for (n = 0; n < h->udl; n++)
721                                 if (h->ud[n] == '\\') {
722                                         *p++ = '\\';
723                                         *p++ = '\\';
724                                 } else if (h->ud[n] == '\n') {
725                                         *p++ = '\\';
726                                         *p++ = 'n';
727                                 } else if (h->ud[n] == '\r') {
728                                         *p++ = '\\';
729                                         *p++ = 'r';
730                                 } else if (h->ud[n] < 32 || h->ud[n] == 127)
731                                         *p++ = 191;
732                                 else
733                                         *p++ = h->ud[n];
734                         *p++ = '\n';
735                         *p = 0;
736                         write (o, line, strlen (line));
737                         close (o);
738                 }
739                 *h->oa = *h->da = h->udl = 0;
740         }
741 }
742
743 /*! \brief parse and delete a file */
744 static void sms_readfile (sms_t * h, char *fn)
745 {
746         char line[1000];
747         FILE *s;
748         char dcsset = 0;                /* if DSC set */
749         ast_log (LOG_EVENT, "Sending %s\n", fn);
750         h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
751         h->mr = -1;
752         h->dcs = 0xF1;                  /* normal messages class 1 */
753         h->scts = time (0);
754         s = fopen (fn, "r");
755         if (s) {
756                 if (unlink (fn)) {      /* concurrent access, we lost */
757                         fclose (s);
758                         return;
759                 }
760                 while (fgets (line, sizeof (line), s)) {        /* process line in file */
761                         char *p;
762                         void *pp = &p;
763                         for (p = line; *p && *p != '\n' && *p != '\r'; p++);
764                         *p = 0;                                  /* strip eoln */
765                         p = line;
766                         if (!*p || *p == ';')
767                                 continue;                         /* blank line or comment, ignore */
768                         while (isalnum (*p)) {
769                                 *p = tolower (*p);
770                                 p++;
771                         }
772                         while (isspace (*p))
773                                 *p++ = 0;
774                         if (*p == '=') {
775                                 *p++ = 0;
776                                 if (!strcmp (line, "ud")) {      /* parse message (UTF-8) */
777                                         unsigned char o = 0;
778                                         memcpy(h->udtxt,p,SMSLEN);      /* for protocol 2 */
779                                         while (*p && o < SMSLEN)
780                                                 h->ud[o++] = utf8decode(pp);
781                                         h->udl = o;
782                                         if (*p)
783                                                 ast_log (LOG_WARNING, "UD too long in %s\n", fn);
784                                 } else {
785                                         while (isspace (*p))
786                                                 p++;
787                                         if (!strcmp (line, "oa") && strlen (p) < sizeof (h->oa))
788                                                 numcpy (h->oa, p);
789                                         else if (!strcmp (line, "da") && strlen (p) < sizeof (h->oa))
790                                                 numcpy (h->da, p);
791                                         else if (!strcmp (line, "pid"))
792                                                 h->pid = atoi (p);
793                                         else if (!strcmp (line, "dcs")) {
794                                                 h->dcs = atoi (p);
795                                                 dcsset = 1;
796                                         } else if (!strcmp (line, "mr"))
797                                                 h->mr = atoi (p);
798                                         else if (!strcmp (line, "srr"))
799                                                 h->srr = (atoi (p) ? 1 : 0);
800                                         else if (!strcmp (line, "vp"))
801                                                 h->vp = atoi (p);
802                                         else if (!strcmp (line, "rp"))
803                                                 h->rp = (atoi (p) ? 1 : 0);
804                                         else if (!strcmp (line, "scts")) {      /* get date/time */
805                                                 int Y,
806                                                   m,
807                                                   d,
808                                                   H,
809                                                   M,
810                                                   S;
811                                                 if (sscanf (p, "%d-%d-%dT%d:%d:%d", &Y, &m, &d, &H, &M, &S) == 6) {
812                                                         struct tm t;
813                                                         t.tm_year = Y - 1900;
814                                                         t.tm_mon = m - 1;
815                                                         t.tm_mday = d;
816                                                         t.tm_hour = H;
817                                                         t.tm_min = M;
818                                                         t.tm_sec = S;
819                                                         t.tm_isdst = -1;
820                                                         h->scts = mktime (&t);
821                                                         if (h->scts == (time_t) - 1)
822                                                                 ast_log (LOG_WARNING, "Bad date/timein %s: %s", fn, p);
823                                                 }
824                                         } else
825                                                 ast_log (LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
826                                 }
827                         } else if (*p == '#') {         /* raw hex format */
828                                 *p++ = 0;
829                                 if (*p == '#') {
830                                         p++;
831                                         if (!strcmp (line, "ud")) {     /* user data */
832                                                 int o = 0;
833                                                 while (*p && o < SMSLEN) {
834                                                         if (isxdigit (*p) && isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3])) {
835                                                                 h->ud[o++] =
836                                                                         (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 12) +
837                                                                         (((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
838                                                                         (((isalpha (p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha (p[3]) ? 9 : 0) + (p[3] & 0xF));
839                                                                 p += 4;
840                                                         } else
841                                                                 break;
842                                                 }
843                                                 h->udl = o;
844                                                 if (*p)
845                                                         ast_log (LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
846                                         } else
847                                                 ast_log (LOG_WARNING, "Only ud can use ## format, %s\n", fn);
848                                 } else if (!strcmp (line, "ud")) {      /* user data */
849                                         int o = 0;
850                                         while (*p && o < SMSLEN) {
851                                                 if (isxdigit (*p) && isxdigit (p[1])) {
852                                                         h->ud[o++] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
853                                                         p += 2;
854                                                 } else
855                                                         break;
856                                         }
857                                         h->udl = o;
858                                         if (*p)
859                                                 ast_log (LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
860                                 } else if (!strcmp (line, "udh")) {     /* user data header */
861                                         unsigned char o = 0;
862                                         h->udhi = 1;
863                                         while (*p && o < SMSLEN) {
864                                                 if (isxdigit (*p) && isxdigit (p[1])) {
865                                                         h->udh[o] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
866                                                         o++;
867                                                         p += 2;
868                                                 } else
869                                                         break;
870                                         }
871                                         h->udhl = o;
872                                         if (*p)
873                                                 ast_log (LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
874                                 } else
875                                         ast_log (LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
876                         } else
877                                 ast_log (LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
878                 }
879                 fclose (s);
880                 if (!dcsset && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0) {
881                         if (packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0) {
882                                 if (packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
883                                         ast_log (LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
884                                 else {
885                                         h->dcs = 0x08;  /* default to 16 bit */
886                                         ast_log (LOG_WARNING, "Sending in 16 bit format (%s)\n", fn);
887                                 }
888                         } else {
889                                 h->dcs = 0xF5;          /* default to 8 bit */
890                                 ast_log (LOG_WARNING, "Sending in 8 bit format (%s)\n", fn);
891                         }
892                 }
893                 if (is7bit (h->dcs) && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
894                         ast_log (LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
895                 if (is8bit (h->dcs) && packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
896                         ast_log (LOG_WARNING, "Invalid 8 bit data %s\n", fn);
897                 if (is16bit (h->dcs) && packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
898                         ast_log (LOG_WARNING, "Invalid 16 bit data %s\n", fn);
899         }
900 }
901
902 /*! \brief white a received text message to a file */
903 static void sms_writefile (sms_t * h)
904 {
905         char fn[200] = "", fn2[200] = "";
906         char buf[30];
907         FILE *o;
908
909         ast_copy_string (fn, spool_dir, sizeof (fn));
910         mkdir (fn, 0777);                       /* ensure it exists */
911         snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
912         mkdir (fn, 0777);                       /* ensure it exists */
913         ast_copy_string (fn2, fn, sizeof (fn2));
914         snprintf (fn2 + strlen (fn2), sizeof (fn2) - strlen (fn2), "/%s.%s-%d", h->queue, isodate(h->scts, buf, sizeof(buf)), seq++);
915         snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/.%s", fn2 + strlen (fn) + 1);
916         o = fopen (fn, "w");
917         if (o) {
918                 if (*h->oa)
919                         fprintf (o, "oa=%s\n", h->oa);
920                 if (*h->da)
921                         fprintf (o, "da=%s\n", h->da);
922                 if (h->udhi) {
923                         unsigned int p;
924                         fprintf (o, "udh#");
925                         for (p = 0; p < h->udhl; p++)
926                                 fprintf (o, "%02X", h->udh[p]);
927                         fprintf (o, "\n");
928                 }
929                 if (h->udl) {
930                         unsigned int p;
931                         for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
932                         if (p < h->udl)
933                                 fputc (';', o);   /* cannot use ud=, but include as a comment for human readable */
934                         fprintf (o, "ud=");
935                         for (p = 0; p < h->udl; p++) {
936                                 unsigned short v = h->ud[p];
937                                 if (v < 32)
938                                         fputc (191, o);
939                                 else if (v < 0x80)
940                                         fputc (v, o);
941                                 else if (v < 0x800)
942                                 {
943                                         fputc (0xC0 + (v >> 6), o);
944                                         fputc (0x80 + (v & 0x3F), o);
945                                 } else
946                                 {
947                                         fputc (0xE0 + (v >> 12), o);
948                                         fputc (0x80 + ((v >> 6) & 0x3F), o);
949                                         fputc (0x80 + (v & 0x3F), o);
950                                 }
951                         }
952                         fprintf (o, "\n");
953                         for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
954                         if (p < h->udl) {
955                                 for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
956                                 if (p == h->udl) {                                               /* can write in ucs-1 hex */
957                                         fprintf (o, "ud#");
958                                         for (p = 0; p < h->udl; p++)
959                                                 fprintf (o, "%02X", h->ud[p]);
960                                         fprintf (o, "\n");
961                                 } else {                                                 /* write in UCS-2 */
962                                         fprintf (o, "ud##");
963                                         for (p = 0; p < h->udl; p++)
964                                                 fprintf (o, "%04X", h->ud[p]);
965                                         fprintf (o, "\n");
966                                 }
967                         }
968                 }
969                 if (h->scts) {
970                         char buf[30];
971                         fprintf (o, "scts=%s\n", isodate(h->scts, buf, sizeof(buf)));
972                 }
973                 if (h->pid)
974                         fprintf (o, "pid=%d\n", h->pid);
975                 if (h->dcs != 0xF1)
976                         fprintf (o, "dcs=%d\n", h->dcs);
977                 if (h->vp)
978                         fprintf (o, "vp=%d\n", h->vp);
979                 if (h->srr)
980                         fprintf (o, "srr=1\n");
981                 if (h->mr >= 0)
982                         fprintf (o, "mr=%d\n", h->mr);
983                 if (h->rp)
984                         fprintf (o, "rp=1\n");
985                 fclose (o);
986                 if (rename (fn, fn2))
987                         unlink (fn);
988                 else
989                         ast_log (LOG_EVENT, "Received to %s\n", fn2);
990         }
991 }
992
993 /*! \brief read dir skipping dot files... */
994 static struct dirent *readdirqueue (DIR * d, char *queue)
995 {
996    struct dirent *f;
997    do {
998       f = readdir (d);
999    } while (f && (*f->d_name == '.' || strncmp (f->d_name, queue, strlen (queue)) || f->d_name[strlen (queue)] != '.'));
1000    return f;
1001 }
1002
1003 /*! \brief handle the incoming message */
1004 static unsigned char sms_handleincoming (sms_t * h)
1005 {
1006         unsigned char p = 3;
1007         if (h->smsc) {                                                                   /* SMSC */
1008                 if ((h->imsg[2] & 3) == 1) {                            /* SMS-SUBMIT */
1009                         h->udhl = h->udl = 0;
1010                         h->vp = 0;
1011                         h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1012                         h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1013                         h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1014                         ast_copy_string (h->oa, h->cli, sizeof (h->oa));
1015                         h->scts = time (0);
1016                         h->mr = h->imsg[p++];
1017                         p += unpackaddress (h->da, h->imsg + p);
1018                         h->pid = h->imsg[p++];
1019                         h->dcs = h->imsg[p++];
1020                         if ((h->imsg[2] & 0x18) == 0x10) {                                                       /* relative VP */
1021                                 if (h->imsg[p] < 144)
1022                                         h->vp = (h->imsg[p] + 1) * 5;
1023                                 else if (h->imsg[p] < 168)
1024                                         h->vp = 720 + (h->imsg[p] - 143) * 30;
1025                                 else if (h->imsg[p] < 197)
1026                                         h->vp = (h->imsg[p] - 166) * 1440;
1027                                 else
1028                                         h->vp = (h->imsg[p] - 192) * 10080;
1029                                 p++;
1030                         } else if (h->imsg[2] & 0x18)
1031                                 p += 7;                          /* ignore enhanced / absolute VP */
1032                         p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1033                         h->rx = 1;                               /* received message */
1034                         sms_writefile (h);        /* write the file */
1035                         if (p != h->imsg[1] + 2) {
1036                                 ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1037                                 return 0xFF;              /* duh! */
1038                         }
1039                 } else {
1040                         ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
1041                         return 0xFF;
1042                 }
1043         } else {                                                                         /* client */
1044                 if (!(h->imsg[2] & 3)) {                                                                 /* SMS-DELIVER */
1045                         *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
1046                         h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
1047                         h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
1048                         h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
1049                         h->mr = -1;
1050                         p += unpackaddress (h->oa, h->imsg + p);
1051                         h->pid = h->imsg[p++];
1052                         h->dcs = h->imsg[p++];
1053                         h->scts = unpackdate (h->imsg + p);
1054                         p += 7;
1055                         p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
1056                         h->rx = 1;                               /* received message */
1057                         sms_writefile (h);        /* write the file */
1058                         if (p != h->imsg[1] + 2) {
1059                                 ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
1060                                 return 0xFF;              /* duh! */
1061                         }
1062                 } else {
1063                         ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
1064                         return 0xFF;
1065                 }
1066         }
1067         return 0;                                                 /* no error */
1068 }
1069
1070 #ifdef SOLARIS
1071 #define NAME_MAX 1024
1072 #endif
1073
1074 /*!
1075  * Add data to a protocol 2 message.
1076  * Use the length field (h->omsg[1]) as a pointer to the next free position.
1077  */
1078 static void adddata_proto2 (sms_t *h, unsigned char msg, char *data, int size)
1079 {
1080         int x = h->omsg[1]+2;   /* Get current position */
1081         if (x==2)
1082                 x += 2;         /* First: skip Payload length (set later) */
1083         h->omsg[x++] = msg;     /* Message code */
1084         h->omsg[x++]=(unsigned char)size;       /* Data size Low */
1085         h->omsg[x++]=0;         /* Data size Hi */
1086         for (; size>0 ; size--)
1087                 h->omsg[x++] = *data++;
1088         h->omsg[1] = x-2;       /* Frame size */
1089         h->omsg[2] = x-4;       /* Payload length (Lo) */
1090         h->omsg[3] = 0;         /* Payload length (Hi) */
1091 }
1092
1093 static void putdummydata_proto2 (sms_t *h)
1094 {
1095         adddata_proto2 (h, 0x10, "\0", 1);              /* Media Identifier > SMS */
1096         adddata_proto2 (h, 0x11, "\0\0\0\0\0\0", 6);    /* Firmware version */
1097         adddata_proto2 (h, 0x12, "\2\0\4", 3);          /* SMS provider ID */
1098         adddata_proto2 (h, 0x13, h->udtxt, h->udl);     /* Body */
1099 }
1100
1101 static void sms_compose2(sms_t *h, int more)
1102 {
1103         struct tm *tm;
1104         char stm[9];
1105
1106         h->omsg[0] = 0x00;       /* set later... */
1107         h->omsg[1] = 0;
1108         putdummydata_proto2 (h);
1109         if (h->smsc) {                  /* deliver */
1110                 h->omsg[0] = 0x11;      /* SMS_DELIVERY */
1111                 // Required: 10 11 12 13 14 15 17 (seems they must be ordered!)
1112                 tm=localtime(&h->scts);
1113                 sprintf (stm, "%02d%02d%02d%02d", tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min);     // Date mmddHHMM
1114                 adddata_proto2 (h, 0x14, stm, 8);               /* Date */
1115                 if(*h->oa==0)
1116                         strcpy(h->oa,"00000000");
1117                 adddata_proto2 (h, 0x15, h->oa, strlen(h->oa)); /* Originator */
1118                 adddata_proto2 (h, 0x17, "\1", 1);              /* Calling Terminal ID */
1119         } else {                        /* submit */
1120                 h->omsg[0] = 0x10;      /* SMS_SUBMIT */
1121                 // Required: 10 11 12 13 17 18 1B 1C (seems they must be ordered!)
1122                 adddata_proto2 (h, 0x17, "\1", 1);              /* Calling Terminal ID */
1123                 if(*h->da==0)
1124                         strcpy(h->da,"00000000");
1125                 adddata_proto2 (h, 0x18, h->da, strlen(h->da)); /* Originator */
1126                 adddata_proto2 (h, 0x1B, "\1", 1);              /* Called Terminal ID */
1127                 adddata_proto2 (h, 0x1C, "\0\0\0", 3);          /* Notification */
1128         }
1129 }
1130
1131 static void putdummydata_proto2 (sms_t *h);
1132
1133 #if 1 /* XXX debugging */
1134 static char *sms_hexdump (unsigned char buf[], int size)
1135 {
1136         static char *s=NULL;
1137         char *p;
1138         int f;
1139
1140         s=(char *)realloc(s,(size*3)+1);
1141         for(p=s,f=0; f<size && f<800/3; f++,p+=3) 
1142                 sprintf(p,"%02X ",(unsigned char)buf[f]);
1143         return(s);
1144 }
1145 #endif
1146
1147 /*! \brief sms_handleincoming_proto2: handle the incoming message */
1148 static int sms_handleincoming_proto2 (sms_t * h)
1149 {
1150         int f, i, sz=0;
1151         int msg, msgsz;
1152         struct tm *tm;
1153
1154         sz = h->imsg[1]+2;
1155         /* ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg,sz)); */
1156
1157         /* Parse message body (called payload) */
1158         h->scts = time (0);
1159         for(f=4; f<sz; ) {
1160                 msg=h->imsg[f++];
1161                 msgsz=h->imsg[f++];
1162                 msgsz+=(h->imsg[f++]*256);
1163                 switch(msg) {
1164                 case 0x13:      /* Body */
1165                         if (option_verbose > 2)
1166                                 ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Body#%02X=[%.*s]\n",msg,msgsz,&h->imsg[f]);
1167                         if (msgsz >= sizeof(h->imsg))
1168                                 msgsz = sizeof(h->imsg)-1;
1169                         for (i=0; i<msgsz; i++)
1170                                 h->ud[i]=h->imsg[f+i];
1171                         h->udl = msgsz;
1172                         break;
1173                 case 0x14:      /* Date SCTS */
1174                         h->scts = time (0);
1175                         tm = localtime (&h->scts);
1176                         tm->tm_mon = ( (h->imsg[f]*10) + h->imsg[f+1] ) - 1;
1177                         tm->tm_mday = ( (h->imsg[f+2]*10) + h->imsg[f+3] );
1178                         tm->tm_hour = ( (h->imsg[f+4]*10) + h->imsg[f+5] );
1179                         tm->tm_min = ( (h->imsg[f+6]*10) + h->imsg[f+7] );
1180                         tm->tm_sec = 0;
1181                         h->scts = mktime (tm);
1182                         if (option_verbose > 2)
1183                                 ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Date#%02X=%02d/%02d %02d:%02d\n", msg, tm->tm_mday, tm->tm_mon+1, tm->tm_hour, tm->tm_min);
1184                         break;
1185                 case 0x15:      /* Calling line (from SMSC) */
1186                         if (msgsz>=20)
1187                                 msgsz=20-1;
1188                         if (option_verbose > 2)
1189                                 ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Origin#%02X=[%.*s]\n",msg,msgsz,&h->imsg[f]);
1190                         ast_copy_string (h->oa, (char*)(&h->imsg[f]), msgsz+1);
1191                         break;
1192                 case 0x18:      /* Destination (from TE/phone) */
1193                         if (msgsz>=20)
1194                                 msgsz=20-1;
1195                         if (option_verbose > 2)
1196                                 ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Destination#%02X=[%.*s]\n",msg,msgsz,&h->imsg[f]);
1197                         ast_copy_string (h->da, (char*)(&h->imsg[f]), msgsz+1);
1198                         break;
1199                 case 0x1C:      /* Notify */
1200                         if (option_verbose > 2)
1201                                 ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Notify#%02X=%s\n",msg,sms_hexdump(&h->imsg[f],3));
1202                         break;
1203                 default:
1204                         if (option_verbose > 2)
1205                                 ast_verbose (VERBOSE_PREFIX_3 "SMS-P2 Par#%02X [%d]: %s\n",msg,msgsz,sms_hexdump(&h->imsg[f],msgsz));
1206                         break;
1207                 }
1208                 f+=msgsz;       /* Skip to next */
1209         }
1210         h->rx = 1;              /* received message */
1211         sms_writefile (h);      /* write the file */
1212         return 0;               /* no error */
1213 }
1214
1215 #if 0
1216 static void smssend(sms_t *h, char *c)
1217 {
1218         int f, x;
1219         for(f=0; f<strlen(c); f++) {
1220                 sscanf(&c[f*3],"%x",&x);
1221                 h->omsg[f] = x;
1222         }
1223         sms_messagetx (h);
1224 }
1225 #endif
1226
1227 static void sms_nextoutgoing (sms_t *h);
1228
1229 static void sms_messagerx2(sms_t * h)
1230 {
1231         int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */
1232         int cause;
1233
1234 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
1235         switch (p) {
1236         case DLL2_SMS_EST:      /* Protocol 2: Connection ready (fake): send message  */
1237                 sms_nextoutgoing (h);
1238                 //smssend(h,"11 29 27 00 10 01 00 00 11 06 00 00 00 00 00 00 00 12 03 00 02 00 04 13 01 00 41 14 08 00 30 39 31 35 30 02 30 02 15 02 00 39 30 ");
1239                 break;
1240
1241         case DLL2_SMS_INFO_MO:  /* transport SMS_SUBMIT */
1242         case DLL2_SMS_INFO_MT:  /* transport SMS_DELIVERY */
1243                 cause = sms_handleincoming_proto2(h);
1244                 if (!cause)     /* ACK */
1245                         sms_log (h, 'Y');
1246                 h->omsg[0] = DLL2_ACK(h);
1247                 h->omsg[1] = 0x06;  /* msg len */
1248                 h->omsg[2] = 0x04;  /* payload len */
1249                 h->omsg[3] = 0x00;  /* payload len */
1250                 h->omsg[4] = 0x1f;  /* Response type */
1251                 h->omsg[5] = 0x01;  /* parameter len */
1252                 h->omsg[6] = 0x00;  /* parameter len */
1253                 h->omsg[7] = cause;  /* CONFIRM or error */
1254                 sms_messagetx (h);
1255                 break;
1256
1257         case DLL2_SMS_NACK:     /* Protocol 2: SMS_NAK */
1258                 h->omsg[0] = DLL2_SMS_REL;  /* SMS_REL */
1259                 h->omsg[1] = 0x00;  /* msg len */
1260                 sms_messagetx (h);
1261                 break;
1262
1263         case DLL2_SMS_ACK0:
1264         case DLL2_SMS_ACK1:
1265                 /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */
1266                 if( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
1267                         /* a response to our Release, just hangup */
1268                         h->hangup = 1;          /* hangup */
1269                 } else {
1270                         /* XXX depending on what we are.. */
1271                         ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY");
1272                         sms_nextoutgoing (h);
1273                 }
1274                 break;
1275
1276         case DLL2_SMS_REL:      /* Protocol 2: SMS_REL (hangup req) */
1277                 h->omsg[0] = DLL2_ACK(h);
1278                 h->omsg[1] = 0;
1279                 sms_messagetx (h);
1280                 break;
1281         }
1282 }
1283
1284 /*! \brief compose a message for protocol 1 */
1285 static void sms_compose1(sms_t *h, int more)
1286 {
1287         unsigned int p = 2;     /* next byte to write. Skip type and len */
1288
1289         h->omsg[0] = 0x91;                /* SMS_DATA */
1290         if (h->smsc) {                   /* deliver */
1291                 h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
1292                 p += packaddress (h->omsg + p, h->oa);
1293                 h->omsg[p++] = h->pid;
1294                 h->omsg[p++] = h->dcs;
1295                 packdate (h->omsg + p, h->scts);
1296                 p += 7;
1297                 p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
1298         } else {                         /* submit */
1299                 h->omsg[p++] =
1300                         0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
1301                 if (h->mr < 0)
1302                         h->mr = message_ref++;
1303                 h->omsg[p++] = h->mr;
1304                 p += packaddress (h->omsg + p, h->da);
1305                 h->omsg[p++] = h->pid;
1306                 h->omsg[p++] = h->dcs;
1307                 if (h->vp) {             /* relative VP */
1308                         if (h->vp < 720)
1309                                 h->omsg[p++] = (h->vp + 4) / 5 - 1;
1310                         else if (h->vp < 1440)
1311                                 h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
1312                         else if (h->vp < 43200)
1313                                 h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
1314                         else if (h->vp < 635040)
1315                                 h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
1316                         else
1317                                 h->omsg[p++] = 255;             /* max */
1318                 }
1319                 p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
1320         }
1321         h->omsg[1] = p - 2;
1322 }
1323
1324 /*! \brief find and fill in next message, or send a REL if none waiting */
1325 static void sms_nextoutgoing (sms_t * h)
1326 {          
1327         char fn[100 + NAME_MAX] = "";
1328         DIR *d;
1329         char more = 0;
1330
1331         *h->da = *h->oa = '\0';                 /* clear destinations */
1332         ast_copy_string (fn, spool_dir, sizeof (fn));
1333         mkdir(fn, 0777);                        /* ensure it exists */
1334         h->rx = 0;                              /* outgoing message */
1335         snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? "mttx" : "motx");
1336         mkdir (fn, 0777);                       /* ensure it exists */
1337         d = opendir (fn);
1338         if (d) {
1339                 struct dirent *f = readdirqueue (d, h->queue);
1340                 if (f) {
1341                         snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", f->d_name);
1342                         sms_readfile (h, fn);
1343                         if (readdirqueue (d, h->queue))
1344                                 more = 1;                         /* more to send */
1345                 }
1346                 closedir (d);
1347         }
1348         if (*h->da || *h->oa) {                                                                  /* message to send */
1349                 if (h->protocol==2)
1350                         sms_compose2(h, more);
1351                 else
1352                         sms_compose1(h,more);
1353         } else {                                /* no message */
1354                 if (h->protocol==2) {
1355                         h->omsg[0] = 0x17;      /* SMS_REL */
1356                         h->omsg[1] = 0;
1357                 } else {
1358                         h->omsg[0] = 0x94;      /* SMS_REL */
1359                         h->omsg[1] = 0;
1360                 }
1361         }
1362         sms_messagetx (h);
1363 }
1364
1365 #define DIR_RX 1
1366 #define DIR_TX 2
1367 static void sms_debug (int dir, sms_t *h)
1368 {
1369         char txt[259 * 3 + 1];
1370         char *p = txt;                                           /* always long enough */
1371         unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
1372         int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
1373         int q = 0;
1374         while (q < n && q < 30) {
1375                 sprintf (p, " %02X", msg[q++]);
1376                 p += 3;
1377         }
1378         if (q < n)
1379                 sprintf (p, "...");
1380         if (option_verbose > 2)
1381                 ast_verbose (VERBOSE_PREFIX_3 "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
1382 }
1383
1384
1385 static void sms_messagerx(sms_t * h)
1386 {
1387         int cause;
1388
1389         sms_debug (DIR_RX, h);
1390         if (h->protocol == 2) {
1391                 sms_messagerx2(h);
1392                 return;
1393         }
1394         /* parse incoming message for Protocol 1 */
1395         switch (h->imsg[0]) {
1396         case 0x91:                                              /* SMS_DATA */
1397                         cause = sms_handleincoming (h);
1398                         if (!cause) {
1399                                 sms_log (h, 'Y');
1400                                 h->omsg[0] = 0x95;  /* SMS_ACK */
1401                                 h->omsg[1] = 0x02;
1402                                 h->omsg[2] = 0x00;  /* deliver report */
1403                                 h->omsg[3] = 0x00;  /* no parameters */
1404                         } else {                                                         /* NACK */
1405                                 sms_log (h, 'N');
1406                                 h->omsg[0] = 0x96;  /* SMS_NACK */
1407                                 h->omsg[1] = 3;
1408                                 h->omsg[2] = 0;   /* delivery report */
1409                                 h->omsg[3] = cause; /* cause */
1410                                 h->omsg[4] = 0;   /* no parameters */
1411                         }
1412                         sms_messagetx (h);
1413                         break;
1414
1415         case 0x92:                                              /* SMS_ERROR */
1416                 h->err = 1;
1417                 sms_messagetx (h);                /* send whatever we sent again */
1418                 break;
1419         case 0x93:                                              /* SMS_EST */
1420                 sms_nextoutgoing (h);
1421                 break;
1422         case 0x94:                                              /* SMS_REL */
1423                 h->hangup = 1;                          /* hangup */
1424                 break;
1425         case 0x95:                                              /* SMS_ACK */
1426                 sms_log (h, 'Y');
1427                 sms_nextoutgoing (h);
1428                 break;
1429         case 0x96:                                              /* SMS_NACK */
1430                 h->err = 1;
1431                 sms_log (h, 'N');
1432                 sms_nextoutgoing (h);
1433                 break;
1434         default:                                                  /* Unknown */
1435                 h->omsg[0] = 0x92;                /* SMS_ERROR */
1436                 h->omsg[1] = 1;
1437                 h->omsg[2] = 3;                   /* unknown message type; */
1438                 sms_messagetx (h);
1439                 break;
1440         }
1441 }
1442
1443 static void sms_messagetx(sms_t * h)
1444 {
1445         unsigned char c = 0, p;
1446         int len = h->omsg[1] + 2;       /* total message length excluding checksum */
1447
1448         for (p = 0; p < len; p++)       /* compute checksum */
1449                 c += h->omsg[p];
1450         h->omsg[len] = 0 - c;           /* actually, (256 - (c & 0fxx)) & 0xff) */
1451         sms_debug(DIR_TX, h);
1452         h->framenumber++;       /* Proto 2 */
1453         h->obyte = 1;           /* send mark ('1') at the beginning */
1454         h->opause = 200;
1455         /* Change the initial message delay. BT requires 300ms,
1456          * but for others this might be way too much and the phone
1457          * could time out. XXX make it configurable.
1458          */
1459         if (h->omsg[0] == 0x93)
1460                 h->opause = 8 * h->opause_0;    /* initial message delay */
1461         h->obytep = 0;
1462         h->obitp = 0;
1463         if (h->protocol == 2) {
1464                 h->oseizure = 300;      /* Proto 2: 300bits (or more ?) */
1465                 h->obyte = 0;           /* Seizure starts with  space (0) */
1466                 h->opause = 400;
1467         } else {
1468                 h->oseizure = 0;        /* Proto 1: No seizure */
1469         }
1470         /* Note - setting osync triggers the generator */
1471         h->osync = OSYNC_BITS;                  /* 80 sync bits */
1472         h->obyten = len + 1;            /* bytes to send (including checksum) */
1473 }
1474
1475 /*!
1476  * outgoing data are produced by this generator function, that reads from
1477  * the descriptor whether it has data to send and which ones.
1478  */
1479 static int sms_generate (struct ast_channel *chan, void *data, int len, int samples)
1480 {
1481         struct ast_frame f = { 0 };
1482 #define MAXSAMPLES (800)
1483         output_t *buf;
1484         sms_t *h = data;
1485         int i;
1486
1487         if (samples > MAXSAMPLES) {
1488                 ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
1489                          MAXSAMPLES, samples);
1490                 samples = MAXSAMPLES;
1491         }
1492         len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET;
1493         buf = alloca(len);
1494
1495         f.frametype = AST_FRAME_VOICE;
1496         f.subclass = __OUT_FMT;
1497         f.datalen = samples * sizeof(*buf);
1498         f.offset = AST_FRIENDLY_OFFSET;
1499         f.mallocd = 0;
1500         f.data = buf;
1501         f.samples = samples;
1502         f.src = "app_sms";
1503         /* create a buffer containing the digital sms pattern */
1504         for (i = 0; i < samples; i++) {
1505                 buf[i] = wave_out[0];   /* default is silence */
1506
1507                 if (h->opause)
1508                         h->opause--;
1509                 else if (h->obyten || h->osync) {       /* sending data */
1510                         buf[i] = wave_out[h->ophase];
1511                         h->ophase += (h->obyte & 1) ? 13 : 21;  /* compute next phase */
1512                         if (h->ophase >= 80)
1513                                 h->ophase -= 80;
1514                         if ((h->ophasep += 12) >= 80) {         /* time to send the next bit */
1515                                 h->ophasep -= 80;
1516                                 if (h->oseizure > 0) {           /* sending channel seizure (proto 2) */
1517                                         h->oseizure--;
1518                                         h->obyte ^= 1;  /* toggle low bit */
1519                                 } else if (h->osync) {
1520                                         h->obyte = 1;   /* send mark as sync bit */
1521                                         h->osync--;             /* sending sync bits */
1522                                         if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
1523                                                 h->obytep = h->obyten = 0;      /* we are done */
1524                                         }
1525                                 } else {
1526                                         h->obitp++;
1527                                         if (h->obitp == 1)
1528                                                 h->obyte = 0; /* start bit; */
1529                                         else if (h->obitp == 2)
1530                                                 h->obyte = h->omsg[h->obytep];
1531                                         else if (h->obitp == 10) {
1532                                                 h->obyte = 1; /* stop bit */
1533                                                 h->obitp = 0;
1534                                                 h->obytep++;
1535                                                 if (h->obytep == h->obyten) {
1536                                                         h->obytep = h->obyten = 0; /* sent */
1537                                                         h->osync = 10;    /* trailing marks */
1538                                                 }
1539                                         } else
1540                                                 h->obyte >>= 1;
1541                                 }
1542                         }
1543                 }
1544         }
1545         if (ast_write (chan, &f) < 0) {
1546                 ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror (errno));
1547                 return -1;
1548         }
1549         return 0;
1550 #undef MAXSAMPLES
1551 }
1552
1553 /*!
1554  * Just return the pointer to the descriptor that we received.
1555  */
1556 static void *sms_alloc (struct ast_channel *chan, void *sms_t_ptr)
1557 {
1558         return sms_t_ptr;
1559 }
1560
1561 static void sms_release (struct ast_channel *chan, void *data)
1562 {
1563         return; /* nothing to do here. */
1564 }
1565
1566 static struct ast_generator smsgen = {
1567         .alloc = sms_alloc,
1568         .release = sms_release,
1569         .generate = sms_generate,
1570 };
1571
1572 /*!
1573  * Process an incoming frame, trying to detect the carrier and
1574  * decode the message. The two frequencies are 1300 and 2100 Hz.
1575  * The decoder detects the amplitude of the signal over the last
1576  * few samples, filtering the absolute values with a lowpass filter.
1577  * If the magnitude (h->imag) is large enough, multiply the signal
1578  * by the two carriers, and compute the amplitudes m0 and m1.
1579  * Record the current sample as '0' or '1' depending on which one is greater.
1580  * The last 3 bits are stored in h->ibith, with the count of '1'
1581  * bits in h->ibitt.
1582  * XXX the rest is to be determined.
1583  */
1584 static void sms_process(sms_t * h, int samples, signed short *data)
1585 {
1586         int bit;
1587
1588         /*
1589          * Ignore incoming audio while a packet is being transmitted,
1590          * the protocol is half-duplex.
1591          * Unfortunately this means that if the outbound and incoming
1592          * transmission overlap (which is an error condition anyways),
1593          * we may miss some data and this makes debugging harder.
1594          */
1595         if (h->obyten || h->osync)
1596                 return;
1597         for ( ; samples-- ; data++) {
1598                 unsigned long long m0, m1;
1599                 if (abs (*data) > h->imag)
1600                         h->imag = abs (*data);
1601                 else
1602                         h->imag = h->imag * 7 / 8;
1603                 if (h->imag <= 500) {           /* below [arbitrary] threahold: lost carrier */
1604                         if (h->idle++ == 80000) {                /* nothing happening */
1605                                 ast_log (LOG_NOTICE, "No data, hanging up\n");
1606                                 h->hangup = 1;
1607                                 h->err = 1;
1608                         }
1609                         if (h->ierr) {          /* error */
1610                                 ast_log (LOG_NOTICE, "Error %d, hanging up\n", h->ierr);
1611                                 /* Protocol 1 */
1612                                 h->err = 1;
1613                                 h->omsg[0] = 0x92;  /* error */
1614                                 h->omsg[1] = 1;
1615                                 h->omsg[2] = h->ierr;
1616                                 sms_messagetx (h);  /* send error */
1617                         }
1618                         h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1619                         continue;
1620                 }
1621                 h->idle = 0;
1622
1623                 /* multiply signal by the two carriers. */
1624                 h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
1625                 h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
1626                 h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
1627                 h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
1628                 /* compute the amplitudes */
1629                 m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
1630                 m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
1631
1632                 /* advance the sin/cos pointers */
1633                 if ((h->ips0 += 21) >= 80)
1634                         h->ips0 -= 80;
1635                 if ((h->ipc0 += 21) >= 80)
1636                         h->ipc0 -= 80;
1637                 if ((h->ips1 += 13) >= 80)
1638                         h->ips1 -= 80;
1639                 if ((h->ipc1 += 13) >= 80)
1640                         h->ipc1 -= 80;
1641
1642                 /* set new bit to 1 or 0 depending on which value is stronger */
1643                 h->ibith <<= 1;
1644                 if (m1 > m0)
1645                         h->ibith |= 1;
1646                 if (h->ibith & 8)
1647                         h->ibitt--;
1648                 if (h->ibith & 1)
1649                         h->ibitt++;
1650                 bit = ((h->ibitt > 1) ? 1 : 0);
1651                 if (bit != h->ibitl)
1652                         h->ibitc = 1;
1653                 else
1654                         h->ibitc++;
1655                 h->ibitl = bit;
1656                 if (!h->ibitn && h->ibitc == 4 && !bit) {
1657                         h->ibitn = 1;
1658                         h->iphasep = 0;
1659                 }
1660                 if (bit && h->ibitc == 200) {                                            /* sync, restart message */
1661                         /* Protocol 2: empty connnection ready (I am master) */
1662                         if(h->framenumber<0 && h->ibytec>=160 && !memcmp(h->imsg,"UUUUUUUUUUUUUUUUUUUU",20)) {
1663                                 h->framenumber = 1;
1664                                 if (option_verbose > 2)
1665                                         ast_verbose (VERBOSE_PREFIX_3 "SMS protocol 2 detected\n");
1666                                 h->protocol = 2;
1667                                 h->imsg[0] = 0xff;      /* special message (fake) */
1668                                 h->imsg[1] = h->imsg[2] = 0x00;
1669                                 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1670                                 sms_messagerx (h);
1671                         }
1672                         h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
1673                 }
1674                 if (h->ibitn) {
1675                         h->iphasep += 12;
1676                         if (h->iphasep >= 80) {                                 /* next bit */
1677                                 h->iphasep -= 80;
1678                                 if (h->ibitn++ == 9) {                          /* end of byte */
1679                                         if (!bit) { /* bad stop bit */
1680                                                 ast_log(LOG_NOTICE, "bad stop bit");
1681                                                 h->ierr = 0xFF; /* unknown error */
1682                                         } else {
1683                                                 if (h->ibytep < sizeof (h->imsg)) {
1684                                                         h->imsg[h->ibytep] = h->ibytev;
1685                                                         h->ibytec += h->ibytev;
1686                                                         h->ibytep++;
1687                                                 } else if (h->ibytep == sizeof (h->imsg)) {
1688                                                         ast_log(LOG_NOTICE, "msg too large");
1689                                                         h->ierr = 2; /* bad message length */
1690                                                 }
1691                                                 if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
1692                                                         if (!h->ibytec)
1693                                                                 sms_messagerx (h);
1694                                                         else {
1695                                                                 ast_log(LOG_NOTICE, "bad checksum");
1696                                                                 h->ierr = 1;            /* bad checksum */
1697                                                         }
1698                                                 }
1699                                         }
1700                                         h->ibitn = 0;
1701                                 }
1702                                 h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
1703                         }
1704                 }
1705         }
1706 }
1707
1708 /*
1709  * Standard argument parsing:
1710  *      - one enum for the flags we recognise,
1711  *      - one enum for argument indexes
1712  *      - AST_APP_OPTIONS() to drive the parsing routine
1713  *      - in the function, AST_DECLARE_APP_ARGS(...) for the arguments.
1714  */
1715 enum {
1716         OPTION_BE_SMSC  = (1 << 0),     /* act as sms center */
1717         OPTION_ANSWER   = (1 << 1),     /* answer on incoming calls */
1718         OPTION_TWO      = (1 << 2),     /* Use Protocol Two */
1719         OPTION_PAUSE    = (1 << 3),     /* pause before sending data, in ms */
1720         OPTION_SRR      = (1 << 4),     /* set srr */
1721         OPTION_DCS      = (1 << 5),     /* set dcs */
1722 } sms_flags;
1723
1724 enum {
1725         OPTION_ARG_PAUSE = 0,
1726         OPTION_ARG_ARRAY_SIZE
1727 } sms_opt_args;
1728
1729 AST_APP_OPTIONS(sms_options, {
1730         AST_APP_OPTION('s', OPTION_BE_SMSC),
1731         AST_APP_OPTION('a', OPTION_ANSWER),
1732         AST_APP_OPTION('t', OPTION_TWO),
1733         AST_APP_OPTION('r', OPTION_SRR),
1734         AST_APP_OPTION('o', OPTION_DCS),
1735         AST_APP_OPTION_ARG('p', OPTION_PAUSE, OPTION_ARG_PAUSE),
1736         } );
1737
1738 static int sms_exec (struct ast_channel *chan, void *data)
1739 {
1740         int res = -1;
1741         struct ast_module_user *u;
1742         sms_t h = { 0 };
1743         /* argument parsing support */
1744         struct ast_flags sms_flags;
1745         char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE];
1746         char *p;
1747         AST_DECLARE_APP_ARGS(sms_args,
1748                 AST_APP_ARG(queue);
1749                 AST_APP_ARG(options);
1750                 AST_APP_ARG(addr);
1751                 AST_APP_ARG(body);
1752         );
1753
1754         if (!data) {
1755                 ast_log (LOG_ERROR, "Requires queue name at least\n");
1756                 return -1;
1757         }
1758
1759         parse = ast_strdupa(data);      /* create a local copy */
1760         AST_STANDARD_APP_ARGS(sms_args, parse);
1761         if (sms_args.argc > 1)
1762                 ast_app_parse_options(sms_options, &sms_flags, sms_opts, sms_args.options);
1763
1764         ast_verbose("sms argc %d queue <%s> opts <%s> addr <%s> body <%s>\n",
1765                 sms_args.argc, S_OR(sms_args.queue, ""),
1766                 S_OR(sms_args.options, ""),
1767                 S_OR(sms_args.addr, ""),
1768                 S_OR(sms_args.body, "") );
1769
1770         u = ast_module_user_add(chan);
1771         h.ipc0 = h.ipc1 = 20;           /* phase for cosine */
1772         h.dcs = 0xF1;                   /* default */
1773
1774         if (chan->cid.cid_num)
1775                 ast_copy_string (h.cli, chan->cid.cid_num, sizeof (h.cli));
1776
1777         if (ast_strlen_zero(sms_args.queue)) {
1778                 ast_log (LOG_ERROR, "Requires queue name\n");
1779                 goto done;
1780         }
1781         if (strlen(sms_args.queue) >= sizeof(h.queue)) {
1782                 ast_log (LOG_ERROR, "Queue name too long\n");
1783                 goto done;
1784         }
1785         ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue));
1786
1787         for (p = h.queue; *p; p++)
1788                 if (!isalnum (*p))
1789                         *p = '-';                         /* make very safe for filenames */
1790
1791         h.smsc = ast_test_flag(&sms_flags, OPTION_BE_SMSC);
1792         h.protocol = ast_test_flag(&sms_flags, OPTION_TWO) ? 2 : 1;
1793         if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE]))
1794                 h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
1795         if (h.opause_0 < 25 || h.opause_0 > 2000)
1796                 h.opause_0 = 300;       /* default 300ms */
1797         ast_verbose("initial delay %dms\n", h.opause_0);
1798
1799
1800         /* the following apply if there is an arg3/4 and apply to the created message file */
1801         if (ast_test_flag(&sms_flags, OPTION_SRR))
1802                 h.srr = 1;
1803         if (ast_test_flag(&sms_flags, OPTION_DCS))
1804                 h.dcs = 1;
1805 #if 0   
1806                 case '1':
1807                 case '2':
1808                 case '3':
1809                 case '4':
1810                 case '5':
1811                 case '6':
1812                 case '7':                                /* set the pid for saved local message */
1813                         h.pid = 0x40 + (*d & 0xF);
1814                         break;
1815                 }
1816 #endif
1817         if (sms_args.argc > 2) {
1818                 unsigned char *up;
1819
1820                 /* submitting a message, not taking call. */
1821                 /* deprecated, use smsq instead */
1822                 h.scts = time (0);
1823                 if (ast_strlen_zero(sms_args.addr) || strlen (sms_args.addr) >= sizeof (h.oa)) {
1824                         ast_log (LOG_ERROR, "Address too long %s\n", sms_args.addr);
1825                         goto done;
1826                 }
1827                 if (h.smsc)
1828                         ast_copy_string (h.oa, sms_args.addr, sizeof (h.oa));
1829                 else {
1830                         ast_copy_string (h.da, sms_args.addr, sizeof (h.da));
1831                         ast_copy_string (h.oa, h.cli, sizeof (h.oa));
1832                 }
1833                 h.udl = 0;
1834                 if (ast_strlen_zero(sms_args.body)) {
1835                         ast_log (LOG_ERROR, "Missing body for %s\n", sms_args.addr);
1836                         goto done;
1837                 }
1838                 up = (unsigned char *)sms_args.body;
1839                 while (*up && h.udl < SMSLEN)
1840                         h.ud[h.udl++] = utf8decode(&up);
1841                 if (is7bit (h.dcs) && packsms7 (0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1842                         ast_log (LOG_WARNING, "Invalid 7 bit GSM data\n");
1843                         goto done;
1844                 }
1845                 if (is8bit (h.dcs) && packsms8 (0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1846                         ast_log (LOG_WARNING, "Invalid 8 bit data\n");
1847                         goto done;
1848                 }
1849                 if (is16bit (h.dcs) && packsms16 (0, h.udhl, h.udh, h.udl, h.ud) < 0) {
1850                         ast_log (LOG_WARNING, "Invalid 16 bit data\n");
1851                         goto done;
1852                 }
1853                 h.rx = 0;                                 /* sent message */
1854                 h.mr = -1;
1855                 sms_writefile (&h);
1856                 res = h.err;
1857                 goto done;
1858         }
1859
1860         if (ast_test_flag(&sms_flags, OPTION_ANSWER)) {
1861                 h.framenumber = 1;             /* Proto 2 */
1862                 /* set up SMS_EST initial message */
1863                 if (h.protocol == 2) {
1864                         h.omsg[0] = DLL2_SMS_EST;
1865                         h.omsg[1] = 0;
1866                 } else {
1867                         h.omsg[0] = DLL1_SMS_EST | DLL1_SMS_COMPLETE;
1868                         h.omsg[1] = 0;
1869                 }
1870                 sms_messagetx (&h);
1871         }
1872
1873         if (chan->_state != AST_STATE_UP)
1874                 ast_answer (chan);
1875
1876         res = ast_set_write_format (chan, __OUT_FMT);
1877         if (res >= 0)
1878                 res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
1879         if (res < 0) {
1880                 ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
1881                 goto done;
1882         }
1883
1884         if ( (res = ast_activate_generator (chan, &smsgen, &h)) < 0) {
1885                 ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
1886                 goto done;
1887         }
1888
1889         /* Do our thing here */
1890         for (;;) {
1891                 struct ast_frame *f;
1892                 int i = ast_waitfor(chan, -1);
1893                 if (i < 0) {
1894                         ast_log(LOG_NOTICE, "waitfor failed\n");
1895                         break;
1896                 }
1897                 if (h.hangup) {
1898                         ast_log(LOG_NOTICE, "channel hangup\n");
1899                         break;
1900                 }
1901                 f = ast_read (chan);
1902                 if (!f) {
1903                         ast_log(LOG_NOTICE, "ast_read failed\n");
1904                         break;
1905                 }
1906                 if (f->frametype == AST_FRAME_VOICE) {
1907                         sms_process (&h, f->samples, f->data);
1908                 }
1909
1910                 ast_frfree (f);
1911         }
1912         res = h.err;    /* XXX */
1913
1914         sms_log (&h, '?');                        /* log incomplete message */
1915 done:
1916         ast_module_user_remove(u);
1917         return (res);
1918 }
1919
1920 static int unload_module(void)
1921 {
1922         int res;
1923
1924         res = ast_unregister_application (app);
1925         
1926         ast_module_user_hangup_all();
1927
1928         return res;     
1929 }
1930
1931 static int load_module(void)
1932 {
1933 #ifdef OUTALAW
1934         int p;
1935         for (p = 0; p < 80; p++)
1936                 wavea[p] = AST_LIN2A (wave[p]);
1937 #endif
1938         snprintf (log_file, sizeof (log_file), "%s/sms", ast_config_AST_LOG_DIR);
1939         snprintf (spool_dir, sizeof (spool_dir), "%s/sms", ast_config_AST_SPOOL_DIR);
1940         return ast_register_application (app, sms_exec, synopsis, descrip);
1941 }
1942
1943 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SMS/PSTN handler");