Sat Apr 26 2014 22:01:27

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: 403855 $")
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 smsc:1;        /*!< we are SMSC */
00220    unsigned char rx:1;          /*!< this is a received message */
00221    char queue[30];              /*!< queue name */
00222    char oa[20];                 /*!< originating address */
00223    char da[20];                 /*!< destination address */
00224    struct timeval scts;         /*!< time stamp, UTC */
00225    unsigned char pid;           /*!< protocol ID */
00226    unsigned char dcs;           /*!< data coding scheme */
00227    short mr;                    /*!< message reference - actually a byte, but use -1 for not set */
00228    int udl;                     /*!< user data length */
00229    int udhl;                    /*!< user data header length */
00230    unsigned char srr:1;         /*!< Status Report request */
00231    unsigned char udhi:1;        /*!< User Data Header required, even if length 0 */
00232    unsigned char rp:1;          /*!< Reply Path */
00233    unsigned int vp;             /*!< validity period in minutes, 0 for not set */
00234    unsigned short ud[SMSLEN];   /*!< user data (message), UCS-2 coded */
00235    unsigned char udh[SMSLEN];   /*!< user data header */
00236    char cli[20];                /*!< caller ID */
00237    unsigned char ophase;        /*!< phase (0-79) for 0 and 1 frequencies (1300Hz and 2100Hz) */
00238    unsigned char ophasep;       /*!< phase (0-79) for 1200 bps */
00239    unsigned char obyte;         /*!< byte being sent */
00240    unsigned int opause;         /*!< silent pause before sending (in sample periods) */
00241    unsigned char obitp;         /*!< bit in byte */
00242    unsigned char osync;         /*!< sync bits to send */
00243    unsigned char obytep;        /*!< byte in data */
00244    unsigned char obyten;        /*!< bytes in data */
00245    unsigned char omsg[256];     /*!< data buffer (out) */
00246    unsigned char imsg[250];     /*!< data buffer (in) */
00247    signed long long ims0,
00248       imc0,
00249       ims1,
00250       imc1;                    /*!< magnitude averages sin/cos 0/1 */
00251    unsigned int idle;
00252    unsigned short imag;         /*!< signal level */
00253    unsigned char ips0;          /*!< phase sin for bit 0, start at  0 inc by 21 mod 80 */
00254    unsigned char ips1;          /*!< phase cos for bit 0, start at 20 inc by 21 mod 80 */
00255    unsigned char ipc0;          /*!< phase sin for bit 1, start at  0 inc by 13 mod 80 */
00256    unsigned char ipc1;          /*!< phase cos for bit 1, start at 20 inc by 13 mod 80 */
00257    unsigned char ibitl;         /*!< last bit */
00258    unsigned char ibitc;         /*!< bit run length count */
00259    unsigned char iphasep;       /*!< bit phase (0-79) for 1200 bps */
00260    unsigned char ibitn;         /*!< bit number in byte being received */
00261    unsigned char ibytev;        /*!< byte value being received */
00262    unsigned char ibytep;        /*!< byte pointer in message */
00263    unsigned char ibytec;        /*!< byte checksum for message */
00264    unsigned char ierr;          /*!< error flag */
00265    unsigned char ibith;         /*!< history of last bits */
00266    unsigned char ibitt;         /*!< total of 1's in last 3 bytes */
00267    /* more to go here */
00268 
00269    int opause_0;                /*!< initial delay in ms, p() option */
00270    int protocol;                /*!< ETSI SMS protocol to use (passed at app call) */
00271    int oseizure;                /*!< protocol 2: channel seizure bits to send */
00272    int framenumber;             /*!< protocol 2: frame number (for sending ACK0 or ACK1) */
00273    char udtxt[SMSLEN];          /*!< user data (message), PLAIN text */
00274 } sms_t;
00275 
00276 /* different types of encoding */
00277 #define is7bit(dcs)  ( ((dcs) & 0xC0) ? (!((dcs) & 4) ) : (((dcs) & 0xc) == 0) )
00278 #define is8bit(dcs)  ( ((dcs) & 0xC0) ? ( ((dcs) & 4) ) : (((dcs) & 0xc) == 4) )
00279 #define is16bit(dcs) ( ((dcs) & 0xC0) ? 0               : (((dcs) & 0xc) == 8) )
00280 
00281 static void sms_messagetx(sms_t *h);
00282 
00283 /*! \brief copy number, skipping non digits apart from leading + */
00284 static void numcpy(char *d, char *s)
00285 {
00286    if (*s == '+') {
00287       *d++ = *s++;
00288    }
00289    while (*s) {
00290       if (isdigit(*s)) {
00291          *d++ = *s;
00292       }
00293       s++;
00294    }
00295    *d = 0;
00296 }
00297 
00298 /*! \brief static, return a date/time in ISO format */
00299 static char *isodate(time_t t, char *buf, int len)
00300 {
00301    struct ast_tm tm;
00302    struct timeval local = { t, 0 };
00303    ast_localtime(&local, &tm, NULL);
00304    ast_strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
00305    return buf;
00306 }
00307 
00308 /*! \brief Reads next UCS character from NUL terminated UTF-8 string and advance pointer */
00309 /* for non valid UTF-8 sequences, returns character as is */
00310 /* Does not advance pointer for null termination */
00311 static long utf8decode(unsigned char **pp)
00312 {
00313    unsigned char *p = *pp;
00314    if (!*p) {
00315       return 0;                           /* null termination of string */
00316    }
00317    (*pp)++;
00318    if (*p < 0xC0) {
00319       return *p;                          /* ascii or continuation character */
00320    }
00321    if (*p < 0xE0) {
00322       if (*p < 0xC2 || (p[1] & 0xC0) != 0x80) {
00323          return *p;                      /* not valid UTF-8 */
00324       }
00325       (*pp)++;
00326       return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
00327       }
00328    if (*p < 0xF0) {
00329       if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80) {
00330          return *p;                      /* not valid UTF-8 */
00331       }
00332       (*pp) += 2;
00333       return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
00334    }
00335    if (*p < 0xF8) {
00336       if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80) {
00337          return *p;                      /* not valid UTF-8 */
00338       }
00339       (*pp) += 3;
00340       return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
00341    }
00342    if (*p < 0xFC) {
00343       if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00344          || (p[4] & 0xC0) != 0x80) {
00345          return *p;                      /* not valid UTF-8 */
00346       }
00347       (*pp) += 4;
00348       return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
00349    }
00350    if (*p < 0xFE) {
00351       if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00352          || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80) {
00353          return *p;                      /* not valid UTF-8 */
00354       }
00355       (*pp) += 5;
00356       return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
00357    }
00358    return *p;                              /* not sensible */
00359 }
00360 
00361 /*! \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 */
00362 /* The return value is the number of septets packed in to o, which is internally limited to SMSLEN */
00363 /* o can be null, in which case this is used to validate or count only */
00364 /* if the input contains invalid characters then the return value is -1 */
00365 static int packsms7(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00366 {
00367    unsigned char p = 0;                    /* output pointer (bytes) */
00368    unsigned char b = 0;                    /* bit position */
00369    unsigned char n = 0;                    /* output character count */
00370    unsigned char dummy[SMSLEN];
00371 
00372    if (o == NULL) {                        /* output to a dummy buffer if o not set */
00373       o = dummy;
00374    }
00375 
00376    if (udhl) {                             /* header */
00377       o[p++] = udhl;
00378       b = 1;
00379       n = 1;
00380       while (udhl--) {
00381          o[p++] = *udh++;
00382          b += 8;
00383          while (b >= 7) {
00384             b -= 7;
00385             n++;
00386          }
00387          if (n >= SMSLEN)
00388             return n;
00389       }
00390       if (b) {
00391          b = 7 - b;
00392          if (++n >= SMSLEN)
00393             return n;
00394       }                                   /* filling to septet boundary */
00395    }
00396    o[p] = 0;
00397    /* message */
00398    while (udl--) {
00399       long u;
00400       unsigned char v;
00401       u = *ud++;
00402       /* XXX 0 is invalid ? */
00403       /* look up in defaultalphabet[]. If found, v is the 7-bit code */
00404       for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
00405       if (v == 128 /* not found */ && u && n + 1 < SMSLEN) {
00406          /* if not found, look in the escapes table (we need 2 bytes) */
00407          for (v = 0; v < 128 && escapes[v] != u; v++);
00408          if (v < 128) { /* escaped sequence, esc + v */
00409             /* store the low (8-b) bits in o[p], the remaining bits in o[p+1] */
00410             o[p] |= (27 << b);          /* the low bits go into o[p] */ 
00411             b += 7;
00412             if (b >= 8) {
00413                b -= 8;
00414                p++;
00415                o[p] = (27 >> (7 - b));
00416             }
00417             n++;
00418          }
00419       }
00420       if (v == 128)
00421          return -1;                      /* invalid character */
00422       /* store, same as above */
00423       o[p] |= (v << b);
00424       b += 7;
00425       if (b >= 8) {
00426          b -= 8;
00427          p++;
00428          o[p] = (v >> (7 - b));
00429       }
00430       if (++n >= SMSLEN)
00431          return n;
00432    }
00433    return n;
00434 }
00435 
00436 /*! \brief takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud)
00437  * and packs in to o using 8 bit character codes.
00438  * The return value is the number of bytes packed in to o, which is internally limited to 140.
00439  * o can be null, in which case this is used to validate or count only.
00440  * if the input contains invalid characters then the return value is -1
00441  */
00442 static int packsms8(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00443 {
00444    unsigned char p = 0;
00445    unsigned char dummy[SMSLEN_8];
00446 
00447    if (o == NULL)
00448       o = dummy;
00449    /* header - no encoding */
00450    if (udhl) {
00451       o[p++] = udhl;
00452       while (udhl--) {
00453          o[p++] = *udh++;
00454          if (p >= SMSLEN_8) {
00455             return p;
00456          }
00457       }
00458    }
00459    while (udl--) {
00460       long u;
00461       u = *ud++;
00462       if (u < 0 || u > 0xFF) {
00463          return -1;                      /* not valid */
00464       }
00465       o[p++] = u;
00466       if (p >= SMSLEN_8) {
00467          return p;
00468       }
00469    }
00470    return p;
00471 }
00472 
00473 /*! \brief takes a binary header (udhl bytes at udh) and UCS-2 
00474    message (udl characters at ud) and packs in to o using 16 bit 
00475    UCS-2 character codes 
00476    The return value is the number of bytes packed in to o, which is 
00477    internally limited to 140 
00478    o can be null, in which case this is used to validate or count 
00479    only if the input contains invalid characters then 
00480    the return value is -1 */
00481 static int packsms16(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00482 {
00483    unsigned char p = 0;
00484    unsigned char dummy[SMSLEN_8];
00485 
00486    if (o == NULL) {
00487       o = dummy;
00488    }
00489    /* header - no encoding */
00490    if (udhl) {
00491       o[p++] = udhl;
00492       while (udhl--) {
00493          o[p++] = *udh++;
00494          if (p >= SMSLEN_8) {
00495             return p;
00496          }
00497       }
00498    }
00499    while (udl--) {
00500       long u;
00501       u = *ud++;
00502       o[p++] = (u >> 8);
00503       if (p >= SMSLEN_8) {
00504          return p - 1;                   /* could not fit last character */
00505       }
00506       o[p++] = u;
00507       if (p >= SMSLEN_8) {
00508          return p;
00509       }
00510    }
00511    return p;
00512 }
00513 
00514 /*! \brief general pack, with length and data, 
00515    returns number of bytes of target used */
00516 static int packsms(unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
00517 {
00518    unsigned char *p = base;
00519    if (udl == 0) {
00520       *p++ = 0;                           /* no user data */
00521    } else {
00522       
00523       int l = 0;
00524       if (is7bit(dcs)) {                  /* 7 bit */
00525          if ((l = packsms7(p + 1, udhl, udh, udl, ud)) < 0) {
00526             l = 0;
00527          }
00528          *p++ = l;
00529          p += (l * 7 + 7) / 8;
00530       } else if (is8bit(dcs)) {           /* 8 bit */
00531          if ((l = packsms8(p + 1, udhl, udh, udl, ud)) < 0) {
00532             l = 0;
00533          }
00534          *p++ = l;
00535          p += l;
00536       } else {                            /* UCS-2 */
00537          if ((l = packsms16(p + 1, udhl, udh, udl, ud)) < 0) {
00538             l = 0;
00539          }
00540          *p++ = l;
00541          p += l;
00542       }
00543    }
00544    return p - base;
00545 }
00546 
00547 
00548 /*! \brief pack a date and return */
00549 static void packdate(unsigned char *o, time_t w)
00550 {
00551    struct ast_tm t;
00552    struct timeval topack = { w, 0 };
00553    int z;
00554 
00555    ast_localtime(&topack, &t, NULL);
00556 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
00557    z = -t.tm_gmtoff / 60 / 15;
00558 #else
00559    z = timezone / 60 / 15;
00560 #endif
00561    *o++ = ((t.tm_year % 10) << 4) + (t.tm_year % 100) / 10;
00562    *o++ = (((t.tm_mon + 1) % 10) << 4) + (t.tm_mon + 1) / 10;
00563    *o++ = ((t.tm_mday % 10) << 4) + t.tm_mday / 10;
00564    *o++ = ((t.tm_hour % 10) << 4) + t.tm_hour / 10;
00565    *o++ = ((t.tm_min % 10) << 4) + t.tm_min / 10;
00566    *o++ = ((t.tm_sec % 10) << 4) + t.tm_sec / 10;
00567    if (z < 0) {
00568       *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
00569    } else {
00570       *o++ = ((z % 10) << 4) + z / 10;
00571    }
00572 }
00573 
00574 /*! \brief unpack a date and return */
00575 static struct timeval unpackdate(unsigned char *i)
00576 {
00577    struct ast_tm t;
00578 
00579    t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
00580    t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
00581    t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
00582    t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
00583    t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
00584    t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
00585    t.tm_isdst = 0;
00586    if (i[6] & 0x08) {
00587       t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00588    } else {
00589       t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00590    }
00591 
00592    return ast_mktime(&t, NULL);
00593 }
00594 
00595 /*! \brief unpacks bytes (7 bit encoding) at i, len l septets, 
00596    and places in udh and ud setting udhl and udl. udh not used 
00597    if udhi not set */
00598 static void unpacksms7(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00599 {
00600    unsigned char b = 0, p = 0;
00601    unsigned short *o = ud;
00602    *udhl = 0;
00603    if (udhi && l) {                        /* header */
00604       int h = i[p];
00605       *udhl = h;
00606       if (h) {
00607          b = 1;
00608          p++;
00609          l--;
00610          while (h-- && l) {
00611             *udh++ = i[p++];
00612             b += 8;
00613             while (b >= 7) {
00614                b -= 7;
00615                l--;
00616                if (!l) {
00617                   break;
00618                }
00619             }
00620          }
00621          /* adjust for fill, septets */
00622          if (b) {
00623             b = 7 - b;
00624             l--;
00625          }
00626       }
00627    }
00628    while (l--) {
00629       unsigned char v;
00630       if (b < 2) {
00631          v = ((i[p] >> b) & 0x7F);       /* everything in one byte */
00632       } else {
00633          v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
00634       }
00635       b += 7;
00636       if (b >= 8) {
00637          b -= 8;
00638          p++;
00639       }
00640       /* 0x00A0 is the encoding of ESC (27) in defaultalphabet */
00641       if (o > ud && o[-1] == 0x00A0 && escapes[v]) {
00642          o[-1] = escapes[v];
00643       } else {
00644          *o++ = defaultalphabet[v];
00645       }
00646    }
00647    *udl = (o - ud);
00648 }
00649 
00650 /*! \brief unpacks bytes (8 bit encoding) at i, len l septets, 
00651  *  and places in udh and ud setting udhl and udl. udh not used 
00652  *  if udhi not set.
00653  */
00654 static void unpacksms8(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00655 {
00656    unsigned short *o = ud;
00657    *udhl = 0;
00658    if (udhi) {
00659       int n = *i;
00660       *udhl = n;
00661       if (n) {
00662          i++;
00663          l--;
00664          while (l && n) {
00665             l--;
00666             n--;
00667             *udh++ = *i++;
00668          }
00669       }
00670    }
00671    while (l--) {
00672       *o++ = *i++;                        /* not to UTF-8 as explicitly 8 bit coding in DCS */
00673    }
00674    *udl = (o - ud);
00675 }
00676 
00677 /*! \brief unpacks bytes (16 bit encoding) at i, len l septets,
00678     and places in udh and ud setting udhl and udl. 
00679    udh not used if udhi not set */
00680 static void unpacksms16(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00681 {
00682    unsigned short *o = ud;
00683    *udhl = 0;
00684    if (udhi) {
00685       int n = *i;
00686       *udhl = n;
00687       if (n) {
00688          i++;
00689          l--;
00690          while (l && n) {
00691             l--;
00692             n--;
00693             *udh++ = *i++;
00694          }
00695       }
00696    }
00697    while (l--) {
00698       int v = *i++;
00699       if (l && l--) {
00700          v = (v << 8) + *i++;
00701       }
00702       *o++ = v;
00703    }
00704    *udl = (o - ud);
00705 }
00706 
00707 /*! \brief general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length */
00708 static int unpacksms(unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00709 {
00710    int l = *i++;
00711    if (is7bit(dcs)) {
00712       unpacksms7(i, l, udh, udhl, ud, udl, udhi);
00713       l = (l * 7 + 7) / 8;                /* adjust length to return */
00714    } else if (is8bit(dcs)) {
00715       unpacksms8(i, l, udh, udhl, ud, udl, udhi);
00716    } else {
00717       l += l % 2;
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->ud)) {
01274             msgsz = sizeof(h->ud) - 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\n");
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       }
01469    }
01470    sms_messagetx(h);
01471 }
01472 
01473 #define DIR_RX 1
01474 #define DIR_TX 2
01475 static void sms_debug (int dir, sms_t *h)
01476 {
01477    char txt[259 * 3 + 1];
01478    char *p = txt;                          /* always long enough */
01479    unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
01480    int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
01481    int q = 0;
01482    while (q < n && q < 30) {
01483       sprintf(p, " %02X", msg[q++]);
01484       p += 3;
01485    }
01486    if (q < n) {
01487       sprintf(p, "...");
01488    }
01489    ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
01490 }
01491 
01492 
01493 static void sms_messagerx(sms_t * h)
01494 {
01495    int cause;
01496 
01497    sms_debug (DIR_RX, h);
01498    if (h->protocol == 2) {
01499       sms_messagerx2(h);
01500       return;
01501    }
01502    /* parse incoming message for Protocol 1 */
01503    switch (h->imsg[0]) {
01504    case 0x91:                              /* SMS_DATA */
01505       cause = sms_handleincoming (h);
01506       if (!cause) {
01507          sms_log(h, 'Y');
01508          h->omsg[0] = 0x95;              /* SMS_ACK */
01509          h->omsg[1] = 0x02;
01510          h->omsg[2] = 0x00;              /* deliver report */
01511          h->omsg[3] = 0x00;              /* no parameters */
01512       } else {                            /* NACK */
01513          sms_log(h, 'N');
01514          h->omsg[0] = 0x96;              /* SMS_NACK */
01515          h->omsg[1] = 3;
01516          h->omsg[2] = 0;                 /* delivery report */
01517          h->omsg[3] = cause;             /* cause */
01518          h->omsg[4] = 0;                 /* no parameters */
01519       }
01520       sms_messagetx(h);
01521       break;
01522 
01523    case 0x92:                              /* SMS_ERROR */
01524       h->err = 1;
01525       sms_messagetx(h);                   /* send whatever we sent again */
01526       break;
01527    case 0x93:                              /* SMS_EST */
01528       sms_nextoutgoing (h);
01529       break;
01530    case 0x94:                              /* SMS_REL */
01531       h->hangup = 1;                      /* hangup */
01532       break;
01533    case 0x95:                              /* SMS_ACK */
01534       sms_log(h, 'Y');
01535       sms_nextoutgoing (h);
01536       break;
01537    case 0x96:                              /* SMS_NACK */
01538       h->err = 1;
01539       sms_log(h, 'N');
01540       sms_nextoutgoing (h);
01541       break;
01542    default:                                /* Unknown */
01543       h->omsg[0] = 0x92;                  /* SMS_ERROR */
01544       h->omsg[1] = 1;
01545       h->omsg[2] = 3;                     /* unknown message type */
01546       sms_messagetx(h);
01547       break;
01548    }
01549 }
01550 
01551 static void sms_messagetx(sms_t * h)
01552 {
01553    unsigned char c = 0, p;
01554    int len = h->omsg[1] + 2;               /* total message length excluding checksum */
01555 
01556    for (p = 0; p < len; p++) {             /* compute checksum */
01557       c += h->omsg[p];
01558    }
01559    h->omsg[len] = 0 - c;                   /* actually, (256 - (c & 0fxx)) & 0xff) */
01560    sms_debug(DIR_TX, h);
01561    h->framenumber++;                       /* Proto 2 */
01562    h->obytep = 0;
01563    h->obitp = 0;
01564    if (h->protocol == 2) {                 /* Proto 2: */
01565       h->oseizure = 300;                  /* 300bits (or more ?) */
01566       h->obyte = 0;                       /* Seizure starts with  space (0) */
01567       if (h->omsg[0] == 0x7F) {
01568          h->opause = 8 * h->opause_0;    /* initial message delay */
01569       } else {
01570          h->opause = 400;
01571       }
01572    } else {                                /* Proto 1: */
01573       h->oseizure = 0;                    /* No seizure */
01574       h->obyte = 1;                       /* send mark ('1') at the beginning */
01575       /* Change the initial message delay. BT requires 300ms,
01576        * but for others this might be way too much and the phone
01577        * could time out. XXX make it configurable.
01578       */
01579       if (h->omsg[0] == 0x93) {
01580          h->opause = 8 * h->opause_0;    /* initial message delay */
01581       } else {
01582          h->opause = 200;
01583       }
01584    }
01585    /* Note - setting osync triggers the generator */
01586    h->osync = OSYNC_BITS;                  /* 80 sync bits */
01587    h->obyten = len + 1;                    /* bytes to send (including checksum) */
01588 }
01589 
01590 /*!
01591  * outgoing data are produced by this generator function, that reads from
01592  * the descriptor whether it has data to send and which ones.
01593  */
01594 static int sms_generate(struct ast_channel *chan, void *data, int len, int samples)
01595 {
01596    struct ast_frame f = { 0 };
01597 #define MAXSAMPLES (800)
01598    output_t *buf;
01599    sms_t *h = data;
01600    int i;
01601 
01602    if (samples > MAXSAMPLES) {
01603       ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
01604           MAXSAMPLES, samples);
01605       samples = MAXSAMPLES;
01606    }
01607    len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET;
01608    buf = ast_alloca(len);
01609 
01610    f.frametype = AST_FRAME_VOICE;
01611    ast_format_set(&f.subclass.format, __OUT_FMT, 0);
01612    f.datalen = samples * sizeof(*buf);
01613    f.offset = AST_FRIENDLY_OFFSET;
01614    f.mallocd = 0;
01615    f.data.ptr = buf;
01616    f.samples = samples;
01617    f.src = "app_sms";
01618    /* create a buffer containing the digital sms pattern */
01619    for (i = 0; i < samples; i++) {
01620       buf[i] = wave_out[0];               /* default is silence */
01621 
01622       if (h->opause) {
01623          h->opause--;
01624       } else if (h->obyten || h->osync) { /* sending data */
01625          buf[i] = wave_out[h->ophase];
01626          h->ophase += (h->obyte & 1) ? 13 : 21; /* compute next phase */
01627          if (h->ophase >= 80)
01628             h->ophase -= 80;
01629          if ((h->ophasep += 12) >= 80) { /* time to send the next bit */
01630             h->ophasep -= 80;
01631             if (h->oseizure > 0) {      /* sending channel seizure (proto 2) */
01632                h->oseizure--;
01633                h->obyte ^= 1;          /* toggle low bit */
01634             } else if (h->osync) {
01635                h->obyte = 1;           /* send mark as sync bit */
01636                h->osync--;             /* sending sync bits */
01637                if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
01638                   h->obytep = h->obyten = 0; /* we are done */
01639                }
01640             } else {
01641                h->obitp++;
01642                if (h->obitp == 1) {
01643                   h->obyte = 0;       /* start bit; */
01644                } else if (h->obitp == 2) {
01645                   h->obyte = h->omsg[h->obytep];
01646                } else if (h->obitp == 10) {
01647                   h->obyte = 1; /* stop bit */
01648                   h->obitp = 0;
01649                   h->obytep++;
01650                   if (h->obytep == h->obyten) {
01651                      h->obytep = h->obyten = 0; /* sent */
01652                      h->osync = 10;   /* trailing marks */
01653                   }
01654                } else {
01655                   h->obyte >>= 1;
01656                }
01657             }
01658          }
01659       }
01660    }
01661    if (ast_write(chan, &f) < 0) {
01662       ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
01663       return -1;
01664    }
01665    return 0;
01666 #undef MAXSAMPLES
01667 }
01668 
01669 /*!
01670  * Just return the pointer to the descriptor that we received.
01671  */
01672 static void *sms_alloc(struct ast_channel *chan, void *sms_t_ptr)
01673 {
01674    return sms_t_ptr;
01675 }
01676 
01677 static void sms_release(struct ast_channel *chan, void *data)
01678 {
01679    return;  /* nothing to do here. */
01680 }
01681 
01682 static struct ast_generator smsgen = {
01683    .alloc = sms_alloc,
01684    .release = sms_release,
01685    .generate = sms_generate,
01686 };
01687 
01688 /*!
01689  * Process an incoming frame, trying to detect the carrier and
01690  * decode the message. The two frequencies are 1300 and 2100 Hz.
01691  * The decoder detects the amplitude of the signal over the last
01692  * few samples, filtering the absolute values with a lowpass filter.
01693  * If the magnitude (h->imag) is large enough, multiply the signal
01694  * by the two carriers, and compute the amplitudes m0 and m1.
01695  * Record the current sample as '0' or '1' depending on which one is greater.
01696  * The last 3 bits are stored in h->ibith, with the count of '1'
01697  * bits in h->ibitt.
01698  * XXX the rest is to be determined.
01699  */
01700 static void sms_process(sms_t * h, int samples, signed short *data)
01701 {
01702    int bit;
01703 
01704    /*
01705     * Ignore incoming audio while a packet is being transmitted,
01706     * the protocol is half-duplex.
01707     * Unfortunately this means that if the outbound and incoming
01708     * transmission overlap (which is an error condition anyways),
01709     * we may miss some data and this makes debugging harder.
01710     */
01711    if (h->obyten || h->osync) {
01712       return;
01713    }
01714    for ( ; samples-- ; data++) {
01715       unsigned long long m0, m1;
01716       if (abs(*data) > h->imag) {
01717          h->imag = abs(*data);
01718       } else {
01719          h->imag = h->imag * 7 / 8;
01720       }
01721       if (h->imag <= 500) {               /* below [arbitrary] threahold: lost carrier */
01722          if (h->idle++ == 80000) {       /* nothing happening */
01723             ast_log(LOG_NOTICE, "No data, hanging up\n");
01724             h->hangup = 1;
01725             h->err = 1;
01726          }
01727          if (h->ierr) {                  /* error */
01728             ast_log(LOG_NOTICE, "Error %d, hanging up\n", h->ierr);
01729             /* Protocol 1 */
01730             h->err = 1;
01731             h->omsg[0] = 0x92;          /* error */
01732             h->omsg[1] = 1;
01733             h->omsg[2] = h->ierr;
01734             sms_messagetx(h);           /* send error */
01735          }
01736          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01737          continue;
01738       }
01739       h->idle = 0;
01740 
01741       /* multiply signal by the two carriers. */
01742       h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
01743       h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
01744       h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
01745       h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
01746       /* compute the amplitudes */
01747       m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
01748       m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
01749 
01750       /* advance the sin/cos pointers */
01751       if ((h->ips0 += 21) >= 80) {
01752          h->ips0 -= 80;
01753       }
01754       if ((h->ipc0 += 21) >= 80) {
01755          h->ipc0 -= 80;
01756       }
01757       if ((h->ips1 += 13) >= 80) {
01758          h->ips1 -= 80;
01759       }
01760       if ((h->ipc1 += 13) >= 80) {
01761          h->ipc1 -= 80;
01762       }
01763 
01764       /* set new bit to 1 or 0 depending on which value is stronger */
01765       h->ibith <<= 1;
01766       if (m1 > m0) {
01767          h->ibith |= 1;
01768       }
01769       if (h->ibith & 8) {
01770          h->ibitt--;
01771       }
01772       if (h->ibith & 1) {
01773          h->ibitt++;
01774       }
01775       bit = ((h->ibitt > 1) ? 1 : 0);
01776       if (bit != h->ibitl) {
01777          h->ibitc = 1;
01778       } else {
01779          h->ibitc++;
01780       }
01781       h->ibitl = bit;
01782       if (!h->ibitn && h->ibitc == 4 && !bit) {
01783          h->ibitn = 1;
01784          h->iphasep = 0;
01785       }
01786       if (bit && h->ibitc == 200) {       /* sync, restart message */
01787          /* Protocol 2: empty connection ready (I am master) */
01788          if (h->framenumber < 0 && h->ibytec >= 160 && !memcmp(h->imsg, "UUUUUUUUUUUUUUUUUUUU", 20)) {
01789             h->framenumber = 1;
01790             ast_verb(3, "SMS protocol 2 detected\n");
01791             h->protocol = 2;
01792             h->imsg[0] = 0xff;          /* special message (fake) */
01793             h->imsg[1] = h->imsg[2] = 0x00;
01794             h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01795             sms_messagerx(h);
01796          }
01797          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01798       }
01799       if (h->ibitn) {
01800          h->iphasep += 12;
01801          if (h->iphasep >= 80) {         /* next bit */
01802             h->iphasep -= 80;
01803             if (h->ibitn++ == 9) {      /* end of byte */
01804                if (!bit) {             /* bad stop bit */
01805                   ast_log(LOG_NOTICE, "bad stop bit\n");
01806                   h->ierr = 0xFF;     /* unknown error */
01807                } else {
01808                   if (h->ibytep < sizeof(h->imsg)) {
01809                      h->imsg[h->ibytep] = h->ibytev;
01810                      h->ibytec += h->ibytev;
01811                      h->ibytep++;
01812                   } else if (h->ibytep == sizeof(h->imsg)) {
01813                      ast_log(LOG_NOTICE, "msg too large\n");
01814                      h->ierr = 2;    /* bad message length */
01815                   }
01816                   if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
01817                      if (!h->ibytec) {
01818                         sms_messagerx(h);
01819                      } else {
01820                         ast_log(LOG_NOTICE, "bad checksum\n");
01821                         h->ierr = 1; /* bad checksum */
01822                      }
01823                   }
01824                }
01825                h->ibitn = 0;
01826             }
01827             h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
01828          }
01829       }
01830    }
01831 }
01832 
01833 /*
01834  * Standard argument parsing:
01835  * - one enum for the flags we recognise,
01836  * - one enum for argument indexes
01837  * - AST_APP_OPTIONS() to drive the parsing routine
01838  * - in the function, AST_DECLARE_APP_ARGS(...) for the arguments.
01839  */
01840 enum sms_flags {
01841    OPTION_BE_SMSC = (1 << 0),             /* act as sms center */
01842    OPTION_ANSWER  = (1 << 1),             /* answer on incoming calls */
01843    OPTION_TWO  = (1 << 2),                 /* Use Protocol Two */
01844    OPTION_PAUSE   = (1 << 3),             /* pause before sending data, in ms */
01845    OPTION_SRR  = (1 << 4),                 /* set srr */
01846    OPTION_DCS  = (1 << 5),                 /* set dcs */
01847 };
01848 
01849 enum sms_opt_args {
01850    OPTION_ARG_PAUSE = 0,
01851    OPTION_ARG_ARRAY_SIZE
01852 };
01853 
01854 AST_APP_OPTIONS(sms_options, {
01855    AST_APP_OPTION('s', OPTION_BE_SMSC),
01856    AST_APP_OPTION('a', OPTION_ANSWER),
01857    AST_APP_OPTION('t', OPTION_TWO),
01858    AST_APP_OPTION('r', OPTION_SRR),
01859    AST_APP_OPTION('o', OPTION_DCS),
01860    AST_APP_OPTION_ARG('p', OPTION_PAUSE, OPTION_ARG_PAUSE),
01861    } );
01862 
01863 static int sms_exec(struct ast_channel *chan, const char *data)
01864 {
01865    int res = -1;
01866    sms_t h = { 0 };
01867    /* argument parsing support */
01868    struct ast_flags flags;
01869    char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, };
01870    char *p;
01871    AST_DECLARE_APP_ARGS(sms_args,
01872       AST_APP_ARG(queue);
01873       AST_APP_ARG(options);
01874       AST_APP_ARG(addr);
01875       AST_APP_ARG(body);
01876    );
01877 
01878    if (!data) {
01879       ast_log(LOG_ERROR, "Requires queue name at least\n");
01880       return -1;
01881    }
01882 
01883    parse = ast_strdupa(data);              /* create a local copy */
01884    AST_STANDARD_APP_ARGS(sms_args, parse);
01885    if (sms_args.argc > 1) {
01886       ast_app_parse_options(sms_options, &flags, sms_opts, sms_args.options);
01887    }
01888 
01889    ast_verb(1, "sms argc %d queue <%s> opts <%s> addr <%s> body <%s>\n",
01890       sms_args.argc, S_OR(sms_args.queue, ""),
01891       S_OR(sms_args.options, ""),
01892       S_OR(sms_args.addr, ""),
01893       S_OR(sms_args.body, "") );
01894 
01895    h.ipc0 = h.ipc1 = 20;                   /* phase for cosine */
01896    h.dcs = 0xF1;                           /* default */
01897 
01898    ast_copy_string(h.cli,
01899       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
01900       sizeof(h.cli));
01901 
01902    if (ast_strlen_zero(sms_args.queue)) {
01903       ast_log(LOG_ERROR, "Requires queue name\n");
01904       goto done;
01905    }
01906    if (strlen(sms_args.queue) >= sizeof(h.queue)) {
01907       ast_log(LOG_ERROR, "Queue name too long\n");
01908       goto done;
01909    }
01910    ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue));
01911 
01912    for (p = h.queue; *p; p++) {
01913       if (!isalnum(*p)) {
01914          *p = '-';                       /* make very safe for filenames */
01915       }
01916    }
01917 
01918    h.smsc = ast_test_flag(&flags, OPTION_BE_SMSC);
01919    h.protocol = ast_test_flag(&flags, OPTION_TWO) ? 2 : 1;
01920    if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE])) {
01921       h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
01922    }
01923    if (h.opause_0 < 25 || h.opause_0 > 2000) {
01924       h.opause_0 = 300;                   /* default 300ms */
01925    }
01926    ast_verb(1, "initial delay %dms\n", h.opause_0);
01927 
01928 
01929    /* the following apply if there is an arg3/4 and apply to the created message file */
01930    if (ast_test_flag(&flags, OPTION_SRR)) {
01931       h.srr = 1;
01932    }
01933    if (ast_test_flag(&flags, OPTION_DCS)) {
01934       h.dcs = 1;
01935    }
01936 #if 0 
01937       case '1':
01938       case '2':
01939       case '3':
01940       case '4':
01941       case '5':
01942       case '6':
01943       case '7':                           /* set the pid for saved local message */
01944          h.pid = 0x40 + (*d & 0xF);
01945          break;
01946       }
01947 #endif
01948    if (sms_args.argc > 2) {
01949       unsigned char *up;
01950 
01951       /* submitting a message, not taking call. */
01952       /* deprecated, use smsq instead */
01953       h.scts = ast_tvnow();
01954       if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) {
01955          ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr);
01956          goto done;
01957       }
01958       if (h.smsc) {
01959          ast_copy_string(h.oa, sms_args.addr, sizeof(h.oa));
01960       } else {
01961          ast_copy_string(h.da, sms_args.addr, sizeof(h.da));
01962          ast_copy_string(h.oa, h.cli, sizeof(h.oa));
01963       }
01964       h.udl = 0;
01965       if (ast_strlen_zero(sms_args.body)) {
01966          ast_log(LOG_ERROR, "Missing body for %s\n", sms_args.addr);
01967          goto done;
01968       }
01969       up = (unsigned char *)sms_args.body;
01970       while (*up && h.udl < SMSLEN) {
01971          h.ud[h.udl++] = utf8decode(&up);
01972       }
01973       if (is7bit(h.dcs) && packsms7(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01974          ast_log(LOG_WARNING, "Invalid 7 bit GSM data\n");
01975          goto done;
01976       }
01977       if (is8bit(h.dcs) && packsms8(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01978          ast_log(LOG_WARNING, "Invalid 8 bit data\n");
01979          goto done;
01980       }
01981       if (is16bit(h.dcs) && packsms16(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01982          ast_log(LOG_WARNING, "Invalid 16 bit data\n");
01983          goto done;
01984       }
01985       h.rx = 0;                           /* sent message */
01986       h.mr = -1;
01987       sms_writefile(&h);
01988       res = h.err;
01989       goto done;
01990    }
01991    
01992    if (ast_channel_state(chan) != AST_STATE_UP) {     /* make sure channel is answered before any TX */
01993       ast_answer(chan);
01994    }
01995 
01996    if (ast_test_flag(&flags, OPTION_ANSWER)) {
01997       h.framenumber = 1;                  /* Proto 2 */
01998       /* set up SMS_EST initial message */
01999       if (h.protocol == 2) {
02000          h.omsg[0] = DLL2_SMS_EST;
02001          h.omsg[1] = 0;
02002       } else {
02003          h.omsg[0] = DLL1_SMS_EST | DLL1_SMS_COMPLETE;
02004          h.omsg[1] = 0;
02005       }
02006       sms_messagetx(&h);
02007    }
02008 
02009    res = ast_set_write_format_by_id(chan, __OUT_FMT);
02010    if (res >= 0) {
02011       res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
02012    }
02013    if (res < 0) {
02014       ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
02015       goto done;
02016    }
02017 
02018    if ( (res = ast_activate_generator(chan, &smsgen, &h)) < 0) {
02019       ast_log(LOG_ERROR, "Failed to activate generator on '%s'\n", ast_channel_name(chan));
02020       goto done;
02021    }
02022 
02023    /* Do our thing here */
02024    for (;;) {
02025       struct ast_frame *f;
02026       int i = ast_waitfor(chan, -1);
02027       if (i < 0) {
02028          ast_log(LOG_NOTICE, "waitfor failed\n");
02029          break;
02030       }
02031       if (h.hangup) {
02032          ast_log(LOG_NOTICE, "channel hangup\n");
02033          break;
02034       }
02035       f = ast_read(chan);
02036       if (!f) {
02037          ast_log(LOG_NOTICE, "ast_read failed\n");
02038          break;
02039       }
02040       if (f->frametype == AST_FRAME_VOICE) {
02041          sms_process(&h, f->samples, f->data.ptr);
02042       }
02043 
02044       ast_frfree(f);
02045    }
02046    res = h.err;                            /* XXX */
02047 
02048    /* 
02049     * The SMS generator data is on the stack.  We _MUST_ make sure the generator
02050     * is stopped before returning from this function.
02051     */
02052    ast_deactivate_generator(chan);
02053 
02054    sms_log(&h, '?');                       /* log incomplete message */
02055 done:
02056    return (res);
02057 }
02058 
02059 static int unload_module(void)
02060 {
02061    return ast_unregister_application(app);
02062 }
02063 
02064 static int load_module(void)
02065 {
02066 #ifdef OUTALAW
02067    int p;
02068    for (p = 0; p < 80; p++) {
02069       wavea[p] = AST_LIN2A(wave[p]);
02070    }
02071 #endif
02072    snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR);
02073    return ast_register_application_xml(app, sms_exec);
02074 }
02075 
02076 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SMS/PSTN handler");