Fri Aug 17 00:17:09 2018

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: 413586 $")
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 && 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       l += l % 2;
00719       unpacksms16(i, l, udh, udhl, ud, udl, udhi);
00720    }
00721    return l + 1;
00722 }
00723 
00724 /*! \brief unpack an address from i, return byte length, unpack to o */
00725 static unsigned char unpackaddress(char *o, unsigned char *i)
00726 {
00727    unsigned char l = i[0], p;
00728    if (i[1] == 0x91) {
00729       *o++ = '+';
00730    }
00731    for (p = 0; p < l; p++) {
00732       if (p & 1) {
00733          *o++ = (i[2 + p / 2] >> 4) + '0';
00734       } else {
00735          *o++ = (i[2 + p / 2] & 0xF) + '0';
00736       }
00737    }
00738    *o = 0;
00739    return (l + 5) / 2;
00740 }
00741 
00742 /*! \brief store an address at o, and return number of bytes used */
00743 static unsigned char packaddress(unsigned char *o, char *i)
00744 {
00745    unsigned char p = 2;
00746    o[0] = 0;                               /* number of bytes */
00747    if (*i == '+') {                        /* record as bit 0 in byte 1 */
00748       i++;
00749       o[1] = 0x91;
00750    } else {
00751       o[1] = 0x81;
00752    }
00753    for ( ; *i ; i++) {
00754       if (!isdigit(*i)) {                 /* ignore non-digits */
00755          continue;
00756       }
00757       if (o[0] & 1) {
00758          o[p++] |= ((*i & 0xF) << 4);
00759       } else {
00760          o[p] = (*i & 0xF);
00761       }
00762       o[0]++;
00763    }
00764    if (o[0] & 1) {
00765       o[p++] |= 0xF0;                     /* pad */
00766    }
00767    return p;
00768 }
00769 
00770 /*! \brief Log the output, and remove file */
00771 static void sms_log(sms_t * h, char status)
00772 {
00773    int o;
00774 
00775    if (*h->oa == '\0' && *h->da == '\0') {
00776       return;
00777    }
00778    o = open(log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE);
00779    if (o >= 0) {
00780       char line[1000], mrs[3] = "", *p;
00781       char buf[30];
00782       unsigned char n;
00783 
00784       if (h->mr >= 0) {
00785          snprintf(mrs, sizeof(mrs), "%02X", (unsigned)h->mr);
00786       }
00787       snprintf(line, sizeof(line), "%s %c%c%c%s %s %s %s ",
00788          isodate(time(NULL), buf, sizeof(buf)),
00789          status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue,
00790          S_OR(h->oa, "-"), S_OR(h->da, "-") );
00791       p = line + strlen(line);
00792       for (n = 0; n < h->udl; n++) {
00793          if (h->ud[n] == '\\') {
00794             *p++ = '\\';
00795             *p++ = '\\';
00796          } else if (h->ud[n] == '\n') {
00797             *p++ = '\\';
00798             *p++ = 'n';
00799          } else if (h->ud[n] == '\r') {
00800             *p++ = '\\';
00801             *p++ = 'r';
00802          } else if (h->ud[n] < 32 || h->ud[n] == 127) {
00803             *p++ = 191;
00804          } else {
00805             *p++ = h->ud[n];
00806          }
00807       }
00808       *p++ = '\n';
00809       *p = 0;
00810       if (write(o, line, strlen(line)) < 0) {
00811          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00812       }
00813       close(o);
00814    }
00815    *h->oa = *h->da = h->udl = 0;
00816 }
00817 
00818 /*! \brief parse and delete a file */
00819 static void sms_readfile(sms_t * h, char *fn)
00820 {
00821    char line[1000];
00822    FILE *s;
00823    char dcsset = 0;                        /* if DSC set */
00824    ast_log(LOG_NOTICE, "Sending %s\n", fn);
00825    h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
00826    h->mr = -1;
00827    h->dcs = 0xF1;                          /* normal messages class 1 */
00828    h->scts = ast_tvnow();
00829    s = fopen(fn, "r");
00830    if (s) {
00831       if (unlink(fn)) {                   /* concurrent access, we lost */
00832          fclose(s);
00833          return;
00834       }
00835       while (fgets (line, sizeof(line), s)) {   /* process line in file */
00836          char *p;
00837          void *pp = &p;
00838          for (p = line; *p && *p != '\n' && *p != '\r'; p++);
00839          *p = 0;                         /* strip eoln */
00840          p = line;
00841          if (!*p || *p == ';') {
00842             continue;                   /* blank line or comment, ignore */
00843          }
00844          while (isalnum(*p)) {
00845             *p = tolower (*p);
00846             p++;
00847          }
00848          while (isspace (*p)) {
00849             *p++ = 0;
00850          }
00851          if (*p == '=') {
00852             *p++ = 0;
00853             if (!strcmp(line, "ud")) {  /* parse message (UTF-8) */
00854                unsigned char o = 0;
00855                memcpy(h->udtxt, p, SMSLEN); /* for protocol 2 */
00856                while (*p && o < SMSLEN) {
00857                   h->ud[o++] = utf8decode(pp);
00858                }
00859                h->udl = o;
00860                if (*p) {
00861                   ast_log(LOG_WARNING, "UD too long in %s\n", fn);
00862                }
00863             } else {
00864                while (isspace (*p)) {
00865                   p++;
00866                }
00867                if (!strcmp(line, "oa") && strlen(p) < sizeof(h->oa)) {
00868                   numcpy (h->oa, p);
00869                } else if (!strcmp(line, "da") && strlen(p) < sizeof(h->oa)) {
00870                   numcpy (h->da, p);
00871                } else if (!strcmp(line, "pid")) {
00872                   h->pid = atoi(p);
00873                } else if (!strcmp(line, "dcs")) {
00874                   h->dcs = atoi(p);
00875                   dcsset = 1;
00876                } else if (!strcmp(line, "mr")) {
00877                   h->mr = atoi(p);
00878                } else if (!strcmp(line, "srr")) {
00879                   h->srr = (atoi(p) ? 1 : 0);
00880                } else if (!strcmp(line, "vp")) {
00881                   h->vp = atoi(p);
00882                } else if (!strcmp(line, "rp")) {
00883                   h->rp = (atoi(p) ? 1 : 0);
00884                } else if (!strcmp(line, "scts")) {    /* get date/time */
00885                   int Y, m, d, H, M, S;
00886                   /* XXX Why aren't we using ast_strptime here? */
00887                   if (sscanf(p, "%4d-%2d-%2dT%2d:%2d:%2d", &Y, &m, &d, &H, &M, &S) == 6) {
00888                      struct ast_tm t = { 0, };
00889                      t.tm_year = Y - 1900;
00890                      t.tm_mon = m - 1;
00891                      t.tm_mday = d;
00892                      t.tm_hour = H;
00893                      t.tm_min = M;
00894                      t.tm_sec = S;
00895                      t.tm_isdst = -1;
00896                      h->scts = ast_mktime(&t, NULL);
00897                      if (h->scts.tv_sec == 0) {
00898                         ast_log(LOG_WARNING, "Bad date/timein %s: %s", fn, p);
00899                      }
00900                   }
00901                } else {
00902                   ast_log(LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
00903                }
00904             }
00905          } else if (*p == '#') {                   /* raw hex format */
00906             *p++ = 0;
00907             if (*p == '#') {
00908                p++;
00909                if (!strcmp(line, "ud")) {        /* user data */
00910                   int o = 0;
00911                   while (*p && o < SMSLEN) {
00912                      if (isxdigit(*p) && isxdigit(p[1]) && isxdigit(p[2]) && isxdigit(p[3])) {
00913                         h->ud[o++] =
00914                            (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 12) +
00915                            (((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
00916                            (((isalpha(p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha(p[3]) ? 9 : 0) + (p[3] & 0xF));
00917                         p += 4;
00918                      } else
00919                         break;
00920                   }
00921                   h->udl = o;
00922                   if (*p)
00923                      ast_log(LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
00924                } else
00925                   ast_log(LOG_WARNING, "Only ud can use ## format, %s\n", fn);
00926             } else if (!strcmp(line, "ud")) {       /* user data */
00927                int o = 0;
00928                while (*p && o < SMSLEN) {
00929                   if (isxdigit(*p) && isxdigit(p[1])) {
00930                      h->ud[o++] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
00931                      p += 2;
00932                   } else {
00933                      break;
00934                   }
00935                }
00936                h->udl = o;
00937                if (*p) {
00938                   ast_log(LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
00939                }
00940             } else if (!strcmp(line, "udh")) {      /* user data header */
00941                unsigned char o = 0;
00942                h->udhi = 1;
00943                while (*p && o < SMSLEN) {
00944                   if (isxdigit(*p) && isxdigit(p[1])) {
00945                      h->udh[o] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
00946                      o++;
00947                      p += 2;
00948                   } else {
00949                      break;
00950                   }
00951                }
00952                h->udhl = o;
00953                if (*p) {
00954                   ast_log(LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
00955                }
00956             } else {
00957                ast_log(LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
00958             }
00959          } else {
00960             ast_log(LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
00961          }
00962       }
00963       fclose(s);
00964       if (!dcsset && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00965          if (packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00966             if (packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00967                ast_log(LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
00968             } else {
00969                h->dcs = 0x08;          /* default to 16 bit */
00970                ast_log(LOG_WARNING, "Sending in 16 bit format(%s)\n", fn);
00971             }
00972          } else {
00973             h->dcs = 0xF5;              /* default to 8 bit */
00974             ast_log(LOG_WARNING, "Sending in 8 bit format(%s)\n", fn);
00975          }
00976       }
00977       if (is7bit(h->dcs) && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00978          ast_log(LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
00979       }
00980       if (is8bit(h->dcs) && packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00981          ast_log(LOG_WARNING, "Invalid 8 bit data %s\n", fn);
00982       }
00983       if (is16bit(h->dcs) && packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00984          ast_log(LOG_WARNING, "Invalid 16 bit data %s\n", fn);
00985       }
00986    }
00987 }
00988 
00989 /*! \brief white a received text message to a file */
00990 static void sms_writefile(sms_t * h)
00991 {
00992    char fn[200] = "", fn2[200] = "";
00993    char buf[30];
00994    FILE *o;
00995 
00996    if (ast_tvzero(h->scts)) {
00997       h->scts = ast_tvnow();
00998    }
00999    snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
01000    ast_mkdir(fn, 0777);                    /* ensure it exists */
01001    ast_copy_string(fn2, fn, sizeof(fn2));
01002    snprintf(fn2 + strlen(fn2), sizeof(fn2) - strlen(fn2), "/%s.%s-%u", h->queue, isodate(h->scts.tv_sec, buf, sizeof(buf)), seq++);
01003    snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/.%s", fn2 + strlen(fn) + 1);
01004    if ((o = fopen(fn, "w")) == NULL) {
01005       return;
01006    }
01007 
01008    if (*h->oa) {
01009       fprintf(o, "oa=%s\n", h->oa);
01010    }
01011    if (*h->da) {
01012       fprintf(o, "da=%s\n", h->da);
01013    }
01014    if (h->udhi) {
01015       unsigned int p;
01016       fprintf(o, "udh#");
01017       for (p = 0; p < h->udhl; p++) {
01018          fprintf(o, "%02X", (unsigned)h->udh[p]);
01019       }
01020       fprintf(o, "\n");
01021    }
01022    if (h->udl) {
01023       unsigned int p;
01024       for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
01025       if (p < h->udl) {
01026          fputc(';', o);                  /* cannot use ud=, but include as a comment for human readable */
01027       }
01028       fprintf(o, "ud=");
01029       for (p = 0; p < h->udl; p++) {
01030          unsigned short v = h->ud[p];
01031          if (v < 32) {
01032             fputc(191, o);
01033          } else if (v < 0x80) {
01034             fputc(v, o);
01035          } else if (v < 0x800) {
01036             fputc(0xC0 + (v >> 6), o);
01037             fputc(0x80 + (v & 0x3F), o);
01038          } else {
01039             fputc(0xE0 + (v >> 12), o);
01040             fputc(0x80 + ((v >> 6) & 0x3F), o);
01041             fputc(0x80 + (v & 0x3F), o);
01042          }
01043       }
01044       fprintf(o, "\n");
01045       for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
01046       if (p < h->udl) {
01047          for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
01048          if (p == h->udl) {              /* can write in ucs-1 hex */
01049             fprintf(o, "ud#");
01050             for (p = 0; p < h->udl; p++) {
01051                fprintf(o, "%02X", (unsigned)h->ud[p]);
01052             }
01053             fprintf(o, "\n");
01054          } else {                        /* write in UCS-2 */
01055             fprintf(o, "ud##");
01056             for (p = 0; p < h->udl; p++) {
01057                fprintf(o, "%04X", (unsigned)h->ud[p]);
01058             }
01059             fprintf(o, "\n");
01060          }
01061       }
01062    }
01063    if (h->scts.tv_sec) {
01064       char datebuf[30];
01065       fprintf(o, "scts=%s\n", isodate(h->scts.tv_sec, datebuf, sizeof(datebuf)));
01066    }
01067    if (h->pid) {
01068       fprintf(o, "pid=%d\n", h->pid);
01069    }
01070    if (h->dcs != 0xF1) {
01071       fprintf(o, "dcs=%d\n", h->dcs);
01072    }
01073    if (h->vp) {
01074       fprintf(o, "vp=%u\n", h->vp);
01075    }
01076    if (h->srr) {
01077       fprintf(o, "srr=1\n");
01078    }
01079    if (h->mr >= 0) {
01080       fprintf(o, "mr=%d\n", h->mr);
01081    }
01082    if (h->rp) {
01083       fprintf(o, "rp=1\n");
01084    }
01085    fclose(o);
01086    if (rename(fn, fn2)) {
01087       unlink(fn);
01088    } else {
01089       ast_log(LOG_NOTICE, "Received to %s\n", fn2);
01090    }
01091 }
01092 
01093 /*! \brief read dir skipping dot files... */
01094 static struct dirent *readdirqueue(DIR *d, char *queue)
01095 {
01096    struct dirent *f;
01097    do {
01098       f = readdir(d);
01099    } while (f && (*f->d_name == '.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] != '.'));
01100    return f;
01101 }
01102 
01103 /*! \brief handle the incoming message */
01104 static unsigned char sms_handleincoming (sms_t * h)
01105 {
01106    unsigned char p = 3;
01107    if (h->smsc) {                          /* SMSC */
01108       if ((h->imsg[2] & 3) == 1) {        /* SMS-SUBMIT */
01109          h->udhl = h->udl = 0;
01110          h->vp = 0;
01111          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
01112          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
01113          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01114          ast_copy_string(h->oa, h->cli, sizeof(h->oa));
01115          h->scts = ast_tvnow();
01116          h->mr = h->imsg[p++];
01117          p += unpackaddress(h->da, h->imsg + p);
01118          h->pid = h->imsg[p++];
01119          h->dcs = h->imsg[p++];
01120          if ((h->imsg[2] & 0x18) == 0x10) {       /* relative VP */
01121             if (h->imsg[p] < 144) {
01122                h->vp = (h->imsg[p] + 1) * 5;
01123             } else if (h->imsg[p] < 168) {
01124                h->vp = 720 + (h->imsg[p] - 143) * 30;
01125             } else if (h->imsg[p] < 197) {
01126                h->vp = (h->imsg[p] - 166) * 1440;
01127             } else {
01128                h->vp = (h->imsg[p] - 192) * 10080;
01129             }
01130             p++;
01131          } else if (h->imsg[2] & 0x18) {
01132             p += 7;                     /* ignore enhanced / absolute VP */
01133          }
01134          p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01135          h->rx = 1;                      /* received message */
01136          sms_writefile(h);               /* write the file */
01137          if (p != h->imsg[1] + 2) {
01138             ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01139             return 0xFF;        /* duh! */
01140          }
01141       } else {
01142          ast_log(LOG_WARNING, "Unknown message type %02X\n", (unsigned)h->imsg[2]);
01143          return 0xFF;
01144       }
01145    } else {                                /* client */
01146       if (!(h->imsg[2] & 3)) {            /* SMS-DELIVER */
01147          *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
01148          h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
01149          h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
01150          h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01151          h->mr = -1;
01152          p += unpackaddress(h->oa, h->imsg + p);
01153          h->pid = h->imsg[p++];
01154          h->dcs = h->imsg[p++];
01155          h->scts = unpackdate(h->imsg + p);
01156          p += 7;
01157          p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01158          h->rx = 1;                      /* received message */
01159          sms_writefile(h);               /* write the file */
01160          if (p != h->imsg[1] + 2) {
01161             ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01162             return 0xFF;                /* duh! */
01163          }
01164       } else {
01165          ast_log(LOG_WARNING, "Unknown message type %02X\n", (unsigned)h->imsg[2]);
01166          return 0xFF;
01167       }
01168    }
01169    return 0;                               /* no error */
01170 }
01171 
01172 #ifdef SOLARIS
01173 #define NAME_MAX 1024
01174 #endif
01175 
01176 /*!
01177  * Add data to a protocol 2 message.
01178  * Use the length field (h->omsg[1]) as a pointer to the next free position.
01179  */
01180 static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
01181 {
01182    int x = h->omsg[1] + 2;                 /* Get current position */
01183    if (x == 2) {
01184       x += 2;                             /* First: skip Payload length (set later) */
01185    }
01186    h->omsg[x++] = msg;                     /* Message code */
01187    h->omsg[x++] = (unsigned char)size;     /* Data size Low */
01188    h->omsg[x++] = 0;                       /* Data size Hi */
01189    for (; size > 0 ; size--) {
01190       h->omsg[x++] = *data++;
01191    }
01192    h->omsg[1] = x - 2;                     /* Frame size */
01193    h->omsg[2] = x - 4;                     /* Payload length (Lo) */
01194    h->omsg[3] = 0;                         /* Payload length (Hi) */
01195 }
01196 
01197 static void putdummydata_proto2(sms_t *h)
01198 {
01199    adddata_proto2(h, 0x10, "\0", 1);           /* Media Identifier > SMS */
01200    adddata_proto2(h, 0x11, "\0\0\0\0\0\0", 6); /* Firmware version */
01201    adddata_proto2(h, 0x12, "\2\0\4", 3);       /* SMS provider ID */
01202    adddata_proto2(h, 0x13, h->udtxt, h->udl);  /* Body */
01203 }
01204 
01205 static void sms_compose2(sms_t *h, int more)
01206 {
01207    struct ast_tm tm;
01208    struct timeval now = h->scts;
01209    char stm[9];
01210 
01211    h->omsg[0] = 0x00;                      /* set later... */
01212    h->omsg[1] = 0;
01213    putdummydata_proto2(h);
01214    if (h->smsc) {                          /* deliver */
01215       h->omsg[0] = 0x11;                  /* SMS_DELIVERY */
01216       /* Required: 10 11 12 13 14 15 17 (seems they must be ordered!) */
01217       ast_localtime(&now, &tm, NULL);
01218       sprintf(stm, "%02d%02d%02d%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);  /* Date mmddHHMM */
01219       adddata_proto2(h, 0x14, stm, 8);    /* Date */
01220       if (*h->oa == 0) {
01221          strcpy(h->oa, "00000000");
01222       }
01223       adddata_proto2(h, 0x15, h->oa, strlen(h->oa)); /* Originator */
01224       adddata_proto2(h, 0x17, "\1", 1);   /* Calling Terminal ID */
01225    } else {                                /* submit */
01226       h->omsg[0] = 0x10;                  /* SMS_SUBMIT */
01227       /* Required: 10 11 12 13 17 18 1B 1C (seems they must be ordered!) */
01228       adddata_proto2(h, 0x17, "\1", 1);   /* Calling Terminal ID */
01229       if (*h->da == 0) {
01230          strcpy(h->da, "00000000");
01231       }
01232       adddata_proto2(h, 0x18, h->da, strlen(h->da)); /* Originator */
01233       adddata_proto2(h, 0x1B, "\1", 1);         /* Called Terminal ID */
01234       adddata_proto2(h, 0x1C, "\0\0\0", 3);    /* Notification */
01235    }
01236 }
01237 
01238 static void putdummydata_proto2(sms_t *h);
01239 
01240 #define MAX_DEBUG_LEN   300
01241 static char *sms_hexdump(unsigned char buf[], int size, char *s /* destination */)
01242 {
01243    char *p;
01244    int f;
01245 
01246    for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3) {
01247       sprintf(p, "%02X ", (unsigned)buf[f]);
01248    }
01249    return(s);
01250 }
01251 
01252 
01253 /*! \brief sms_handleincoming_proto2: handle the incoming message */
01254 static int sms_handleincoming_proto2(sms_t *h)
01255 {
01256    int f, i, sz = 0;
01257    int msg, msgsz;
01258    struct ast_tm tm;
01259    struct timeval now = { 0, 0 };
01260    char debug_buf[MAX_DEBUG_LEN * 3 + 1];
01261 
01262    sz = h->imsg[1] + 2;
01263    /* ast_verb(3, "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg, sz, debug_buf)); */
01264 
01265    /* Parse message body (called payload) */
01266    now = h->scts = ast_tvnow();
01267    for (f = 4; f < sz; ) {
01268       msg = h->imsg[f++];
01269       msgsz = h->imsg[f++];
01270       msgsz += (h->imsg[f++] * 256);
01271       switch (msg) {
01272       case 0x13:                          /* Body */
01273          ast_verb(3, "SMS-P2 Body#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
01274          if (msgsz >= sizeof(h->ud)) {
01275             msgsz = sizeof(h->ud) - 1;
01276          }
01277          for (i = 0; i < msgsz; i++) {
01278             h->ud[i] = h->imsg[f + i];
01279          }
01280          h->udl = msgsz;
01281          break;
01282       case 0x14:                          /* Date SCTS */
01283          now = h->scts = ast_tvnow();
01284          ast_localtime(&now, &tm, NULL);
01285          tm.tm_mon = ( (h->imsg[f] * 10) + h->imsg[f + 1] ) - 1;
01286          tm.tm_mday = ( (h->imsg[f + 2] * 10) + h->imsg[f + 3] );
01287          tm.tm_hour = ( (h->imsg[f + 4] * 10) + h->imsg[f + 5] );
01288          tm.tm_min = ( (h->imsg[f + 6] * 10) + h->imsg[f + 7] );
01289          tm.tm_sec = 0;
01290          h->scts = ast_mktime(&tm, NULL);
01291          ast_verb(3, "SMS-P2 Date#%02X=%02d/%02d %02d:%02d\n", (unsigned)msg, tm.tm_mday, tm.tm_mon + 1, tm.tm_hour, tm.tm_min);
01292          break;
01293       case 0x15:                          /* Calling line (from SMSC) */
01294          if (msgsz >= 20) {
01295             msgsz = 20 - 1;
01296          }
01297          ast_verb(3, "SMS-P2 Origin#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
01298          ast_copy_string(h->oa, (char *)(&h->imsg[f]), msgsz + 1);
01299          break;
01300       case 0x18:                          /* Destination(from TE/phone) */
01301          if (msgsz >= 20) {
01302             msgsz = 20 - 1;
01303          }
01304          ast_verb(3, "SMS-P2 Destination#%02X=[%.*s]\n", (unsigned)msg, msgsz, &h->imsg[f]);
01305          ast_copy_string(h->da, (char *)(&h->imsg[f]), msgsz + 1);
01306          break;
01307       case 0x1C:                          /* Notify */
01308          ast_verb(3, "SMS-P2 Notify#%02X=%s\n", (unsigned)msg, sms_hexdump(&h->imsg[f], 3, debug_buf));
01309          break;
01310       default:
01311          ast_verb(3, "SMS-P2 Par#%02X [%d]: %s\n", (unsigned)msg, msgsz, sms_hexdump(&h->imsg[f], msgsz, debug_buf));
01312          break;
01313       }
01314       f+=msgsz;                           /* Skip to next */
01315    }
01316    h->rx = 1;                              /* received message */
01317    sms_writefile(h);                       /* write the file */
01318    return 0;                               /* no error */
01319 }
01320 
01321 #if 0
01322 static void smssend(sms_t *h, char *c)
01323 {
01324    int f, x;
01325    for (f = 0; f < strlen(c); f++) {
01326       sscanf(&c[f*3], "%x", &x);
01327       h->omsg[f] = x;
01328    }
01329    sms_messagetx(h);
01330 }
01331 #endif
01332 
01333 static void sms_nextoutgoing (sms_t *h);
01334 
01335 static void sms_messagerx2(sms_t * h)
01336 {
01337    int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */
01338    int cause;
01339 
01340 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
01341    switch (p) {
01342    case DLL2_SMS_EST:                      /* Protocol 2: Connection ready (fake): send message  */
01343       sms_nextoutgoing (h);
01344       /* 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 "); */
01345       break;
01346 
01347    case DLL2_SMS_INFO_MO:                  /* transport SMS_SUBMIT */
01348    case DLL2_SMS_INFO_MT:                  /* transport SMS_DELIVERY */
01349       cause = sms_handleincoming_proto2(h);
01350       if (!cause) {                       /* ACK */
01351          sms_log(h, 'Y');
01352       }
01353       h->omsg[0] = DLL2_ACK(h);
01354       h->omsg[1] = 0x06;                  /* msg len */
01355       h->omsg[2] = 0x04;                  /* payload len */
01356       h->omsg[3] = 0x00;                  /* payload len */
01357       h->omsg[4] = 0x1f;                  /* Response type */
01358       h->omsg[5] = 0x01;                  /* parameter len */
01359       h->omsg[6] = 0x00;                  /* parameter len */
01360       h->omsg[7] = cause;                 /* CONFIRM or error */
01361       sms_messagetx(h);
01362       break;
01363 
01364    case DLL2_SMS_NACK:                     /* Protocol 2: SMS_NAK */
01365       h->omsg[0] = DLL2_SMS_REL;          /* SMS_REL */
01366       h->omsg[1] = 0x00;                  /* msg len */
01367       sms_messagetx(h);
01368       break;
01369 
01370    case DLL2_SMS_ACK0:
01371    case DLL2_SMS_ACK1:
01372       /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */
01373       if ( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
01374          /* a response to our Release, just hangup */
01375          h->hangup = 1;                  /* hangup */
01376       } else {
01377          /* XXX depending on what we are.. */
01378          ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY\n");
01379          sms_nextoutgoing (h);
01380       }
01381       break;
01382 
01383    case DLL2_SMS_REL:                      /* Protocol 2: SMS_REL (hangup req) */
01384       h->omsg[0] = DLL2_ACK(h);
01385       h->omsg[1] = 0;
01386       sms_messagetx(h);
01387       break;
01388    }
01389 }
01390 
01391 /*! \brief compose a message for protocol 1 */
01392 static void sms_compose1(sms_t *h, int more)
01393 {
01394    unsigned int p = 2;                     /* next byte to write. Skip type and len */
01395 
01396    h->omsg[0] = 0x91;                      /* SMS_DATA */
01397    if (h->smsc) {                          /* deliver */
01398       h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
01399       p += packaddress(h->omsg + p, h->oa);
01400       h->omsg[p++] = h->pid;
01401       h->omsg[p++] = h->dcs;
01402       packdate(h->omsg + p, h->scts.tv_sec);
01403       p += 7;
01404       p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01405    } else {                                /* submit */
01406       h->omsg[p++] =
01407          0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
01408       if (h->mr < 0) {
01409          h->mr = message_ref++;
01410       }
01411       h->omsg[p++] = h->mr;
01412       p += packaddress(h->omsg + p, h->da);
01413       h->omsg[p++] = h->pid;
01414       h->omsg[p++] = h->dcs;
01415       if (h->vp) {                        /* relative VP */
01416          if (h->vp < 720) {
01417             h->omsg[p++] = (h->vp + 4) / 5 - 1;
01418          } else if (h->vp < 1440) {
01419             h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
01420          } else if (h->vp < 43200) {
01421             h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
01422          } else if (h->vp < 635040) {
01423             h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
01424          } else {
01425             h->omsg[p++] = 255;         /* max */
01426          }
01427       }
01428       p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01429    }
01430    h->omsg[1] = p - 2;
01431 }
01432 
01433 /*! \brief find and fill in next message, or send a REL if none waiting */
01434 static void sms_nextoutgoing (sms_t * h)
01435 {    
01436    char fn[100 + NAME_MAX] = "";
01437    DIR *d;
01438    char more = 0;
01439 
01440    *h->da = *h->oa = '\0';                 /* clear destinations */
01441    h->rx = 0;                              /* outgoing message */
01442    snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? "mttx" : "motx");
01443    ast_mkdir(fn, 0777);                    /* ensure it exists */
01444    d = opendir(fn);
01445    if (d) {
01446       struct dirent *f = readdirqueue(d, h->queue);
01447       if (f) {
01448          snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", f->d_name);
01449          sms_readfile(h, fn);
01450          if (readdirqueue(d, h->queue)) {
01451             more = 1;                   /* more to send */
01452          }
01453       }
01454       closedir(d);
01455    }
01456    if (*h->da || *h->oa) {                 /* message to send */
01457       if (h->protocol == 2) {
01458          sms_compose2(h, more);
01459       } else {
01460          sms_compose1(h, more);
01461       }
01462    } else {                                /* no message */
01463       if (h->protocol == 2) {
01464          h->omsg[0] = 0x17;              /* SMS_REL */
01465          h->omsg[1] = 0;
01466       } else {
01467          h->omsg[0] = 0x94;              /* SMS_REL */
01468          h->omsg[1] = 0;
01469          h->sent_rel = 1;
01470       }
01471    }
01472    sms_messagetx(h);
01473 }
01474 
01475 #define DIR_RX 1
01476 #define DIR_TX 2
01477 static void sms_debug (int dir, sms_t *h)
01478 {
01479    char txt[259 * 3 + 1];
01480    char *p = txt;                          /* always long enough */
01481    unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
01482    int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
01483    int q = 0;
01484    while (q < n && q < 30) {
01485       sprintf(p, " %02X", (unsigned)msg[q++]);
01486       p += 3;
01487    }
01488    if (q < n) {
01489       sprintf(p, "...");
01490    }
01491    ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
01492 }
01493 
01494 
01495 static void sms_messagerx(sms_t * h)
01496 {
01497    int cause;
01498 
01499    sms_debug (DIR_RX, h);
01500    if (h->protocol == 2) {
01501       sms_messagerx2(h);
01502       return;
01503    }
01504    /* parse incoming message for Protocol 1 */
01505    switch (h->imsg[0]) {
01506    case 0x91:                              /* SMS_DATA */
01507       cause = sms_handleincoming (h);
01508       if (!cause) {
01509          sms_log(h, 'Y');
01510          h->omsg[0] = 0x95;              /* SMS_ACK */
01511          h->omsg[1] = 0x02;
01512          h->omsg[2] = 0x00;              /* deliver report */
01513          h->omsg[3] = 0x00;              /* no parameters */
01514       } else {                            /* NACK */
01515          sms_log(h, 'N');
01516          h->omsg[0] = 0x96;              /* SMS_NACK */
01517          h->omsg[1] = 3;
01518          h->omsg[2] = 0;                 /* delivery report */
01519          h->omsg[3] = cause;             /* cause */
01520          h->omsg[4] = 0;                 /* no parameters */
01521       }
01522       sms_messagetx(h);
01523       break;
01524 
01525    case 0x92:                              /* SMS_ERROR */
01526       h->err = 1;
01527       sms_messagetx(h);                   /* send whatever we sent again */
01528       break;
01529    case 0x93:                              /* SMS_EST */
01530       sms_nextoutgoing (h);
01531       break;
01532    case 0x94:                              /* SMS_REL */
01533       h->hangup = 1;                      /* hangup */
01534       break;
01535    case 0x95:                              /* SMS_ACK */
01536       sms_log(h, 'Y');
01537       sms_nextoutgoing (h);
01538       break;
01539    case 0x96:                              /* SMS_NACK */
01540       h->err = 1;
01541       sms_log(h, 'N');
01542       sms_nextoutgoing (h);
01543       break;
01544    default:                                /* Unknown */
01545       h->omsg[0] = 0x92;                  /* SMS_ERROR */
01546       h->omsg[1] = 1;
01547       h->omsg[2] = 3;                     /* unknown message type */
01548       sms_messagetx(h);
01549       break;
01550    }
01551 }
01552 
01553 static void sms_messagetx(sms_t * h)
01554 {
01555    unsigned char c = 0, p;
01556    int len = h->omsg[1] + 2;               /* total message length excluding checksum */
01557 
01558    for (p = 0; p < len; p++) {             /* compute checksum */
01559       c += h->omsg[p];
01560    }
01561    h->omsg[len] = 0 - c;                   /* actually, (256 - (c & 0fxx)) & 0xff) */
01562    sms_debug(DIR_TX, h);
01563    h->framenumber++;                       /* Proto 2 */
01564    h->obytep = 0;
01565    h->obitp = 0;
01566    if (h->protocol == 2) {                 /* Proto 2: */
01567       h->oseizure = 300;                  /* 300bits (or more ?) */
01568       h->obyte = 0;                       /* Seizure starts with  space (0) */
01569       if (h->omsg[0] == 0x7F) {
01570          h->opause = 8 * h->opause_0;    /* initial message delay */
01571       } else {
01572          h->opause = 400;
01573       }
01574    } else {                                /* Proto 1: */
01575       h->oseizure = 0;                    /* No seizure */
01576       h->obyte = 1;                       /* send mark ('1') at the beginning */
01577       /* Change the initial message delay. BT requires 300ms,
01578        * but for others this might be way too much and the phone
01579        * could time out. XXX make it configurable.
01580       */
01581       if (h->omsg[0] == 0x93) {
01582          h->opause = 8 * h->opause_0;    /* initial message delay */
01583       } else {
01584          h->opause = 200;
01585       }
01586    }
01587    /* Note - setting osync triggers the generator */
01588    h->osync = OSYNC_BITS;                  /* 80 sync bits */
01589    h->obyten = len + 1;                    /* bytes to send (including checksum) */
01590 }
01591 
01592 /*!
01593  * outgoing data are produced by this generator function, that reads from
01594  * the descriptor whether it has data to send and which ones.
01595  */
01596 static int sms_generate(struct ast_channel *chan, void *data, int len, int samples)
01597 {
01598    struct ast_frame f = { 0 };
01599 #define MAXSAMPLES (800)
01600    output_t *buf;
01601    sms_t *h = data;
01602    int i;
01603 
01604    if (samples > MAXSAMPLES) {
01605       ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
01606           MAXSAMPLES, samples);
01607       samples = MAXSAMPLES;
01608    }
01609    len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET;
01610    buf = ast_alloca(len);
01611 
01612    f.frametype = AST_FRAME_VOICE;
01613    f.subclass.codec = __OUT_FMT;
01614    f.datalen = samples * sizeof(*buf);
01615    f.offset = AST_FRIENDLY_OFFSET;
01616    f.mallocd = 0;
01617    f.data.ptr = buf;
01618    f.samples = samples;
01619    f.src = "app_sms";
01620    /* create a buffer containing the digital sms pattern */
01621    for (i = 0; i < samples; i++) {
01622       buf[i] = wave_out[0];               /* default is silence */
01623 
01624       if (h->opause) {
01625          h->opause--;
01626       } else if (h->obyten || h->osync) { /* sending data */
01627          buf[i] = wave_out[h->ophase];
01628          h->ophase += (h->obyte & 1) ? 13 : 21; /* compute next phase */
01629          if (h->ophase >= 80)
01630             h->ophase -= 80;
01631          if ((h->ophasep += 12) >= 80) { /* time to send the next bit */
01632             h->ophasep -= 80;
01633             if (h->oseizure > 0) {      /* sending channel seizure (proto 2) */
01634                h->oseizure--;
01635                h->obyte ^= 1;          /* toggle low bit */
01636             } else if (h->osync) {
01637                h->obyte = 1;           /* send mark as sync bit */
01638                h->osync--;             /* sending sync bits */
01639                if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
01640                   h->obytep = h->obyten = 0; /* we are done */
01641                }
01642             } else {
01643                h->obitp++;
01644                if (h->obitp == 1) {
01645                   h->obyte = 0;       /* start bit; */
01646                } else if (h->obitp == 2) {
01647                   h->obyte = h->omsg[h->obytep];
01648                } else if (h->obitp == 10) {
01649                   h->obyte = 1; /* stop bit */
01650                   h->obitp = 0;
01651                   h->obytep++;
01652                   if (h->obytep == h->obyten) {
01653                      h->obytep = h->obyten = 0; /* sent */
01654                      h->osync = 10;   /* trailing marks */
01655                   }
01656                } else {
01657                   h->obyte >>= 1;
01658                }
01659             }
01660          }
01661       }
01662    }
01663    if (ast_write(chan, &f) < 0) {
01664       ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
01665       return -1;
01666    }
01667    return 0;
01668 #undef MAXSAMPLES
01669 }
01670 
01671 /*!
01672  * Just return the pointer to the descriptor that we received.
01673  */
01674 static void *sms_alloc(struct ast_channel *chan, void *sms_t_ptr)
01675 {
01676    return sms_t_ptr;
01677 }
01678 
01679 static void sms_release(struct ast_channel *chan, void *data)
01680 {
01681    return;  /* nothing to do here. */
01682 }
01683 
01684 static struct ast_generator smsgen = {
01685    .alloc = sms_alloc,
01686    .release = sms_release,
01687    .generate = sms_generate,
01688 };
01689 
01690 /*!
01691  * Process an incoming frame, trying to detect the carrier and
01692  * decode the message. The two frequencies are 1300 and 2100 Hz.
01693  * The decoder detects the amplitude of the signal over the last
01694  * few samples, filtering the absolute values with a lowpass filter.
01695  * If the magnitude (h->imag) is large enough, multiply the signal
01696  * by the two carriers, and compute the amplitudes m0 and m1.
01697  * Record the current sample as '0' or '1' depending on which one is greater.
01698  * The last 3 bits are stored in h->ibith, with the count of '1'
01699  * bits in h->ibitt.
01700  * XXX the rest is to be determined.
01701  */
01702 static void sms_process(sms_t * h, int samples, signed short *data)
01703 {
01704    int bit;
01705 
01706    /*
01707     * Ignore incoming audio while a packet is being transmitted,
01708     * the protocol is half-duplex.
01709     * Unfortunately this means that if the outbound and incoming
01710     * transmission overlap (which is an error condition anyways),
01711     * we may miss some data and this makes debugging harder.
01712     */
01713    if (h->obyten || h->osync) {
01714       return;
01715    }
01716    for ( ; samples-- ; data++) {
01717       unsigned long long m0, m1;
01718       if (abs(*data) > h->imag) {
01719          h->imag = abs(*data);
01720       } else {
01721          h->imag = h->imag * 7 / 8;
01722       }
01723       if (h->imag <= 500) {               /* below [arbitrary] threahold: lost carrier */
01724          if (h->idle++ == 80000) {       /* nothing happening */
01725             ast_log(LOG_NOTICE, "No data, hanging up\n");
01726             h->hangup = 1;
01727             h->err = 1;
01728          }
01729          if (h->ierr) {                  /* error */
01730             ast_log(LOG_NOTICE, "Error %d, hanging up\n", h->ierr);
01731             /* Protocol 1 */
01732             h->err = 1;
01733             h->omsg[0] = 0x92;          /* error */
01734             h->omsg[1] = 1;
01735             h->omsg[2] = h->ierr;
01736             sms_messagetx(h);           /* send error */
01737          }
01738          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01739          continue;
01740       }
01741       h->idle = 0;
01742 
01743       /* multiply signal by the two carriers. */
01744       h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
01745       h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
01746       h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
01747       h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
01748       /* compute the amplitudes */
01749       m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
01750       m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
01751 
01752       /* advance the sin/cos pointers */
01753       if ((h->ips0 += 21) >= 80) {
01754          h->ips0 -= 80;
01755       }
01756       if ((h->ipc0 += 21) >= 80) {
01757          h->ipc0 -= 80;
01758       }
01759       if ((h->ips1 += 13) >= 80) {
01760          h->ips1 -= 80;
01761       }
01762       if ((h->ipc1 += 13) >= 80) {
01763          h->ipc1 -= 80;
01764       }
01765 
01766       /* set new bit to 1 or 0 depending on which value is stronger */
01767       h->ibith <<= 1;
01768       if (m1 > m0) {
01769          h->ibith |= 1;
01770       }
01771       if (h->ibith & 8) {
01772          h->ibitt--;
01773       }
01774       if (h->ibith & 1) {
01775          h->ibitt++;
01776       }
01777       bit = ((h->ibitt > 1) ? 1 : 0);
01778       if (bit != h->ibitl) {
01779          h->ibitc = 1;
01780       } else {
01781          h->ibitc++;
01782       }
01783       h->ibitl = bit;
01784       if (!h->ibitn && h->ibitc == 4 && !bit) {
01785          h->ibitn = 1;
01786          h->iphasep = 0;
01787       }
01788       if (bit && h->ibitc == 200) {       /* sync, restart message */
01789          /* Protocol 2: empty connection ready (I am master) */
01790          if (h->framenumber < 0 && h->ibytec >= 160 && !memcmp(h->imsg, "UUUUUUUUUUUUUUUUUUUU", 20)) {
01791             h->framenumber = 1;
01792             ast_verb(3, "SMS protocol 2 detected\n");
01793             h->protocol = 2;
01794             h->imsg[0] = 0xff;          /* special message (fake) */
01795             h->imsg[1] = h->imsg[2] = 0x00;
01796             h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01797             sms_messagerx(h);
01798          }
01799          h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01800       }
01801       if (h->ibitn) {
01802          h->iphasep += 12;
01803          if (h->iphasep >= 80) {         /* next bit */
01804             h->iphasep -= 80;
01805             if (h->ibitn++ == 9) {      /* end of byte */
01806                if (!bit) {             /* bad stop bit */
01807                   if (h->sent_rel) {
01808                      h->hangup = 1;
01809                   } else {
01810                      ast_log(LOG_NOTICE, "Bad stop bit\n");
01811                      h->ierr = 0xFF;     /* unknown error */
01812                   }
01813                } else {
01814                   if (h->ibytep < sizeof(h->imsg)) {
01815                      h->imsg[h->ibytep] = h->ibytev;
01816                      h->ibytec += h->ibytev;
01817                      h->ibytep++;
01818                   } else if (h->ibytep == sizeof(h->imsg)) {
01819                      ast_log(LOG_NOTICE, "msg too large\n");
01820                      h->ierr = 2;    /* bad message length */
01821                   }
01822                   if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
01823                      if (!h->ibytec) {
01824                         sms_messagerx(h);
01825                      } else {
01826                         ast_log(LOG_NOTICE, "bad checksum\n");
01827                         h->ierr = 1; /* bad checksum */
01828                      }
01829                   }
01830                }
01831                h->ibitn = 0;
01832             }
01833             h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
01834          }
01835       }
01836    }
01837 }
01838 
01839 /*
01840  * Standard argument parsing:
01841  * - one enum for the flags we recognise,
01842  * - one enum for argument indexes
01843  * - AST_APP_OPTIONS() to drive the parsing routine
01844  * - in the function, AST_DECLARE_APP_ARGS(...) for the arguments.
01845  */
01846 enum sms_flags {
01847    OPTION_BE_SMSC = (1 << 0),             /* act as sms center */
01848    OPTION_ANSWER  = (1 << 1),             /* answer on incoming calls */
01849    OPTION_TWO  = (1 << 2),                 /* Use Protocol Two */
01850    OPTION_PAUSE   = (1 << 3),             /* pause before sending data, in ms */
01851    OPTION_SRR  = (1 << 4),                 /* set srr */
01852    OPTION_DCS  = (1 << 5),                 /* set dcs */
01853 };
01854 
01855 enum sms_opt_args {
01856    OPTION_ARG_PAUSE = 0,
01857    OPTION_ARG_ARRAY_SIZE
01858 };
01859 
01860 AST_APP_OPTIONS(sms_options, {
01861    AST_APP_OPTION('s', OPTION_BE_SMSC),
01862    AST_APP_OPTION('a', OPTION_ANSWER),
01863    AST_APP_OPTION('t', OPTION_TWO),
01864    AST_APP_OPTION('r', OPTION_SRR),
01865    AST_APP_OPTION('o', OPTION_DCS),
01866    AST_APP_OPTION_ARG('p', OPTION_PAUSE, OPTION_ARG_PAUSE),
01867    } );
01868 
01869 static int sms_exec(struct ast_channel *chan, const char *data)
01870 {
01871    int res = -1;
01872    sms_t h = { 0 };
01873    /* argument parsing support */
01874    struct ast_flags flags = { 0 };
01875    char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, };
01876    char *p;
01877    AST_DECLARE_APP_ARGS(sms_args,
01878       AST_APP_ARG(queue);
01879       AST_APP_ARG(options);
01880       AST_APP_ARG(addr);
01881       AST_APP_ARG(body);
01882    );
01883 
01884    if (!data) {
01885       ast_log(LOG_ERROR, "Requires queue name at least\n");
01886       return -1;
01887    }
01888 
01889    parse = ast_strdupa(data);              /* create a local copy */
01890    AST_STANDARD_APP_ARGS(sms_args, parse);
01891    if (sms_args.argc > 1) {
01892       ast_app_parse_options(sms_options, &flags, sms_opts, sms_args.options);
01893    }
01894 
01895    ast_verb(1, "sms argc %u queue <%s> opts <%s> addr <%s> body <%s>\n",
01896       sms_args.argc, S_OR(sms_args.queue, ""),
01897       S_OR(sms_args.options, ""),
01898       S_OR(sms_args.addr, ""),
01899       S_OR(sms_args.body, "") );
01900 
01901    h.ipc0 = h.ipc1 = 20;                   /* phase for cosine */
01902    h.dcs = 0xF1;                           /* default */
01903 
01904    ast_copy_string(h.cli,
01905       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
01906       sizeof(h.cli));
01907 
01908    if (ast_strlen_zero(sms_args.queue)) {
01909       ast_log(LOG_ERROR, "Requires queue name\n");
01910       goto done;
01911    }
01912    if (strlen(sms_args.queue) >= sizeof(h.queue)) {
01913       ast_log(LOG_ERROR, "Queue name too long\n");
01914       goto done;
01915    }
01916    ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue));
01917 
01918    for (p = h.queue; *p; p++) {
01919       if (!isalnum(*p)) {
01920          *p = '-';                       /* make very safe for filenames */
01921       }
01922    }
01923 
01924    h.smsc = ast_test_flag(&flags, OPTION_BE_SMSC);
01925    h.protocol = ast_test_flag(&flags, OPTION_TWO) ? 2 : 1;
01926    if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE])) {
01927       h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
01928    }
01929    if (h.opause_0 < 25 || h.opause_0 > 2000) {
01930       h.opause_0 = 300;                   /* default 300ms */
01931    }
01932    ast_verb(1, "initial delay %dms\n", h.opause_0);
01933 
01934 
01935    /* the following apply if there is an arg3/4 and apply to the created message file */
01936    if (ast_test_flag(&flags, OPTION_SRR)) {
01937       h.srr = 1;
01938    }
01939    if (ast_test_flag(&flags, OPTION_DCS)) {
01940       h.dcs = 1;
01941    }
01942 #if 0 
01943       case '1':
01944       case '2':
01945       case '3':
01946       case '4':
01947       case '5':
01948       case '6':
01949       case '7':                           /* set the pid for saved local message */
01950          h.pid = 0x40 + (*d & 0xF);
01951          break;
01952       }
01953 #endif
01954    if (sms_args.argc > 2) {
01955       unsigned char *up;
01956 
01957       /* submitting a message, not taking call. */
01958       /* deprecated, use smsq instead */
01959       h.scts = ast_tvnow();
01960       if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) {
01961          ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr);
01962          goto done;
01963       }
01964       if (h.smsc) {
01965          ast_copy_string(h.oa, sms_args.addr, sizeof(h.oa));
01966       } else {
01967          ast_copy_string(h.da, sms_args.addr, sizeof(h.da));
01968          ast_copy_string(h.oa, h.cli, sizeof(h.oa));
01969       }
01970       h.udl = 0;
01971       if (ast_strlen_zero(sms_args.body)) {
01972          ast_log(LOG_ERROR, "Missing body for %s\n", sms_args.addr);
01973          goto done;
01974       }
01975       up = (unsigned char *)sms_args.body;
01976       while (*up && h.udl < SMSLEN) {
01977          h.ud[h.udl++] = utf8decode(&up);
01978       }
01979       if (is7bit(h.dcs) && packsms7(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01980          ast_log(LOG_WARNING, "Invalid 7 bit GSM data\n");
01981          goto done;
01982       }
01983       if (is8bit(h.dcs) && packsms8(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01984          ast_log(LOG_WARNING, "Invalid 8 bit data\n");
01985          goto done;
01986       }
01987       if (is16bit(h.dcs) && packsms16(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01988          ast_log(LOG_WARNING, "Invalid 16 bit data\n");
01989          goto done;
01990       }
01991       h.rx = 0;                           /* sent message */
01992       h.mr = -1;
01993       sms_writefile(&h);
01994       res = h.err;
01995       goto done;
01996    }
01997    
01998    if (chan->_state != AST_STATE_UP) {    /* make sure channel is answered before any TX */
01999       ast_answer(chan);
02000    }
02001 
02002    if (ast_test_flag(&flags, OPTION_ANSWER)) {
02003       h.framenumber = 1;                  /* Proto 2 */
02004       /* set up SMS_EST initial message */
02005       if (h.protocol == 2) {
02006          h.omsg[0] = DLL2_SMS_EST;
02007          h.omsg[1] = 0;
02008       } else {
02009          h.omsg[0] = DLL1_SMS_EST | DLL1_SMS_COMPLETE;
02010          h.omsg[1] = 0;
02011       }
02012       sms_messagetx(&h);
02013    }
02014 
02015    res = ast_set_write_format(chan, __OUT_FMT);
02016    if (res >= 0) {
02017       res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
02018    }
02019    if (res < 0) {
02020       ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
02021       goto done;
02022    }
02023 
02024    if ( (res = ast_activate_generator(chan, &smsgen, &h)) < 0) {
02025       ast_log(LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
02026       goto done;
02027    }
02028 
02029    /* Do our thing here */
02030    for (;;) {
02031       struct ast_frame *f;
02032       int i = ast_waitfor(chan, -1);
02033       if (i < 0) {
02034          ast_log(LOG_NOTICE, "waitfor failed\n");
02035          break;
02036       }
02037       if (h.hangup) {
02038          ast_log(LOG_NOTICE, "channel hangup\n");
02039          break;
02040       }
02041       f = ast_read(chan);
02042       if (!f) {
02043          ast_log(LOG_NOTICE, "ast_read failed\n");
02044          break;
02045       }
02046       if (f->frametype == AST_FRAME_VOICE) {
02047          sms_process(&h, f->samples, f->data.ptr);
02048       }
02049 
02050       ast_frfree(f);
02051    }
02052    res = h.err;                            /* XXX */
02053 
02054    /* 
02055     * The SMS generator data is on the stack.  We _MUST_ make sure the generator
02056     * is stopped before returning from this function.
02057     */
02058    ast_deactivate_generator(chan);
02059 
02060    sms_log(&h, '?');                       /* log incomplete message */
02061 done:
02062    return (res);
02063 }
02064 
02065 static int unload_module(void)
02066 {
02067    return ast_unregister_application(app);
02068 }
02069 
02070 static int load_module(void)
02071 {
02072 #ifdef OUTALAW
02073    int p;
02074    for (p = 0; p < 80; p++) {
02075       wavea[p] = AST_LIN2A(wave[p]);
02076    }
02077 #endif
02078    snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR);
02079    return ast_register_application_xml(app, sms_exec);
02080 }
02081 
02082 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SMS/PSTN handler");

Generated on 17 Aug 2018 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1