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

Generated on Thu Apr 16 06:27:12 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6