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