Sun Oct 16 2011 08:41:29

Asterisk developer's documentation


app_sms.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2004 - 2005, Adrian Kennard, rights assigned to Digium
00005  *
00006  * See http://www.asterisk.org for more information about
00007  * the Asterisk project. Please do not directly contact
00008  * any of the maintainers of this project for assistance;
00009  * the project provides a web site, mailing lists and IRC
00010  * channels for your use.
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU General Public License Version 2. See the LICENSE file
00014  * at the top of the source tree.
00015  */
00016 
00017 /*! \file
00018  *
00019  * \brief SMS application - ETSI ES 201 912 protocol 1 implementation
00020  * 
00021  * \par Development notes
00022  * \note The ETSI standards are available free of charge from ETSI at
00023  * http://pda.etsi.org/pda/queryform.asp
00024  *    Among the relevant documents here we have:
00025  *
00026  * ES 201 912  SMS for PSTN/ISDN
00027  * TS 123 040  Technical realization of SMS
00028  *
00029  * 
00030  * \ingroup applications
00031  *
00032  * \author Adrian Kennard (for the original protocol 1 code)
00033  * \author Filippo Grassilli (Hyppo) - protocol 2 support
00034  *       Not fully tested, under development
00035  */
00036 
00037 /*** MODULEINFO
00038    <support_level>extended</support_level>
00039  ***/
00040 
00041 #include "asterisk.h"
00042 
00043 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00044 
00045 #include <dirent.h>
00046 #include <ctype.h>
00047 #include <sys/stat.h>
00048 
00049 #include "asterisk/paths.h"  /* use ast_config_AST_SPOOL_DIR and LOG_DIR */
00050 #include "asterisk/lock.h"
00051 #include "asterisk/file.h"
00052 #include "asterisk/channel.h"
00053 #include "asterisk/pbx.h"
00054 #include "asterisk/module.h"
00055 #include "asterisk/alaw.h"
00056 #include "asterisk/callerid.h"
00057 #include "asterisk/utils.h"
00058 #include "asterisk/app.h"
00059 
00060 /*** DOCUMENTATION
00061    <application name="SMS" language="en_US">
00062       <synopsis>
00063          Communicates with SMS service centres and SMS capable analogue phones.
00064       </synopsis>
00065       <syntax>
00066          <parameter name="name" required="true">
00067             <para>The name of the queue used in <filename>/var/spool/asterisk/sms</filename></para>
00068          </parameter>
00069          <parameter name="options">
00070             <optionlist>
00071                <option name="a">
00072                   <para>Answer, i.e. send initial FSK packet.</para>
00073                </option>
00074                <option name="s">
00075                   <para>Act as service centre talking to a phone.</para>
00076                </option>
00077                <option name="t">
00078                   <para>Use protocol 2 (default used is protocol 1).</para>
00079                </option>
00080                <option name="p">
00081                   <para>Set the initial delay to N ms (default is <literal>300</literal>).
00082                   addr and body are a deprecated format to send messages out.</para>
00083                </option>
00084                <option name="r">
00085                   <para>Set the Status Report Request (SRR) bit.</para>
00086                </option>
00087                <option name="o">
00088                   <para>The body should be coded as octets not 7-bit symbols.</para>
00089                </option>
00090             </optionlist>
00091          </parameter>
00092          <parameter name="addr" />
00093          <parameter name="body" />
00094       </syntax>
00095       <description>
00096          <para>SMS handles exchange of SMS data with a call to/from SMS capable phone or SMS PSTN service center.
00097          Can send and/or receive SMS messages. Works to ETSI ES 201 912; compatible with BT SMS PSTN service in
00098          UK and Telecom Italia in Italy.</para>
00099          <para>Typical usage is to use to handle calls from the SMS service centre CLI, or to set up a call using
00100          <literal>outgoing</literal> or manager interface to connect service centre to SMS().</para>
00101          <para>"Messages are processed as per text file message queues. smsq (a separate software) is a command to
00102          generate message queues and send messages.</para>
00103          <note><para>The protocol has tight delay bounds. Please use short frames and disable/keep short the
00104          jitter buffer on the ATA to make sure that respones (ACK etc.) are received in time.</para></note>
00105       </description>
00106    </application>
00107  ***/
00108 
00109 /* #define OUTALAW */        /* enable this to output Alaw rather than linear */
00110 
00111 /* ToDo */
00112 /* Add full VP support */
00113 /* Handle status report messages (generation and reception) */
00114 /* Time zones on time stamps */
00115 /* user ref field */
00116 
00117 static volatile unsigned char message_ref;  /* arbitary message ref */
00118 static volatile unsigned int seq;           /* arbitrary message sequence number for unqiue files */
00119 
00120 static char log_file[255];
00121 
00122 static char *app = "SMS";
00123 
00124 /*
00125  * 80 samples of a single period of the wave. At 8000 Hz, it means these
00126  * are the samples of a 100 Hz signal.
00127  * To pick the two carriers (1300Hz for '1' and 2100 Hz for '0') used by
00128  * the modulation, we should take one every 13 and 21 samples respectively.
00129  */
00130 static const signed short wave[] = {
00131    0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
00132    5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
00133    0, -392, -782, -1167,
00134     -1545, -1913, -2270, -2612, -2939, -3247, -3536, -3802, -4045, -4263, -4455, -4619, -4755, -4862, -4938, -4985, -5000,
00135    -4985, -4938, -4862,
00136    -4755, -4619, -4455, -4263, -4045, -3802, -3536, -3247, -2939, -2612, -2270, -1913, -1545, -1167, -782, -392
00137 };
00138 
00139 #ifdef OUTALAW
00140 static unsigned char wavea[80];
00141 typedef unsigned char output_t;
00142 static const output_t *wave_out = wavea;    /* outgoing samples */
00143 #define __OUT_FMT AST_FORMAT_ALAW;
00144 #else
00145 typedef signed short output_t;
00146 static const output_t *wave_out = wave;     /* outgoing samples */
00147 #define __OUT_FMT AST_FORMAT_SLINEAR
00148 #endif
00149 
00150 #define OSYNC_BITS   80                      /* initial sync bits */
00151 
00152 /*!
00153  * The SMS spec ETSI ES 201 912 defines two protocols with different message types.
00154  * Also note that the high bit is used to indicate whether the message
00155  * is complete or not, but in two opposite ways:
00156  * for Protocol 1, 0x80 means that the message is complete;
00157  * for Protocol 2, 0x00 means that the message is complete;
00158  */
00159 enum message_types {
00160    DLL_SMS_MASK        = 0x7f,             /* mask for the valid bits */
00161 
00162    /* Protocol 1 values */
00163    DLL1_SMS_DATA       = 0x11,             /* data packet */
00164    DLL1_SMS_ERROR      = 0x12,
00165    DLL1_SMS_EST        = 0x13,             /* start the connection */
00166    DLL1_SMS_REL        = 0x14,             /* end the connection */
00167    DLL1_SMS_ACK        = 0x15,
00168    DLL1_SMS_NACK       = 0x16,
00169 
00170    DLL1_SMS_COMPLETE   = 0x80,             /* packet is complete */
00171    DLL1_SMS_MORE       = 0x00,             /* more data to follow */
00172 
00173    /* Protocol 2 values */
00174    DLL2_SMS_EST        = 0x7f,             /* magic number. No message body */
00175    DLL2_SMS_INFO_MO    = 0x10,
00176    DLL2_SMS_INFO_MT    = 0x11,
00177    DLL2_SMS_INFO_STA   = 0x12,
00178    DLL2_SMS_NACK       = 0x13,
00179    DLL2_SMS_ACK0       = 0x14,             /* ack even-numbered frame */
00180    DLL2_SMS_ACK1       = 0x15,             /* ack odd-numbered frame */
00181    DLL2_SMS_ENQ        = 0x16,
00182    DLL2_SMS_REL        = 0x17,             /* end the connection */
00183 
00184    DLL2_SMS_COMPLETE   = 0x00,             /* packet is complete */
00185    DLL2_SMS_MORE       = 0x80,             /* more data to follow */
00186 };
00187 
00188 /* SMS 7 bit character mapping to UCS-2 */
00189 static const unsigned short defaultalphabet[] = {
00190    0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
00191    0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
00192    0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
00193    0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
00194    ' ', '!', '"', '#', 164, '%', '&', 39, '(', ')', '*', '+', ',', '-', '.', '/',
00195    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
00196    161, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
00197    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 196, 214, 209, 220, 167,
00198    191, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
00199    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 228, 246, 241, 252, 224,
00200 };
00201 
00202 static const unsigned short escapes[] = {
00203    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x000C, 0, 0, 0, 0, 0,
00204    0, 0, 0, 0, 0x005E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00205    0, 0, 0, 0, 0, 0, 0, 0, 0x007B, 0x007D, 0, 0, 0, 0, 0, 0x005C,
00206    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x005B, 0x007E, 0x005D, 0,
00207    0x007C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00208    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00209    0, 0, 0, 0, 0, 0x20AC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00210    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00211 };
00212 
00213 #define SMSLEN      160          /*!< max SMS length */
00214 #define SMSLEN_8    140          /*!< max SMS length for 8-bit char */
00215 
00216 typedef struct sms_s {
00217    unsigned char hangup;        /*!< we are done... */
00218    unsigned char err;           /*!< set for any errors */
00219    unsigned char sent_rel:1;     /*!< have sent REL message... */
00220    unsigned char smsc:1;        /*!< we are SMSC */
00221    unsigned char rx:1;          /*!< this is a received message */
00222    char queue[30];              /*!< queue name */
00223    char oa[20];                 /*!< originating address */
00224    char da[20];                 /*!< destination address */
00225    struct timeval scts;         /*!< time stamp, UTC */
00226    unsigned char pid;           /*!< protocol ID */
00227    unsigned char dcs;           /*!< data coding scheme */
00228    short mr;                    /*!< message reference - actually a byte, but use -1 for not set */
00229    int udl;                     /*!< user data length */
00230    int udhl;                    /*!< user data header length */
00231    unsigned char srr:1;         /*!< Status Report request */
00232    unsigned char udhi:1;        /*!< User Data Header required, even if length 0 */
00233    unsigned char rp:1;          /*!< Reply Path */
00234    unsigned int vp;             /*!< validity period in minutes, 0 for not set */
00235    unsigned short ud[SMSLEN];   /*!< user data (message), UCS-2 coded */
00236    unsigned char udh[SMSLEN];   /*!< user data header */
00237    char cli[20];                /*!< caller ID */
00238    unsigned char ophase;        /*!< phase (0-79) for 0 and 1 frequencies (1300Hz and 2100Hz) */
00239    unsigned char ophasep;       /*!< phase (0-79) for 1200 bps */
00240    unsigned char obyte;         /*!< byte being sent */
00241    unsigned int opause;         /*!< silent pause before sending (in sample periods) */
00242    unsigned char obitp;         /*!< bit in byte */
00243    unsigned char osync;         /*!< sync bits to send */
00244    unsigned char obytep;        /*!< byte in data */
00245    unsigned char obyten;        /*!< bytes in data */
00246    unsigned char omsg[256];     /*!< data buffer (out) */
00247    unsigned char imsg[250];     /*!< data buffer (in) */
00248    signed long long ims0,
00249       imc0,
00250       ims1,
00251       imc1;                    /*!< magnitude averages sin/cos 0/1 */
00252    unsigned int idle;
00253    unsigned short imag;         /*!< signal level */
00254    unsigned char ips0;          /*!< phase sin for bit 0, start at  0 inc by 21 mod 80 */
00255    unsigned char ips1;          /*!< phase cos for bit 0, start at 20 inc by 21 mod 80 */
00256    unsigned char ipc0;          /*!< phase sin for bit 1, start at  0 inc by 13 mod 80 */
00257    unsigned char ipc1;          /*!< phase cos for bit 1, start at 20 inc by 13 mod 80 */
00258    unsigned char ibitl;         /*!< last bit */
00259    unsigned char ibitc;         /*!< bit run length count */
00260    unsigned char iphasep;       /*!< bit phase (0-79) for 1200 bps */
00261    unsigned char ibitn;         /*!< bit number in byte being received */
00262    unsigned char ibytev;        /*!< byte value being received */
00263    unsigned char ibytep;        /*!< byte pointer in message */
00264    unsigned char ibytec;        /*!< byte checksum for message */
00265    unsigned char ierr;          /*!< error flag */
00266    unsigned char ibith;         /*!< history of last bits */
00267    unsigned char ibitt;         /*!< total of 1's in last 3 bytes */
00268    /* more to go here */
00269 
00270    int opause_0;                /*!< initial delay in ms, p() option */
00271    int protocol;                /*!< ETSI SMS protocol to use (passed at app call) */
00272    int oseizure;                /*!< protocol 2: channel seizure bits to send */
00273    int framenumber;             /*!< protocol 2: frame number (for sending ACK0 or ACK1) */
00274    char udtxt[SMSLEN];          /*!< user data (message), PLAIN text */
00275 } sms_t;
00276 
00277 /* different types of encoding */
00278 #define is7bit(dcs)  ( ((dcs) & 0xC0) ? (!((dcs) & 4) ) : (((dcs) & 0xc) == 0) )
00279 #define is8bit(dcs)  ( ((dcs) & 0xC0) ? ( ((dcs) & 4) ) : (((dcs) & 0xc) == 4) )
00280 #define is16bit(dcs) ( ((dcs) & 0xC0) ? 0               : (((dcs) & 0xc) == 8) )
00281 
00282 static void sms_messagetx(sms_t *h);
00283 
00284 /*! \brief copy number, skipping non digits apart from leading + */
00285 static void numcpy(char *d, char *s)
00286 {
00287    if (*s == '+') {
00288       *d++ = *s++;
00289    }
00290    while (*s) {
00291       if (isdigit(*s)) {
00292          *d++ = *s;
00293       }
00294       s++;
00295    }
00296    *d = 0;
00297 }
00298 
00299 /*! \brief static, return a date/time in ISO format */
00300 static char *isodate(time_t t, char *buf, int len)
00301 {
00302    struct ast_tm tm;
00303    struct timeval local = { t, 0 };
00304    ast_localtime(&local, &tm, NULL);
00305    ast_strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
00306    return buf;
00307 }
00308 
00309 /*! \brief Reads next UCS character from NUL terminated UTF-8 string and advance pointer */
00310 /* for non valid UTF-8 sequences, returns character as is */
00311 /* Does not advance pointer for null termination */
00312 static long utf8decode(unsigned char **pp)
00313 {
00314    unsigned char *p = *pp;
00315    if (!*p) {
00316       return 0;                           /* null termination of string */
00317    }
00318    (*pp)++;
00319    if (*p < 0xC0) {
00320       return *p;                          /* ascii or continuation character */
00321    }
00322    if (*p < 0xE0) {
00323       if (*p < 0xC2 || (p[1] & 0xC0) != 0x80) {
00324          return *p;                      /* not valid UTF-8 */
00325       }
00326       (*pp)++;
00327       return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
00328       }
00329    if (*p < 0xF0) {
00330       if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80) {
00331          return *p;                      /* not valid UTF-8 */
00332       }
00333       (*pp) += 2;
00334       return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
00335    }
00336    if (*p < 0xF8) {
00337       if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80) {
00338          return *p;                      /* not valid UTF-8 */
00339       }
00340       (*pp) += 3;
00341       return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
00342    }
00343    if (*p < 0xFC) {
00344       if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00345          || (p[4] & 0xC0) != 0x80) {
00346          return *p;                      /* not valid UTF-8 */
00347       }
00348       (*pp) += 4;
00349       return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
00350    }
00351    if (*p < 0xFE) {
00352       if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00353          || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80) {
00354          return *p;                      /* not valid UTF-8 */
00355       }
00356       (*pp) += 5;
00357       return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
00358    }
00359    return *p;                              /* not sensible */
00360 }
00361 
00362 /*! \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 */
00363 /* The return value is the number of septets packed in to o, which is internally limited to SMSLEN */
00364 /* o can be null, in which case this is used to validate or count only */
00365 /* if the input contains invalid characters then the return value is -1 */
00366 static int packsms7(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00367 {
00368    unsigned char p = 0;                    /* output pointer (bytes) */
00369    unsigned char b = 0;                    /* bit position */
00370    unsigned char n = 0;                    /* output character count */
00371    unsigned char dummy[SMSLEN];
00372 
00373    if (o == NULL) {                        /* output to a dummy buffer if o not set */
00374       o = dummy;
00375    }
00376 
00377    if (udhl) {                             /* header */
00378       o[p++] = udhl;
00379       b = 1;
00380       n = 1;
00381       while (udhl--) {
00382          o[p++] = *udh++;
00383          b += 8;
00384          while (b >= 7) {
00385             b -= 7;
00386             n++;
00387          }
00388          if (n >= SMSLEN)
00389             return n;
00390       }
00391       if (b) {
00392          b = 7 - b;
00393          if (++n >= SMSLEN)
00394             return n;
00395       }                                   /* filling to septet boundary */
00396    }
00397    o[p] = 0;
00398    /* message */
00399    while (udl--) {
00400       long u;
00401       unsigned char v;
00402       u = *ud++;
00403       /* XXX 0 is invalid ? */
00404       /* look up in defaultalphabet[]. If found, v is the 7-bit code */
00405       for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
00406       if (v == 128 /* not found */ && u && n + 1 < SMSLEN) {
00407          /* if not found, look in the escapes table (we need 2 bytes) */
00408          for (v = 0; v < 128 && escapes[v] != u; v++);
00409          if (v < 128) { /* escaped sequence, esc + v */
00410             /* store the low (8-b) bits in o[p], the remaining bits in o[p+1] */
00411             o[p] |= (27 << b);          /* the low bits go into o[p] */ 
00412             b += 7;
00413             if (b >= 8) {
00414                b -= 8;
00415                p++;
00416                o[p] = (27 >> (7 - b));
00417             }
00418             n++;
00419          }
00420       }
00421       if (v == 128)
00422          return -1;                      /* invalid character */
00423       /* store, same as above */
00424       o[p] |= (v << b);
00425       b += 7;
00426       if (b >= 8) {
00427          b -= 8;
00428          p++;
00429          o[p] = (v >> (7 - b));
00430       }
00431       if (++n >= SMSLEN)
00432          return n;
00433    }
00434    return n;
00435 }
00436 
00437 /*! \brief takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud)
00438  * and packs in to o using 8 bit character codes.
00439  * The return value is the number of bytes packed in to o, which is internally limited to 140.
00440  * o can be null, in which case this is used to validate or count only.
00441  * if the input contains invalid characters then the return value is -1
00442  */
00443 static int packsms8(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00444 {
00445    unsigned char p = 0;
00446    unsigned char dummy[SMSLEN_8];
00447 
00448    if (o == NULL)
00449       o = dummy;
00450    /* header - no encoding */
00451    if (udhl) {
00452       o[p++] = udhl;
00453       while (udhl--) {
00454          o[p++] = *udh++;
00455          if (p >= SMSLEN_8) {
00456             return p;
00457          }
00458       }
00459    }
00460    while (udl--) {
00461       long u;
00462       u = *ud++;
00463       if (u < 0 || u > 0xFF) {
00464          return -1;                      /* not valid */
00465       }
00466       o[p++] = u;
00467       if (p >= SMSLEN_8) {
00468          return p;
00469       }
00470    }
00471    return p;
00472 }
00473 
00474 /*! \brief takes a binary header (udhl bytes at udh) and UCS-2 
00475    message (udl characters at ud) and packs in to o using 16 bit 
00476    UCS-2 character codes 
00477    The return value is the number of bytes packed in to o, which is 
00478    internally limited to 140 
00479    o can be null, in which case this is used to validate or count 
00480    only if the input contains invalid characters then 
00481    the return value is -1 */
00482 static int packsms16(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00483 {
00484    unsigned char p = 0;
00485    unsigned char dummy[SMSLEN_8];
00486 
00487    if (o == NULL) {
00488       o = dummy;
00489    }
00490    /* header - no encoding */
00491    if (udhl) {
00492       o[p++] = udhl;
00493       while (udhl--) {
00494          o[p++] = *udh++;
00495          if (p >= SMSLEN_8) {
00496             return p;
00497          }
00498       }
00499    }
00500    while (udl--) {
00501       long u;
00502       u = *ud++;
00503       o[p++] = (u >> 8);
00504       if (p >= SMSLEN_8) {
00505          return p - 1;                   /* could not fit last character */
00506       }
00507       o[p++] = u;
00508       if (p >= SMSLEN_8) {
00509          return p;
00510       }
00511    }
00512    return p;
00513 }
00514 
00515 /*! \brief general pack, with length and data, 
00516    returns number of bytes of target used */
00517 static int packsms(unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
00518 {
00519    unsigned char *p = base;
00520    if (udl == 0) {
00521       *p++ = 0;                           /* no user data */
00522    } else {
00523       
00524       int l = 0;
00525       if (is7bit(dcs)) {                  /* 7 bit */
00526          if ((l = packsms7(p + 1, udhl, udh, udl, ud)) < 0) {
00527             l = 0;
00528          }
00529          *p++ = l;
00530          p += (l * 7 + 7) / 8;
00531       } else if (is8bit(dcs)) {           /* 8 bit */
00532          if ((l = packsms8(p + 1, udhl, udh, udl, ud)) < 0) {
00533             l = 0;
00534          }
00535          *p++ = l;
00536          p += l;
00537       } else {                            /* UCS-2 */
00538          if ((l = packsms16(p + 1, udhl, udh, udl, ud)) < 0) {
00539             l = 0;
00540          }
00541          *p++ = l;
00542          p += l;
00543       }
00544    }
00545    return p - base;
00546 }
00547 
00548 
00549 /*! \brief pack a date and return */
00550 static void packdate(unsigned char *o, time_t w)
00551 {
00552    struct ast_tm t;
00553    struct timeval topack = { w, 0 };
00554    int z;
00555 
00556    ast_localtime(&topack, &t, NULL);
00557 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
00558    z = -t.tm_gmtoff / 60 / 15;
00559 #else
00560    z = timezone / 60 / 15;
00561 #endif
00562    *o++ = ((t.tm_year % 10) << 4) + (t.tm_year % 100) / 10;
00563    *o++ = (((t.tm_mon + 1) % 10) << 4) + (t.tm_mon + 1) / 10;
00564    *o++ = ((t.tm_mday % 10) << 4) + t.tm_mday / 10;
00565    *o++ = ((t.tm_hour % 10) << 4) + t.tm_hour / 10;
00566    *o++ = ((t.tm_min % 10) << 4) + t.tm_min / 10;
00567    *o++ = ((t.tm_sec % 10) << 4) + t.tm_sec / 10;
00568    if (z < 0) {
00569       *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
00570    } else {
00571       *o++ = ((z % 10) << 4) + z / 10;
00572    }
00573 }
00574 
00575 /*! \brief unpack a date and return */
00576 static struct timeval unpackdate(unsigned char *i)
00577 {
00578    struct ast_tm t;
00579 
00580    t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
00581    t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
00582    t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
00583    t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
00584    t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
00585    t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
00586    t.tm_isdst = 0;
00587    if (i[6] & 0x08) {
00588       t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00589    } else {
00590       t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00591    }
00592 
00593    return ast_mktime(&t, NULL);
00594 }
00595 
00596 /*! \brief unpacks bytes (7 bit encoding) at i, len l septets, 
00597    and places in udh and ud setting udhl and udl. udh not used 
00598    if udhi not set */
00599 static void unpacksms7(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00600 {
00601    unsigned char b = 0, p = 0;
00602    unsigned short *o = ud;
00603    *udhl = 0;
00604    if (udhi && l) {                        /* header */
00605       int h = i[p];
00606       *udhl = h;
00607       if (h) {
00608          b = 1;
00609          p++;
00610          l--;
00611          while (h-- && l) {
00612             *udh++ = i[p++];
00613             b += 8;
00614             while (b >= 7) {
00615                b -= 7;
00616                l--;
00617                if (!l) {
00618                   break;
00619                }
00620             }
00621          }
00622          /* adjust for fill, septets */
00623          if (b) {
00624             b = 7 - b;
00625             l--;
00626          }
00627       }
00628    }
00629    while (l--) {
00630       unsigned char v;
00631       if (b < 2) {
00632          v = ((i[p] >> b) & 0x7F);       /* everything in one byte */
00633       } else {
00634          v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
00635       }
00636       b += 7;
00637       if (b >= 8) {
00638          b -= 8;
00639          p++;
00640       }
00641       /* 0x00A0 is the encoding of ESC (27) in defaultalphabet */
00642       if (o > ud && o[-1] == 0x00A0 && escapes[v]) {
00643          o[-1] = escapes[v];
00644       } else {
00645          *o++ = defaultalphabet[v];
00646       }
00647    }
00648    *udl = (o - ud);
00649 }
00650 
00651 /*! \brief unpacks bytes (8 bit encoding) at i, len l septets, 
00652  *  and places in udh and ud setting udhl and udl. udh not used 
00653  *  if udhi not set.
00654  */
00655 static void unpacksms8(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00656 {
00657    unsigned short *o = ud;
00658    *udhl = 0;
00659    if (udhi) {
00660       int n = *i;
00661       *udhl = n;
00662       if (n) {
00663          i++;
00664          l--;
00665          while (l && n) {
00666             l--;
00667             n--;
00668             *udh++ = *i++;
00669          }
00670       }
00671    }
00672    while (l--) {
00673       *o++ = *i++;                        /* not to UTF-8 as explicitly 8 bit coding in DCS */
00674    }
00675    *udl = (o - ud);
00676 }
00677 
00678 /*! \brief unpacks bytes (16 bit encoding) at i, len l septets,
00679     and places in udh and ud setting udhl and udl. 
00680    udh not used if udhi not set */
00681 static void unpacksms16(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00682 {
00683    unsigned short *o = ud;
00684    *udhl = 0;
00685    if (udhi) {
00686       int n = *i;
00687       *udhl = n;
00688       if (n) {
00689          i++;
00690          l--;
00691          while (l && n) {
00692             l--;
00693             n--;
00694             *udh++ = *i++;
00695          }
00696       }
00697    }
00698    while (l--) {
00699       int v = *i++;
00700       if (l--) {
00701          v = (v << 8) + *i++;
00702       }
00703       *o++ = v;
00704    }
00705    *udl = (o - ud);
00706 }
00707 
00708 /*! \brief general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length */
00709 static int unpacksms(unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00710 {
00711    int l = *i++;
00712    if (is7bit(dcs)) {
00713       unpacksms7(i, l, udh, udhl, ud, udl, udhi);
00714       l = (l * 7 + 7) / 8;                /* adjust length to return */
00715    } else if (is8bit(dcs)) {
00716       unpacksms8(i, l, udh, udhl, ud, udl, udhi);
00717    } else {
00718       unpacksms16(i, l, udh, udhl, ud, udl, udhi);
00719    }
00720    return l + 1;
00721 }
00722 
00723 /*! \brief unpack an address from i, return byte length, unpack to o */
00724 static unsigned char unpackaddress(char *o, unsigned char *i)
00725 {
00726    unsigned char l = i[0], p;
00727    if (i[1] == 0x91) {
00728       *o++ = '+';
00729    }
00730    for (p = 0; p < l; p++) {
00731       if (p & 1) {
00732          *o++ = (i[2 + p / 2] >> 4) + '0';
00733       } else {
00734          *o++ = (i[2 + p / 2] & 0xF) + '0';
00735       }
00736    }
00737    *o = 0;
00738    return (l + 5) / 2;
00739 }
00740 
00741 /*! \brief store an address at o, and return number of bytes used */
00742 static unsigned char packaddress(unsigned char *o, char *i)
00743 {
00744    unsigned char p = 2;
00745    o[0] = 0;                               /* number of bytes */
00746    if (*i == '+') {                        /* record as bit 0 in byte 1 */
00747       i++;
00748       o[1] = 0x91;
00749    } else {
00750       o[1] = 0x81;
00751    }
00752    for ( ; *i ; i++) {
00753       if (!isdigit(*i)) {                 /* ignore non-digits */
00754          continue;
00755       }
00756       if (o[0] & 1) {
00757          o[p++] |= ((*i & 0xF) << 4);
00758       } else {
00759          o[p] = (*i & 0xF);
00760       }
00761       o[0]++;
00762    }
00763    if (o[0] & 1) {
00764       o[p++] |= 0xF0;                     /* pad */
00765    }
00766    return p;
00767 }
00768 
00769 /*! \brief Log the output, and remove file */
00770 static void sms_log(sms_t * h, char status)
00771 {
00772    int o;
00773 
00774    if (*h->oa == '\0' && *h->da == '\0') {
00775       return;
00776    }
00777    o = open(log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE);
00778    if (o >= 0) {
00779       char line[1000], mrs[3] = "", *p;
00780       char buf[30];
00781       unsigned char n;
00782 
00783       if (h->mr >= 0) {
00784          snprintf(mrs, sizeof(mrs), "%02X", h->mr);
00785       }
00786       snprintf(line, sizeof(line), "%s %c%c%c%s %s %s %s ",
00787          isodate(time(NULL), buf, sizeof(buf)),
00788          status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue,
00789          S_OR(h->oa, "-"), S_OR(h->da, "-") );
00790       p = line + strlen(line);
00791       for (n = 0; n < h->udl; n++) {
00792          if (h->ud[n] == '\\') {
00793             *p++ = '\\';
00794             *p++ = '\\';
00795          } else if (h->ud[n] == '\n') {
00796             *p++ = '\\';
00797             *p++ = 'n';
00798          } else if (h->ud[n] == '\r') {
00799             *p++ = '\\';
00800             *p++ = 'r';
00801          } else if (h->ud[n] < 32 || h->ud[n] == 127) {
00802             *p++ = 191;
00803          } else {
00804             *p++ = h->ud[n];
00805          }
00806       }
00807       *p++ = '\n';
00808       *p = 0;
00809       if (write(o, line, strlen(line)) < 0) {
00810          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00811       }
00812       close(o);
00813    }
00814    *h->oa = *h->da = h->udl = 0;
00815 }
00816 
00817 /*! \brief parse and delete a file */
00818 static void sms_readfile(sms_t * h, char *fn)
00819 {
00820    char line[1000];
00821    FILE *s;
00822    char dcsset = 0;                        /* if DSC set */
00823    ast_log(LOG_NOTICE, "Sending %s\n", fn);
00824    h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
00825    h->mr = -1;
00826    h->dcs = 0xF1;                          /* normal messages class 1 */
00827    h->scts = ast_tvnow();
00828    s = fopen(fn, "r");
00829    if (s) {
00830       if (unlink(fn)) {                   /* concurrent access, we lost */
00831          fclose(s);
00832          return;
00833       }
00834       while (fgets (line, sizeof(line), s)) {   /* process line in file */
00835          char *p;
00836          void *pp = &p;
00837          for (p = line; *p && *p != '\n' && *p != '\r'; p++);
00838          *p = 0;                         /* strip eoln */
00839          p = line;
00840          if (!*p || *p == ';') {
00841             continue;                   /* blank line or comment, ignore */
00842          }
00843          while (isalnum(*p)) {
00844             *p = tolower (*p);
00845             p++;
00846          }
00847          while (isspace (*p)) {
00848             *p++ = 0;
00849          }
00850          if (*p == '=') {
00851             *p++ = 0;
00852             if (!strcmp(line, "ud")) {  /* parse message (UTF-8) */
00853                unsigned char o = 0;
00854                memcpy(h->udtxt, p, SMSLEN); /* for protocol 2 */
00855                while (*p && o < SMSLEN) {
00856                   h->ud[o++] = utf8decode(pp);
00857                }
00858                h->udl = o;
00859                if (*p) {
00860                   ast_log(LOG_WARNING, "UD too long in %s\n", fn);
00861                }
00862             } else {
00863                while (isspace (*p)) {
00864                   p++;
00865                }
00866                if (!strcmp(line, "oa") && strlen(p) < sizeof(h->oa)) {
00867                   numcpy (h->oa, p);
00868                } else if (!strcmp(line, "da") && strlen(p) < sizeof(h->oa)) {
00869                   numcpy (h->da, p);
00870                } else if (!strcmp(line, "pid")) {
00871                   h->pid = atoi(p);
00872                } else if (!strcmp(line, "dcs")) {
00873                   h->dcs = atoi(p);
00874                   dcsset = 1;
00875                } else if (!strcmp(line, "mr")) {
00876                   h->mr = atoi(p);
00877                } else if (!strcmp(line, "srr")) {
00878                   h->srr = (atoi(p) ? 1 : 0);
00879                } else if (!strcmp(line, "vp")) {
00880                   h->vp = atoi(p);
00881                } else if (!strcmp(line, "rp")) {
00882                   h->rp = (atoi(p) ? 1 : 0);
00883                } else if (!strcmp(line, "scts")) {    /* get date/time */
00884                   int Y, m, d, H, M, S;
00885                   /* XXX Why aren't we using ast_strptime here? */
00886                   if (sscanf(p, "%4d-%2d-%2dT%2d:%2d:%2d", &Y, &m, &d, &H, &M, &S) == 6) {
00887                      struct ast_tm t = { 0, };
00888                      t.tm_year = Y - 1900;
00889                      t.tm_mon = m - 1;
00890                      t.tm_mday = d;
00891                      t.tm_hour = H;
00892                      t.tm_min = M;
00893                      t.tm_sec = S;
00894                      t.tm_isdst = -1;
00895                      h->scts = ast_mktime(&t, NULL);
00896                      if (h->scts.tv_sec == 0) {
00897                         ast_log(LOG_WARNING, "Bad date/timein %s: %s", fn, p);
00898                      }
00899                   }
00900                } else {
00901                   ast_log(LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
00902                }
00903             }
00904          } else if (*p == '#') {                   /* raw hex format */
00905             *p++ = 0;
00906             if (*p == '#') {
00907                p++;
00908                if (!strcmp(line, "ud")) {        /* user data */
00909                   int o = 0;
00910                   while (*p && o < SMSLEN) {
00911                      if (isxdigit(*p) && isxdigit(p[1]) && isxdigit(p[2]) && isxdigit(p[3])) {
00912                         h->ud[o++] =
00913                            (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 12) +
00914                            (((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
00915                            (((isalpha(p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha(p[3]) ? 9 : 0) + (p[3] & 0xF));
00916                         p += 4;
00917                      } else
00918                         break;
00919                   }
00920                   h->udl = o;
00921                   if (*p)
00922                      ast_log(LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
00923                } else
00924                   ast_log(LOG_WARNING, "Only ud can use ## format, %s\n", fn);
00925             } else if (!strcmp(line, "ud")) {       /* user data */
00926                int o = 0;
00927                while (*p && o < SMSLEN) {
00928                   if (isxdigit(*p) && isxdigit(p[1])) {
00929                      h->ud[o++] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
00930                      p += 2;
00931                   } else {
00932                      break;
00933                   }
00934                }
00935                h->udl = o;
00936                if (*p) {
00937                   ast_log(LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
00938                }
00939             } else if (!strcmp(line, "udh")) {      /* user data header */
00940                unsigned char o = 0;
00941                h->udhi = 1;
00942                while (*p && o < SMSLEN) {
00943                   if (isxdigit(*p) && isxdigit(p[1])) {
00944                      h->udh[o] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
00945                      o++;
00946                      p += 2;
00947                   } else {
00948                      break;
00949                   }
00950                }
00951                h->udhl = o;
00952                if (*p) {
00953                   ast_log(LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
00954                }
00955             } else {
00956                ast_log(LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
00957             }
00958          } else {
00959             ast_log(LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
00960          }
00961       }
00962       fclose(s);
00963       if (!dcsset && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00964          if (packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00965             if (packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00966                ast_log(LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
00967             } else {
00968                h->dcs = 0x08;          /* default to 16 bit */
00969                ast_log(LOG_WARNING, "Sending in 16 bit format(%s)\n", fn);
00970             }
00971          } else {
00972             h->dcs = 0xF5;              /* default to 8 bit */
00973             ast_log(LOG_WARNING, "Sending in 8 bit format(%s)\n", fn);
00974          }
00975       }
00976       if (is7bit(h->dcs) && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00977          ast_log(LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
00978       }
00979       if (is8bit(h->dcs) && packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00980          ast_log(LOG_WARNING, "Invalid 8 bit data %s\n", fn);
00981       }
00982       if (is16bit(h->dcs) && packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00983          ast_log(LOG_WARNING, "Invalid 16 bit data %s\n", fn);
00984       }
00985    }
00986 }
00987 
00988 /*! \brief white a received text message to a file */
00989 static void sms_writefile(sms_t * h)
00990 {
00991    char fn[200] = "", fn2[200] = "";
00992    char buf[30];
00993    FILE *o;
00994 
00995    if (ast_tvzero(h->scts)) {
00996       h->scts = ast_tvnow();
00997    }
00998    snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
00999    ast_mkdir(fn, 0777);                    /* ensure it exists */
01000    ast_copy_string(fn2, fn, sizeof(fn2));
01001    snprintf(fn2 + strlen(fn2), sizeof(fn2) - strlen(fn2), "/%s.%s-%d", h->queue, isodate(h->scts.tv_sec, buf, sizeof(buf)), seq++);
01002    snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/.%s", fn2 + strlen(fn) + 1);
01003    if ((o = fopen(fn, "w")) == NULL) {
01004       return;
01005    }
01006 
01007    if (*h->oa) {
01008       fprintf(o, "oa=%s\n", h->oa);
01009    }
01010    if (*h->da) {
01011       fprintf(o, "da=%s\n", h->da);
01012    }
01013    if (h->udhi) {
01014       unsigned int p;
01015       fprintf(o, "udh#");
01016       for (p = 0; p < h->udhl; p++) {
01017          fprintf(o, "%02X", h->udh[p]);
01018       }
01019       fprintf(o, "\n");
01020    }
01021    if (h->udl) {
01022       unsigned int p;
01023       for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
01024       if (p < h->udl) {
01025          fputc(';', o);                  /* cannot use ud=, but include as a comment for human readable */
01026       }
01027       fprintf(o, "ud=");
01028       for (p = 0; p < h->udl; p++) {
01029          unsigned short v = h->ud[p];
01030          if (v < 32) {
01031             fputc(191, o);
01032          } else if (v < 0x80) {
01033             fputc(v, o);
01034          } else if (v < 0x800) {
01035             fputc(0xC0 + (v >> 6), o);
01036             fputc(0x80 + (v & 0x3F), o);
01037          } else {
01038             fputc(0xE0 + (v >> 12), o);
01039             fputc(0x80 + ((v >> 6) & 0x3F), o);
01040             fputc(0x80 + (v & 0x3F), o);
01041          }
01042       }
01043       fprintf(o, "\n");
01044       for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
01045       if (p < h->udl) {
01046          for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
01047          if (p == h->udl) {              /* can write in ucs-1 hex */
01048             fprintf(o, "ud#");
01049             for (p = 0; p < h->udl; p++) {
01050                fprintf(o, "%02X", h->ud[p]);
01051             }
01052             fprintf(o, "\n");
01053          } else {                        /* write in UCS-2 */
01054             fprintf(o, "ud##");
01055             for (p = 0; p < h->udl; p++) {
01056                fprintf(o, "%04X", h->ud[p]);
01057             }
01058             fprintf(o, "\n");
01059          }
01060       }
01061    }
01062    if (h->scts.tv_sec) {
01063       char datebuf[30];
01064       fprintf(o, "scts=%s\n", isodate(h->scts.tv_sec, datebuf, sizeof(datebuf)));
01065    }
01066    if (h->pid) {
01067       fprintf(o, "pid=%d\n", h->pid);
01068    }
01069    if (h->dcs != 0xF1) {
01070       fprintf(o, "dcs=%d\n", h->dcs);
01071    }
01072    if (h->vp) {
01073       fprintf(o, "vp=%d\n", h->vp);
01074    }
01075    if (h->srr) {
01076       fprintf(o, "srr=1\n");
01077    }
01078    if (h->mr >= 0) {
01079       fprintf(o, "mr=%d\n", h->mr);
01080    }
01081    if (h->rp) {
01082       fprintf(o, "rp=1\n");
01083    }
01084    fclose(o);
01085    if (rename(fn, fn2)) {
01086       unlink(fn);
01087    } else {
01088       ast_log(LOG_NOTICE, "Received to %s\n", fn2);
01089    }
01090 }
01091 
01092 /*! \brief read dir skipping dot files... */
01093 static struct dirent *readdirqueue(DIR *d, char *queue)
01094 {
01095    struct dirent *f;
01096    do {
01097       f = readdir(d);
01098    } while (f && (*f->d_name == '.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] != '.'));
01099    return f;
01100 }
01101 
01102 /*! \brief handle the incoming message */
01103 static unsigned char sms_handleincoming (sms_t * h)
01104 {
01105    unsigned char p = 3;
01106    if (h->smsc) {                          /* SMSC */
01107       if ((h->imsg[2] & 3) == 1) {        /* SMS-SUBMIT */
01108          h->udhl = h->udl = 0;
01109          h->vp = 0;
01110          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
01111          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
01112          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01113          ast_copy_string(h->oa, h->cli, sizeof(h->oa));
01114          h->scts = ast_tvnow();
01115          h->mr = h->imsg[p++];
01116          p += unpackaddress(h->da, h->imsg + p);
01117          h->pid = h->imsg[p++];
01118          h->dcs = h->imsg[p++];
01119          if ((h->imsg[2] & 0x18) == 0x10) {       /* relative VP */
01120             if (h->imsg[p] < 144) {
01121                h->vp = (h->imsg[p] + 1) * 5;
01122             } else if (h->imsg[p] < 168) {
01123                h->vp = 720 + (h->imsg[p] - 143) * 30;
01124             } else if (h->imsg[p] < 197) {
01125                h->vp = (h->imsg[p] - 166) * 1440;
01126             } else {
01127                h->vp = (h->imsg[p] - 192) * 10080;
01128             }
01129             p++;
01130          } else if (h->imsg[2] & 0x18) {
01131             p += 7;                     /* ignore enhanced / absolute VP */
01132          }
01133          p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01134          h->rx = 1;                      /* received message */
01135          sms_writefile(h);               /* write the file */
01136          if (p != h->imsg[1] + 2) {
01137             ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01138             return 0xFF;        /* duh! */
01139          }
01140       } else {
01141          ast_log(LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
01142          return 0xFF;
01143       }
01144    } else {                                /* client */
01145       if (!(h->imsg[2] & 3)) {            /* SMS-DELIVER */
01146          *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
01147          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
01148          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
01149          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01150          h->mr = -1;
01151          p += unpackaddress(h->oa, h->imsg + p);
01152          h->pid = h->imsg[p++];
01153          h->dcs = h->imsg[p++];
01154          h->scts = unpackdate(h->imsg + p);
01155          p += 7;
01156          p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01157          h->rx = 1;                      /* received message */
01158          sms_writefile(h);               /* write the file */
01159          if (p != h->imsg[1] + 2) {
01160             ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01161             return 0xFF;                /* duh! */
01162          }
01163       } else {
01164          ast_log(LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
01165          return 0xFF;
01166       }
01167    }
01168    return 0;                               /* no error */
01169 }
01170 
01171 #ifdef SOLARIS
01172 #define NAME_MAX 1024
01173 #endif
01174 
01175 /*!
01176  * Add data to a protocol 2 message.
01177  * Use the length field (h->omsg[1]) as a pointer to the next free position.
01178  */
01179 static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
01180 {
01181    int x = h->omsg[1] + 2;                 /* Get current position */
01182    if (x == 2) {
01183       x += 2;                             /* First: skip Payload length (set later) */
01184    }
01185    h->omsg[x++] = msg;                     /* Message code */
01186    h->omsg[x++] = (unsigned char)size;     /* Data size Low */
01187    h->omsg[x++] = 0;                       /* Data size Hi */
01188    for (; size > 0 ; size--) {
01189       h->omsg[x++] = *data++;
01190    }
01191    h->omsg[1] = x - 2;                     /* Frame size */
01192    h->omsg[2] = x - 4;                     /* Payload length (Lo) */
01193    h->omsg[3] = 0;                         /* Payload length (Hi) */
01194 }
01195 
01196 static void putdummydata_proto2(sms_t *h)
01197 {
01198    adddata_proto2(h, 0x10, "\0", 1);           /* Media Identifier > SMS */
01199    adddata_proto2(h, 0x11, "\0\0\0\0\0\0", 6); /* Firmware version */
01200    adddata_proto2(h, 0x12, "\2\0\4", 3);       /* SMS provider ID */
01201    adddata_proto2(h, 0x13, h->udtxt, h->udl);  /* Body */
01202 }
01203 
01204 static void sms_compose2(sms_t *h, int more)
01205 {
01206    struct ast_tm tm;
01207    struct timeval now = h->scts;
01208    char stm[9];
01209 
01210    h->omsg[0] = 0x00;                      /* set later... */
01211    h->omsg[1] = 0;
01212    putdummydata_proto2(h);
01213    if (h->smsc) {                          /* deliver */
01214       h->omsg[0] = 0x11;                  /* SMS_DELIVERY */
01215       /* Required: 10 11 12 13 14 15 17 (seems they must be ordered!) */
01216       ast_localtime(&now, &tm, NULL);
01217       sprintf(stm, "%02d%02d%02d%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);  /* Date mmddHHMM */
01218       adddata_proto2(h, 0x14, stm, 8);    /* Date */
01219       if (*h->oa == 0) {
01220          strcpy(h->oa, "00000000");
01221       }
01222       adddata_proto2(h, 0x15, h->oa, strlen(h->oa)); /* Originator */
01223       adddata_proto2(h, 0x17, "\1", 1);   /* Calling Terminal ID */
01224    } else {                                /* submit */
01225       h->omsg[0] = 0x10;                  /* SMS_SUBMIT */
01226       /* Required: 10 11 12 13 17 18 1B 1C (seems they must be ordered!) */
01227       adddata_proto2(h, 0x17, "\1", 1);   /* Calling Terminal ID */
01228       if (*h->da == 0) {
01229          strcpy(h->da, "00000000");
01230       }
01231       adddata_proto2(h, 0x18, h->da, strlen(h->da)); /* Originator */
01232       adddata_proto2(h, 0x1B, "\1", 1);         /* Called Terminal ID */
01233       adddata_proto2(h, 0x1C, "\0\0\0", 3);    /* Notification */
01234    }
01235 }
01236 
01237 static void putdummydata_proto2(sms_t *h);
01238 
01239 #define MAX_DEBUG_LEN   300
01240 static char *sms_hexdump(unsigned char buf[], int size, char *s /* destination */)
01241 {
01242    char *p;
01243    int f;
01244 
01245    for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3) {
01246       sprintf(p, "%02X ", (unsigned char)buf[f]);
01247    }
01248    return(s);
01249 }
01250 
01251 
01252 /*! \brief sms_handleincoming_proto2: handle the incoming message */
01253 static int sms_handleincoming_proto2(sms_t *h)
01254 {
01255    int f, i, sz = 0;
01256    int msg, msgsz;
01257    struct ast_tm tm;
01258    struct timeval now = { 0, 0 };
01259    char debug_buf[MAX_DEBUG_LEN * 3 + 1];
01260 
01261    sz = h->imsg[1] + 2;
01262    /* ast_verb(3, "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg, sz, debug_buf)); */
01263 
01264    /* Parse message body (called payload) */
01265    now = h->scts = ast_tvnow();
01266    for (f = 4; f < sz; ) {
01267       msg = h->imsg[f++];
01268       msgsz = h->imsg[f++];
01269       msgsz += (h->imsg[f++] * 256);
01270       switch (msg) {
01271       case 0x13:                          /* Body */
01272          ast_verb(3, "SMS-P2 Body#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]);
01273          if (msgsz >= sizeof(h->imsg)) {
01274             msgsz = sizeof(h->imsg) - 1;
01275          }
01276          for (i = 0; i < msgsz; i++) {
01277             h->ud[i] = h->imsg[f + i];
01278          }
01279          h->udl = msgsz;
01280          break;
01281       case 0x14:                          /* Date SCTS */
01282          now = h->scts = ast_tvnow();
01283          ast_localtime(&now, &tm, NULL);
01284          tm.tm_mon = ( (h->imsg[f] * 10) + h->imsg[f + 1] ) - 1;
01285          tm.tm_mday = ( (h->imsg[f + 2] * 10) + h->imsg[f + 3] );
01286          tm.tm_hour = ( (h->imsg[f + 4] * 10) + h->imsg[f + 5] );
01287          tm.tm_min = ( (h->imsg[f + 6] * 10) + h->imsg[f + 7] );
01288          tm.tm_sec = 0;
01289          h->scts = ast_mktime(&tm, NULL);
01290          ast_verb(3, "SMS-P2 Date#%02X=%02d/%02d %02d:%02d\n", msg, tm.tm_mday, tm.tm_mon + 1, tm.tm_hour, tm.tm_min);
01291          break;
01292       case 0x15:                          /* Calling line (from SMSC) */
01293          if (msgsz >= 20) {
01294             msgsz = 20 - 1;
01295          }
01296          ast_verb(3, "SMS-P2 Origin#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]);
01297          ast_copy_string(h->oa, (char *)(&h->imsg[f]), msgsz + 1);
01298          break;
01299       case 0x18:                          /* Destination(from TE/phone) */
01300          if (msgsz >= 20) {
01301             msgsz = 20 - 1;
01302          }
01303          ast_verb(3, "SMS-P2 Destination#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]);
01304          ast_copy_string(h->da, (char *)(&h->imsg[f]), msgsz + 1);
01305          break;
01306       case 0x1C:                          /* Notify */
01307          ast_verb(3, "SMS-P2 Notify#%02X=%s\n", msg, sms_hexdump(&h->imsg[f], 3, debug_buf));
01308          break;
01309       default:
01310          ast_verb(3, "SMS-P2 Par#%02X [%d]: %s\n", msg, msgsz, sms_hexdump(&h->imsg[f], msgsz, debug_buf));
01311          break;
01312       }
01313       f+=msgsz;                           /* Skip to next */
01314    }
01315    h->rx = 1;                              /* received message */
01316    sms_writefile(h);                       /* write the file */
01317    return 0;                               /* no error */
01318 }
01319 
01320 #if 0
01321 static void smssend(sms_t *h, char *c)
01322 {
01323    int f, x;
01324    for (f = 0; f < strlen(c); f++) {
01325       sscanf(&c[f*3], "%x", &x);
01326       h->omsg[f] = x;
01327    }
01328    sms_messagetx(h);
01329 }
01330 #endif
01331 
01332 static void sms_nextoutgoing (sms_t *h);
01333 
01334 static void sms_messagerx2(sms_t * h)
01335 {
01336    int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */
01337    int cause;
01338 
01339 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
01340    switch (p) {
01341    case DLL2_SMS_EST:                      /* Protocol 2: Connection ready (fake): send message  */
01342       sms_nextoutgoing (h);
01343       /* 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 "); */
01344       break;
01345 
01346    case DLL2_SMS_INFO_MO:                  /* transport SMS_SUBMIT */
01347    case DLL2_SMS_INFO_MT:                  /* transport SMS_DELIVERY */
01348       cause = sms_handleincoming_proto2(h);
01349       if (!cause) {                       /* ACK */
01350          sms_log(h, 'Y');
01351       }
01352       h->omsg[0] = DLL2_ACK(h);
01353       h->omsg[1] = 0x06;                  /* msg len */
01354       h->omsg[2] = 0x04;                  /* payload len */
01355       h->omsg[3] = 0x00;                  /* payload len */
01356       h->omsg[4] = 0x1f;                  /* Response type */
01357       h->omsg[5] = 0x01;                  /* parameter len */
01358       h->omsg[6] = 0x00;                  /* parameter len */
01359       h->omsg[7] = cause;                 /* CONFIRM or error */
01360       sms_messagetx(h);
01361       break;
01362 
01363    case DLL2_SMS_NACK:                     /* Protocol 2: SMS_NAK */
01364       h->omsg[0] = DLL2_SMS_REL;          /* SMS_REL */
01365       h->omsg[1] = 0x00;                  /* msg len */
01366       sms_messagetx(h);
01367       break;
01368 
01369    case DLL2_SMS_ACK0:
01370    case DLL2_SMS_ACK1:
01371       /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */
01372       if ( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
01373          /* a response to our Release, just hangup */
01374          h->hangup = 1;                  /* hangup */
01375       } else {
01376          /* XXX depending on what we are.. */
01377          ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY");
01378          sms_nextoutgoing (h);
01379       }
01380       break;
01381 
01382    case DLL2_SMS_REL:                      /* Protocol 2: SMS_REL (hangup req) */
01383       h->omsg[0] = DLL2_ACK(h);
01384       h->omsg[1] = 0;
01385       sms_messagetx(h);
01386       break;
01387    }
01388 }
01389 
01390 /*! \brief compose a message for protocol 1 */
01391 static void sms_compose1(sms_t *h, int more)
01392 {
01393    unsigned int p = 2;                     /* next byte to write. Skip type and len */
01394 
01395    h->omsg[0] = 0x91;                      /* SMS_DATA */
01396    if (h->smsc) {                          /* deliver */
01397       h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
01398       p += packaddress(h->omsg + p, h->oa);
01399       h->omsg[p++] = h->pid;
01400       h->omsg[p++] = h->dcs;
01401       packdate(h->omsg + p, h->scts.tv_sec);
01402       p += 7;
01403       p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01404    } else {                                /* submit */
01405       h->omsg[p++] =
01406          0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
01407       if (h->mr < 0) {
01408          h->mr = message_ref++;
01409       }
01410       h->omsg[p++] = h->mr;
01411       p += packaddress(h->omsg + p, h->da);
01412       h->omsg[p++] = h->pid;
01413       h->omsg[p++] = h->dcs;
01414       if (h->vp) {                        /* relative VP */
01415          if (h->vp < 720) {
01416             h->omsg[p++] = (h->vp + 4) / 5 - 1;
01417          } else if (h->vp < 1440) {
01418             h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
01419          } else if (h->vp < 43200) {
01420             h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
01421          } else if (h->vp < 635040) {
01422             h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
01423          } else {
01424             h->omsg[p++] = 255;         /* max */
01425          }
01426       }
01427       p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01428    }
01429    h->omsg[1] = p - 2;
01430 }
01431 
01432 /*! \brief find and fill in next message, or send a REL if none waiting */
01433 static void sms_nextoutgoing (sms_t * h)
01434 {    
01435    char fn[100 + NAME_MAX] = "";
01436    DIR *d;
01437    char more = 0;
01438 
01439    *h->da = *h->oa = '\0';                 /* clear destinations */
01440    h->rx = 0;                              /* outgoing message */
01441    snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? "mttx" : "motx");
01442    ast_mkdir(fn, 0777);                    /* ensure it exists */
01443    d = opendir(fn);
01444    if (d) {
01445       struct dirent *f = readdirqueue(d, h->queue);
01446       if (f) {
01447          snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", f->d_name);
01448          sms_readfile(h, fn);
01449          if (readdirqueue(d, h->queue)) {
01450             more = 1;                   /* more to send */
01451          }
01452       }
01453       closedir(d);
01454    }
01455    if (*h->da || *h->oa) {                 /* message to send */
01456       if (h->protocol == 2) {
01457          sms_compose2(h, more);
01458       } else {
01459          sms_compose1(h, more);
01460       }
01461    } else {                                /* no message */
01462       if (h->protocol == 2) {
01463          h->omsg[0] = 0x17;              /* SMS_REL */
01464          h->omsg[1] = 0;
01465       } else {
01466          h->omsg[0] = 0x94;              /* SMS_REL */
01467          h->omsg[1] = 0;
01468          h->sent_rel = 1;
01469       }
01470    }
01471    sms_messagetx(h);
01472 }
01473 
01474 #define DIR_RX 1
01475 #define DIR_TX 2
01476 static void sms_debug (int dir, sms_t *h)
01477 {
01478    char txt[259 * 3 + 1];
01479    char *p = txt;                          /* always long enough */
01480    unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
01481    int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
01482    int q = 0;
01483    while (q < n && q < 30) {
01484       sprintf(p, " %02X", msg[q++]);
01485       p += 3;
01486    }
01487    if (q < n) {
01488       sprintf(p, "...");
01489    }
01490    ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
01491 }
01492 
01493 
01494 static void sms_messagerx(sms_t * h)
01495 {
01496    int cause;
01497 
01498    sms_debug (DIR_RX, h);
01499    if (h->protocol == 2) {
01500       sms_messagerx2(h);
01501       return;
01502    }
01503    /* parse incoming message for Protocol 1 */
01504    switch (h->imsg[0]) {
01505    case 0x91:                              /* SMS_DATA */
01506       cause = sms_handleincoming (h);
01507       if (!cause) {
01508          sms_log(h, 'Y');
01509          h->omsg[0] = 0x95;              /* SMS_ACK */
01510          h->omsg[1] = 0x02;
01511          h->omsg[2] = 0x00;              /* deliver report */
01512          h->omsg[3] = 0x00;              /* no parameters */
01513       } else {                            /* NACK */
01514          sms_log(h, 'N');
01515          h->omsg[0] = 0x96;              /* SMS_NACK */
01516          h->omsg[1] = 3;
01517          h->omsg[2] = 0;                 /* delivery report */
01518          h->omsg[3] = cause;             /* cause */
01519          h->omsg[4] = 0;                 /* no parameters */
01520       }
01521       sms_messagetx(h);
01522       break;
01523 
01524    case 0x92:                              /* SMS_ERROR */
01525       h->err = 1;
01526       sms_messagetx(h);                   /* send whatever we sent again */
01527       break;
01528    case 0x93:                              /* SMS_EST */
01529       sms_nextoutgoing (h);
01530       break;
01531    case 0x94:                              /* SMS_REL */
01532       h->hangup = 1;                      /* hangup */
01533       break;
01534    case 0x95:                              /* SMS_ACK */
01535       sms_log(h, 'Y');
01536       sms_nextoutgoing (h);
01537       break;
01538    case 0x96:                              /* SMS_NACK */
01539       h->err = 1;
01540       sms_log(h, 'N');
01541       sms_nextoutgoing (h);
01542       break;
01543    default:                                /* Unknown */
01544       h->omsg[0] = 0x92;                  /* SMS_ERROR */
01545       h->omsg[1] = 1;
01546       h->omsg[2] = 3;                     /* unknown message type */
01547       sms_messagetx(h);
01548       break;
01549    }
01550 }
01551 
01552 static void sms_messagetx(sms_t * h)
01553 {
01554    unsigned char c = 0, p;
01555    int len = h->omsg[1] + 2;               /* total message length excluding checksum */
01556 
01557    for (p = 0; p < len; p++) {             /* compute checksum */
01558       c += h->omsg[p];
01559    }
01560    h->omsg[len] = 0 - c;                   /* actually, (256 - (c & 0fxx)) & 0xff) */
01561    sms_debug(DIR_TX, h);
01562    h->framenumber++;                       /* Proto 2 */
01563    h->obytep = 0;
01564    h->obitp = 0;
01565    if (h->protocol == 2) {                 /* Proto 2: */
01566       h->oseizure = 300;                  /* 300bits (or more ?) */
01567       h->obyte = 0;                       /* Seizure starts with  space (0) */
01568       if (h->omsg[0] == 0x7F) {
01569          h->opause = 8 * h->opause_0;    /* initial message delay */
01570       } else {
01571          h->opause = 400;
01572       }
01573    } else {                                /* Proto 1: */
01574       h->oseizure = 0;                    /* No seizure */
01575       h->obyte = 1;                       /* send mark ('1') at the beginning */
01576       /* Change the initial message delay. BT requires 300ms,
01577        * but for others this might be way too much and the phone
01578        * could time out. XXX make it configurable.
01579       */
01580       if (h->omsg[0] == 0x93) {
01581          h->opause = 8 * h->opause_0;    /* initial message delay */
01582       } else {
01583          h->opause = 200;
01584       }
01585    }
01586    /* Note - setting osync triggers the generator */
01587    h->osync = OSYNC_BITS;                  /* 80 sync bits */
01588    h->obyten = len + 1;                    /* bytes to send (including checksum) */
01589 }
01590 
01591 /*!
01592  * outgoing data are produced by this generator function, that reads from
01593  * the descriptor whether it has data to send and which ones.
01594  */
01595 static int sms_generate(struct ast_channel *chan, void *data, int len, int samples)
01596 {
01597    struct ast_frame f = { 0 };
01598 #define MAXSAMPLES (800)
01599    output_t *buf;
01600    sms_t *h = data;
01601    int i;
01602 
01603    if (samples > MAXSAMPLES) {
01604       ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
01605           MAXSAMPLES, samples);
01606       samples = MAXSAMPLES;
01607    }
01608    len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET;
01609    buf = alloca(len);
01610 
01611    f.frametype = AST_FRAME_VOICE;
01612    f.subclass.codec = __OUT_FMT;
01613    f.datalen = samples * sizeof(*buf);
01614    f.offset = AST_FRIENDLY_OFFSET;
01615    f.mallocd = 0;
01616    f.data.ptr = buf;
01617    f.samples = samples;
01618    f.src = "app_sms";
01619    /* create a buffer containing the digital sms pattern */
01620    for (i = 0; i < samples; i++) {
01621       buf[i] = wave_out[0];               /* default is silence */
01622 
01623       if (h->opause) {
01624          h->opause--;
01625       } else if (h->obyten || h->osync) { /* sending data */
01626          buf[i] = wave_out[h->ophase];
01627          h->ophase += (h->obyte & 1) ? 13 : 21; /* compute next phase */
01628          if (h->ophase >= 80)
01629             h->ophase -= 80;
01630          if ((h->ophasep += 12) >= 80) { /* time to send the next bit */
01631             h->ophasep -= 80;
01632             if (h->oseizure > 0) {      /* sending channel seizure (proto 2) */
01633                h->oseizure--;
01634                h->obyte ^= 1;          /* toggle low bit */
01635             } else if (h->osync) {
01636                h->obyte = 1;           /* send mark as sync bit */
01637                h->osync--;             /* sending sync bits */
01638                if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
01639                   h->obytep = h->obyten = 0; /* we are done */
01640                }
01641             } else {
01642                h->obitp++;
01643                if (h->obitp == 1) {
01644                   h->obyte = 0;       /* start bit; */
01645                } else if (h->obitp == 2) {
01646                   h->obyte = h->omsg[h->obytep];
01647                } else if (h->obitp == 10) {
01648                   h->obyte = 1; /* stop bit */
01649                   h->obitp = 0;
01650                   h->obytep++;
01651                   if (h->obytep == h->obyten) {
01652                      h->obytep = h->obyten = 0; /* sent */
01653                      h->osync = 10;   /* trailing marks */
01654                   }
01655                } else {
01656                   h->obyte >>= 1;
01657                }
01658             }
01659          }
01660       }
01661    }
01662    if (ast_write(chan, &f) < 0) {
01663       ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
01664       return -1;
01665    }
01666    return 0;
01667 #undef MAXSAMPLES
01668 }
01669 
01670 /*!
01671  * Just return the pointer to the descriptor that we received.
01672  */
01673 static void *sms_alloc(struct ast_channel *chan, void *sms_t_ptr)
01674 {
01675    return sms_t_ptr;
01676 }
01677 
01678 static void sms_release(struct ast_channel *chan, void *data)
01679 {
01680    return;  /* nothing to do here. */
01681 }
01682 
01683 static struct ast_generator smsgen = {
01684    .alloc = sms_alloc,
01685    .release = sms_release,
01686    .generate = sms_generate,
01687 };
01688 
01689 /*!
01690  * Process an incoming frame, trying to detect the carrier and
01691  * decode the message. The two frequencies are 1300 and 2100 Hz.
01692  * The decoder detects the amplitude of the signal over the last
01693  * few samples, filtering the absolute values with a lowpass filter.
01694  * If the magnitude (h->imag) is large enough, multiply the signal
01695  * by the two carriers, and compute the amplitudes m0 and m1.
01696  * Record the current sample as '0' or '1' depending on which one is greater.
01697  * The last 3 bits are stored in h->ibith, with the count of '1'
01698  * bits in h->ibitt.
01699  * XXX the rest is to be determined.
01700  */
01701 static void sms_process(sms_t * h, int samples, signed short *data)
01702 {
01703    int bit;
01704 
01705    /*
01706     * Ignore incoming audio while a packet is being transmitted,
01707     * the protocol is half-duplex.
01708     * Unfortunately this means that if the outbound and incoming
01709     * transmission overlap (which is an error condition anyways),
01710     * we may miss some data and this makes debugging harder.
01711     */
01712    if (h->obyten || h->osync) {
01713       return;
01714    }
01715    for ( ; samples-- ; data++) {
01716       unsigned long long m0, m1;
01717       if (abs(*data) > h->imag) {
01718          h->imag = abs(*data);
01719       } else {
01720          h->imag = h->imag * 7 / 8;
01721       }
01722       if (h->imag <= 500) {               /* below [arbitrary] threahold: lost carrier */
01723          if (h->idle++ == 80000) {       /* nothing happening */
01724             ast_log(LOG_NOTICE, "No data, hanging up\n");
01725             h->hangup = 1;
01726             h->err = 1;
01727          }
01728          if (h->ierr) {                  /* error */
01729             ast_log(LOG_NOTICE, "Error %d, hanging up\n", h->ierr);
01730             /* Protocol 1 */
01731             h->err = 1;
01732             h->omsg[0] = 0x92;          /* error */
01733             h->omsg[1] = 1;
01734             h->omsg[2] = h->ierr;
01735             sms_messagetx(h);           /* send error */
01736          }
01737          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01738          continue;
01739       }
01740       h->idle = 0;
01741 
01742       /* multiply signal by the two carriers. */
01743       h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
01744       h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
01745       h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
01746       h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
01747       /* compute the amplitudes */
01748       m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
01749       m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
01750 
01751       /* advance the sin/cos pointers */
01752       if ((h->ips0 += 21) >= 80) {
01753          h->ips0 -= 80;
01754       }
01755       if ((h->ipc0 += 21) >= 80) {
01756          h->ipc0 -= 80;
01757       }
01758       if ((h->ips1 += 13) >= 80) {
01759          h->ips1 -= 80;
01760       }
01761       if ((h->ipc1 += 13) >= 80) {
01762          h->ipc1 -= 80;
01763       }
01764 
01765       /* set new bit to 1 or 0 depending on which value is stronger */
01766       h->ibith <<= 1;
01767       if (m1 > m0) {
01768          h->ibith |= 1;
01769       }
01770       if (h->ibith & 8) {
01771          h->ibitt--;
01772       }
01773       if (h->ibith & 1) {
01774          h->ibitt++;
01775       }
01776       bit = ((h->ibitt > 1) ? 1 : 0);
01777       if (bit != h->ibitl) {
01778          h->ibitc = 1;
01779       } else {
01780          h->ibitc++;
01781       }
01782       h->ibitl = bit;
01783       if (!h->ibitn && h->ibitc == 4 && !bit) {
01784          h->ibitn = 1;
01785          h->iphasep = 0;
01786       }
01787       if (bit && h->ibitc == 200) {       /* sync, restart message */
01788          /* Protocol 2: empty connection ready (I am master) */
01789          if (h->framenumber < 0 && h->ibytec >= 160 && !memcmp(h->imsg, "UUUUUUUUUUUUUUUUUUUU", 20)) {
01790             h->framenumber = 1;
01791             ast_verb(3, "SMS protocol 2 detected\n");
01792             h->protocol = 2;
01793             h->imsg[0] = 0xff;          /* special message (fake) */
01794             h->imsg[1] = h->imsg[2] = 0x00;
01795             h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01796             sms_messagerx(h);
01797          }
01798          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01799       }
01800       if (h->ibitn) {
01801          h->iphasep += 12;
01802          if (h->iphasep >= 80) {         /* next bit */
01803             h->iphasep -= 80;
01804             if (h->ibitn++ == 9) {      /* end of byte */
01805                if (!bit) {             /* bad stop bit */
01806                   if (h->sent_rel) {
01807                      h->hangup = 1;
01808                   } else {
01809                      ast_log(LOG_NOTICE, "bad stop bit\n");
01810                      h->ierr = 0xFF;     /* unknown error */
01811                   }
01812                } else {
01813                   if (h->ibytep < sizeof(h->imsg)) {
01814                      h->imsg[h->ibytep] = h->ibytev;
01815                      h->ibytec += h->ibytev;
01816                      h->ibytep++;
01817                   } else if (h->ibytep == sizeof(h->imsg)) {
01818                      ast_log(LOG_NOTICE, "msg too large");
01819                      h->ierr = 2;    /* bad message length */
01820                   }
01821                   if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
01822                      if (!h->ibytec) {
01823                         sms_messagerx(h);
01824                      } else {
01825                         ast_log(LOG_NOTICE, "bad checksum");
01826                         h->ierr = 1; /* bad checksum */
01827                      }
01828                   }
01829                }
01830                h->ibitn = 0;
01831             }
01832             h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
01833          }
01834       }
01835    }
01836 }
01837 
01838 /*
01839  * Standard argument parsing:
01840  * - one enum for the flags we recognise,
01841  * - one enum for argument indexes
01842  * - AST_APP_OPTIONS() to drive the parsing routine
01843  * - in the function, AST_DECLARE_APP_ARGS(...) for the arguments.
01844  */
01845 enum sms_flags {
01846    OPTION_BE_SMSC = (1 << 0),             /* act as sms center */
01847    OPTION_ANSWER  = (1 << 1),             /* answer on incoming calls */
01848    OPTION_TWO  = (1 << 2),                 /* Use Protocol Two */
01849    OPTION_PAUSE   = (1 << 3),             /* pause before sending data, in ms */
01850    OPTION_SRR  = (1 << 4),                 /* set srr */
01851    OPTION_DCS  = (1 << 5),                 /* set dcs */
01852 };
01853 
01854 enum sms_opt_args {
01855    OPTION_ARG_PAUSE = 0,
01856    OPTION_ARG_ARRAY_SIZE
01857 };
01858 
01859 AST_APP_OPTIONS(sms_options, {
01860    AST_APP_OPTION('s', OPTION_BE_SMSC),
01861    AST_APP_OPTION('a', OPTION_ANSWER),
01862    AST_APP_OPTION('t', OPTION_TWO),
01863    AST_APP_OPTION('r', OPTION_SRR),
01864    AST_APP_OPTION('o', OPTION_DCS),
01865    AST_APP_OPTION_ARG('p', OPTION_PAUSE, OPTION_ARG_PAUSE),
01866    } );
01867 
01868 static int sms_exec(struct ast_channel *chan, const char *data)
01869 {
01870    int res = -1;
01871    sms_t h = { 0 };
01872    /* argument parsing support */
01873    struct ast_flags flags = { 0 };
01874    char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, };
01875    char *p;
01876    AST_DECLARE_APP_ARGS(sms_args,
01877       AST_APP_ARG(queue);
01878       AST_APP_ARG(options);
01879       AST_APP_ARG(addr);
01880       AST_APP_ARG(body);
01881    );
01882 
01883    if (!data) {
01884       ast_log(LOG_ERROR, "Requires queue name at least\n");
01885       return -1;
01886    }
01887 
01888    parse = ast_strdupa(data);              /* create a local copy */
01889    AST_STANDARD_APP_ARGS(sms_args, parse);
01890    if (sms_args.argc > 1) {
01891       ast_app_parse_options(sms_options, &flags, sms_opts, sms_args.options);
01892    }
01893 
01894    ast_verb(1, "sms argc %d queue <%s> opts <%s> addr <%s> body <%s>\n",
01895       sms_args.argc, S_OR(sms_args.queue, ""),
01896       S_OR(sms_args.options, ""),
01897       S_OR(sms_args.addr, ""),
01898       S_OR(sms_args.body, "") );
01899 
01900    h.ipc0 = h.ipc1 = 20;                   /* phase for cosine */
01901    h.dcs = 0xF1;                           /* default */
01902 
01903    ast_copy_string(h.cli,
01904       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
01905       sizeof(h.cli));
01906 
01907    if (ast_strlen_zero(sms_args.queue)) {
01908       ast_log(LOG_ERROR, "Requires queue name\n");
01909       goto done;
01910    }
01911    if (strlen(sms_args.queue) >= sizeof(h.queue)) {
01912       ast_log(LOG_ERROR, "Queue name too long\n");
01913       goto done;
01914    }
01915    ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue));
01916 
01917    for (p = h.queue; *p; p++) {
01918       if (!isalnum(*p)) {
01919          *p = '-';                       /* make very safe for filenames */
01920       }
01921    }
01922 
01923    h.smsc = ast_test_flag(&flags, OPTION_BE_SMSC);
01924    h.protocol = ast_test_flag(&flags, OPTION_TWO) ? 2 : 1;
01925    if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE])) {
01926       h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
01927    }
01928    if (h.opause_0 < 25 || h.opause_0 > 2000) {
01929       h.opause_0 = 300;                   /* default 300ms */
01930    }
01931    ast_verb(1, "initial delay %dms\n", h.opause_0);
01932 
01933 
01934    /* the following apply if there is an arg3/4 and apply to the created message file */
01935    if (ast_test_flag(&flags, OPTION_SRR)) {
01936       h.srr = 1;
01937    }
01938    if (ast_test_flag(&flags, OPTION_DCS)) {
01939       h.dcs = 1;
01940    }
01941 #if 0 
01942       case '1':
01943       case '2':
01944       case '3':
01945       case '4':
01946       case '5':
01947       case '6':
01948       case '7':                           /* set the pid for saved local message */
01949          h.pid = 0x40 + (*d & 0xF);
01950          break;
01951       }
01952 #endif
01953    if (sms_args.argc > 2) {
01954       unsigned char *up;
01955 
01956       /* submitting a message, not taking call. */
01957       /* deprecated, use smsq instead */
01958       h.scts = ast_tvnow();
01959       if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) {
01960          ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr);
01961          goto done;
01962       }
01963       if (h.smsc) {
01964          ast_copy_string(h.oa, sms_args.addr, sizeof(h.oa));
01965       } else {
01966          ast_copy_string(h.da, sms_args.addr, sizeof(h.da));
01967          ast_copy_string(h.oa, h.cli, sizeof(h.oa));
01968       }
01969       h.udl = 0;
01970       if (ast_strlen_zero(sms_args.body)) {
01971          ast_log(LOG_ERROR, "Missing body for %s\n", sms_args.addr);
01972          goto done;
01973       }
01974       up = (unsigned char *)sms_args.body;
01975       while (*up && h.udl < SMSLEN) {
01976          h.ud[h.udl++] = utf8decode(&up);
01977       }
01978       if (is7bit(h.dcs) && packsms7(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01979          ast_log(LOG_WARNING, "Invalid 7 bit GSM data\n");
01980          goto done;
01981       }
01982       if (is8bit(h.dcs) && packsms8(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01983          ast_log(LOG_WARNING, "Invalid 8 bit data\n");
01984          goto done;
01985       }
01986       if (is16bit(h.dcs) && packsms16(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01987          ast_log(LOG_WARNING, "Invalid 16 bit data\n");
01988          goto done;
01989       }
01990       h.rx = 0;                           /* sent message */
01991       h.mr = -1;
01992       sms_writefile(&h);
01993       res = h.err;
01994       goto done;
01995    }
01996    
01997    if (chan->_state != AST_STATE_UP) {    /* make sure channel is answered before any TX */
01998       ast_answer(chan);
01999    }
02000 
02001    if (ast_test_flag(&flags, OPTION_ANSWER)) {
02002       h.framenumber = 1;                  /* Proto 2 */
02003       /* set up SMS_EST initial message */
02004       if (h.protocol == 2) {
02005          h.omsg[0] = DLL2_SMS_EST;
02006          h.omsg[1] = 0;
02007       } else {
02008          h.omsg[0] = DLL1_SMS_EST | DLL1_SMS_COMPLETE;
02009          h.omsg[1] = 0;
02010       }
02011       sms_messagetx(&h);
02012    }
02013 
02014    res = ast_set_write_format(chan, __OUT_FMT);
02015    if (res >= 0) {
02016       res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
02017    }
02018    if (res < 0) {
02019       ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
02020       goto done;
02021    }
02022 
02023    if ( (res = ast_activate_generator(chan, &smsgen, &h)) < 0) {
02024       ast_log(LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
02025       goto done;
02026    }
02027 
02028    /* Do our thing here */
02029    for (;;) {
02030       struct ast_frame *f;
02031       int i = ast_waitfor(chan, -1);
02032       if (i < 0) {
02033          ast_log(LOG_NOTICE, "waitfor failed\n");
02034          break;
02035       }
02036       if (h.hangup) {
02037          ast_log(LOG_NOTICE, "channel hangup\n");
02038          break;
02039       }
02040       f = ast_read(chan);
02041       if (!f) {
02042          ast_log(LOG_NOTICE, "ast_read failed\n");
02043          break;
02044       }
02045       if (f->frametype == AST_FRAME_VOICE) {
02046          sms_process(&h, f->samples, f->data.ptr);
02047       }
02048 
02049       ast_frfree(f);
02050    }
02051    res = h.err;                            /* XXX */
02052 
02053    /* 
02054     * The SMS generator data is on the stack.  We _MUST_ make sure the generator
02055     * is stopped before returning from this function.
02056     */
02057    ast_deactivate_generator(chan);
02058 
02059    sms_log(&h, '?');                       /* log incomplete message */
02060 done:
02061    return (res);
02062 }
02063 
02064 static int unload_module(void)
02065 {
02066    return ast_unregister_application(app);
02067 }
02068 
02069 static int load_module(void)
02070 {
02071 #ifdef OUTALAW
02072    int p;
02073    for (p = 0; p < 80; p++) {
02074       wavea[p] = AST_LIN2A(wave[p]);
02075    }
02076 #endif
02077    snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR);
02078    return ast_register_application_xml(app, sms_exec);
02079 }
02080 
02081 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SMS/PSTN handler");