00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "asterisk.h"
00038
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 153743 $")
00040
00041 #include <dirent.h>
00042 #include <ctype.h>
00043 #include <sys/stat.h>
00044
00045 #include "asterisk/paths.h"
00046 #include "asterisk/lock.h"
00047 #include "asterisk/file.h"
00048 #include "asterisk/channel.h"
00049 #include "asterisk/pbx.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/alaw.h"
00052 #include "asterisk/callerid.h"
00053 #include "asterisk/utils.h"
00054 #include "asterisk/app.h"
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 static volatile unsigned char message_ref;
00065 static volatile unsigned int seq;
00066
00067 static char log_file[255];
00068
00069 static char *app = "SMS";
00070
00071 static char *synopsis = "Communicates with SMS service centres and SMS capable analogue phones";
00072
00073 static char *descrip =
00074 " SMS(name,[a][s][t][p(d)][r][o],addr,body):\n"
00075 "SMS handles exchange of SMS data with a call to/from SMS capable\n"
00076 "phone or SMS PSTN service center. Can send and/or receive SMS messages.\n"
00077 "Works to ETSI ES 201 912; compatible with BT SMS PSTN service in UK\n"
00078 "and Telecom Italia in Italy.\n"
00079 "Typical usage is to use to handle calls from the SMS service centre CLI,\n"
00080 "or to set up a call using 'outgoing' or manager interface to connect\n"
00081 "service centre to SMS()\n"
00082 "name is the name of the queue used in /var/spool/asterisk/sms\n"
00083 "Arguments:\n"
00084 " a - answer, i.e. send initial FSK packet.\n"
00085 " s - act as service centre talking to a phone.\n"
00086 " t - use protocol 2 (default used is protocol 1).\n"
00087 " p(N) - set the initial delay to N ms (default is 300).\n"
00088 " addr and body are a deprecated format to send messages out.\n"
00089 " s - set the Status Report Request (SRR) bit.\n"
00090 " o - the body should be coded as octets not 7-bit symbols.\n"
00091 "Messages are processed as per text file message queues.\n"
00092 "smsq (a separate software) is a command to generate message\n"
00093 "queues and send messages.\n"
00094 "NOTE: the protocol has tight delay bounds. Please use short frames\n"
00095 "and disable/keep short the jitter buffer on the ATA to make sure that\n"
00096 "respones (ACK etc.) are received in time.\n";
00097
00098
00099
00100
00101
00102
00103
00104 static signed short wave[] = {
00105 0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
00106 5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
00107 0, -392, -782, -1167,
00108 -1545, -1913, -2270, -2612, -2939, -3247, -3536, -3802, -4045, -4263, -4455, -4619, -4755, -4862, -4938, -4985, -5000,
00109 -4985, -4938, -4862,
00110 -4755, -4619, -4455, -4263, -4045, -3802, -3536, -3247, -2939, -2612, -2270, -1913, -1545, -1167, -782, -392
00111 };
00112
00113 #ifdef OUTALAW
00114 static unsigned char wavea[80];
00115 typedef unsigned char output_t;
00116 static const output_t *wave_out = wavea;
00117 #define __OUT_FMT AST_FORMAT_ALAW;
00118 #else
00119 typedef signed short output_t;
00120 static const output_t *wave_out = wave;
00121 #define __OUT_FMT AST_FORMAT_SLINEAR
00122 #endif
00123
00124 #define OSYNC_BITS 80
00125
00126
00127
00128
00129
00130
00131
00132
00133 enum message_types {
00134 DLL_SMS_MASK = 0x7f,
00135
00136
00137 DLL1_SMS_DATA = 0x11,
00138 DLL1_SMS_ERROR = 0x12,
00139 DLL1_SMS_EST = 0x13,
00140 DLL1_SMS_REL = 0x14,
00141 DLL1_SMS_ACK = 0x15,
00142 DLL1_SMS_NACK = 0x16,
00143
00144 DLL1_SMS_COMPLETE = 0x80,
00145 DLL1_SMS_MORE = 0x00,
00146
00147
00148 DLL2_SMS_EST = 0x7f,
00149 DLL2_SMS_INFO_MO = 0x10,
00150 DLL2_SMS_INFO_MT = 0x11,
00151 DLL2_SMS_INFO_STA = 0x12,
00152 DLL2_SMS_NACK = 0x13,
00153 DLL2_SMS_ACK0 = 0x14,
00154 DLL2_SMS_ACK1 = 0x15,
00155 DLL2_SMS_ENQ = 0x16,
00156 DLL2_SMS_REL = 0x17,
00157
00158 DLL2_SMS_COMPLETE = 0x00,
00159 DLL2_SMS_MORE = 0x80,
00160 };
00161
00162
00163 static const unsigned short defaultalphabet[] = {
00164 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
00165 0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
00166 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
00167 0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
00168 ' ', '!', '"', '#', 164, '%', '&', 39, '(', ')', '*', '+', ',', '-', '.', '/',
00169 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
00170 161, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
00171 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 196, 214, 209, 220, 167,
00172 191, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
00173 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 228, 246, 241, 252, 224,
00174 };
00175
00176 static const unsigned short escapes[] = {
00177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x000C, 0, 0, 0, 0, 0,
00178 0, 0, 0, 0, 0x005E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00179 0, 0, 0, 0, 0, 0, 0, 0, 0x007B, 0x007D, 0, 0, 0, 0, 0, 0x005C,
00180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x005B, 0x007E, 0x005D, 0,
00181 0x007C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00183 0, 0, 0, 0, 0, 0x20AC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00184 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00185 };
00186
00187 #define SMSLEN 160
00188 #define SMSLEN_8 140
00189
00190 typedef struct sms_s {
00191 unsigned char hangup;
00192 unsigned char err;
00193 unsigned char smsc:1;
00194 unsigned char rx:1;
00195 char queue[30];
00196 char oa[20];
00197 char da[20];
00198 struct timeval scts;
00199 unsigned char pid;
00200 unsigned char dcs;
00201 short mr;
00202 int udl;
00203 int udhl;
00204 unsigned char srr:1;
00205 unsigned char udhi:1;
00206 unsigned char rp:1;
00207 unsigned int vp;
00208 unsigned short ud[SMSLEN];
00209 unsigned char udh[SMSLEN];
00210 char cli[20];
00211 unsigned char ophase;
00212 unsigned char ophasep;
00213 unsigned char obyte;
00214 unsigned int opause;
00215 unsigned char obitp;
00216 unsigned char osync;
00217 unsigned char obytep;
00218 unsigned char obyten;
00219 unsigned char omsg[256];
00220 unsigned char imsg[250];
00221 signed long long ims0,
00222 imc0,
00223 ims1,
00224 imc1;
00225 unsigned int idle;
00226 unsigned short imag;
00227 unsigned char ips0;
00228 unsigned char ips1;
00229 unsigned char ipc0;
00230 unsigned char ipc1;
00231 unsigned char ibitl;
00232 unsigned char ibitc;
00233 unsigned char iphasep;
00234 unsigned char ibitn;
00235 unsigned char ibytev;
00236 unsigned char ibytep;
00237 unsigned char ibytec;
00238 unsigned char ierr;
00239 unsigned char ibith;
00240 unsigned char ibitt;
00241
00242
00243 int opause_0;
00244 int protocol;
00245 int oseizure;
00246 int framenumber;
00247 char udtxt[SMSLEN];
00248 } sms_t;
00249
00250
00251 #define is7bit(dcs) ( ((dcs) & 0xC0) ? (!((dcs)&4) ) : (((dcs) & 0xc) == 0) )
00252 #define is8bit(dcs) ( ((dcs) & 0xC0) ? ( ((dcs)&4) ) : (((dcs) & 0xc) == 4) )
00253 #define is16bit(dcs) ( ((dcs) & 0xC0) ? 0 : (((dcs) & 0xc) == 8) )
00254
00255 static void sms_messagetx(sms_t *h);
00256
00257
00258 static void numcpy(char *d, char *s)
00259 {
00260 if (*s == '+')
00261 *d++ = *s++;
00262 while (*s) {
00263 if (isdigit(*s))
00264 *d++ = *s;
00265 s++;
00266 }
00267 *d = 0;
00268 }
00269
00270
00271 static char *isodate(time_t t, char *buf, int len)
00272 {
00273 struct ast_tm tm;
00274 struct timeval tv = { t, 0 };
00275 ast_localtime(&tv, &tm, NULL);
00276 ast_strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
00277 return buf;
00278 }
00279
00280
00281
00282
00283 static long utf8decode(unsigned char **pp)
00284 {
00285 unsigned char *p = *pp;
00286 if (!*p)
00287 return 0;
00288 (*pp)++;
00289 if (*p < 0xC0)
00290 return *p;
00291 if (*p < 0xE0) {
00292 if (*p < 0xC2 || (p[1] & 0xC0) != 0x80)
00293 return *p;
00294 (*pp)++;
00295 return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
00296 }
00297 if (*p < 0xF0) {
00298 if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80)
00299 return *p;
00300 (*pp) += 2;
00301 return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
00302 }
00303 if (*p < 0xF8) {
00304 if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80)
00305 return *p;
00306 (*pp) += 3;
00307 return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
00308 }
00309 if (*p < 0xFC) {
00310 if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00311 || (p[4] & 0xC0) != 0x80)
00312 return *p;
00313 (*pp) += 4;
00314 return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
00315 }
00316 if (*p < 0xFE) {
00317 if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00318 || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80)
00319 return *p;
00320 (*pp) += 5;
00321 return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
00322 }
00323 return *p;
00324 }
00325
00326
00327
00328
00329
00330 static int packsms7(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00331 {
00332 unsigned char p = 0;
00333 unsigned char b = 0;
00334 unsigned char n = 0;
00335 unsigned char dummy[SMSLEN];
00336
00337 if (o == NULL)
00338 o = dummy;
00339
00340 if (udhl) {
00341 o[p++] = udhl;
00342 b = 1;
00343 n = 1;
00344 while (udhl--) {
00345 o[p++] = *udh++;
00346 b += 8;
00347 while (b >= 7) {
00348 b -= 7;
00349 n++;
00350 }
00351 if (n >= SMSLEN)
00352 return n;
00353 }
00354 if (b) {
00355 b = 7 - b;
00356 if (++n >= SMSLEN)
00357 return n;
00358 };
00359 }
00360 o[p] = 0;
00361
00362 while (udl--) {
00363 long u;
00364 unsigned char v;
00365 u = *ud++;
00366
00367
00368 for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
00369 if (v == 128 && u && n + 1 < SMSLEN) {
00370
00371 for (v = 0; v < 128 && escapes[v] != u; v++);
00372 if (v < 128) {
00373
00374 o[p] |= (27 << b);
00375 b += 7;
00376 if (b >= 8) {
00377 b -= 8;
00378 p++;
00379 o[p] = (27 >> (7 - b));
00380 }
00381 n++;
00382 }
00383 }
00384 if (v == 128)
00385 return -1;
00386
00387 o[p] |= (v << b);
00388 b += 7;
00389 if (b >= 8) {
00390 b -= 8;
00391 p++;
00392 o[p] = (v >> (7 - b));
00393 }
00394 if (++n >= SMSLEN)
00395 return n;
00396 }
00397 return n;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406 static int packsms8(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00407 {
00408 unsigned char p = 0;
00409 unsigned char dummy[SMSLEN_8];
00410
00411 if (o == NULL)
00412 o = dummy;
00413
00414 if (udhl) {
00415 o[p++] = udhl;
00416 while (udhl--) {
00417 o[p++] = *udh++;
00418 if (p >= SMSLEN_8)
00419 return p;
00420 }
00421 }
00422 while (udl--) {
00423 long u;
00424 u = *ud++;
00425 if (u < 0 || u > 0xFF)
00426 return -1;
00427 o[p++] = u;
00428 if (p >= SMSLEN_8)
00429 return p;
00430 }
00431 return p;
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 static int packsms16(unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00443 {
00444 unsigned char p = 0;
00445 unsigned char dummy[SMSLEN_8];
00446
00447 if (o == NULL)
00448 o = dummy;
00449
00450 if (udhl) {
00451 o[p++] = udhl;
00452 while (udhl--) {
00453 o[p++] = *udh++;
00454 if (p >= SMSLEN_8)
00455 return p;
00456 }
00457 }
00458 while (udl--) {
00459 long u;
00460 u = *ud++;
00461 o[p++] = (u >> 8);
00462 if (p >= SMSLEN_8)
00463 return p - 1;
00464 o[p++] = u;
00465 if (p >= SMSLEN_8)
00466 return p;
00467 }
00468 return p;
00469 }
00470
00471
00472
00473 static int packsms(unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
00474 {
00475 unsigned char *p = base;
00476 if (udl == 0)
00477 *p++ = 0;
00478 else {
00479
00480 int l = 0;
00481 if (is7bit(dcs)) {
00482 l = packsms7(p + 1, udhl, udh, udl, ud);
00483 if (l < 0)
00484 l = 0;
00485 *p++ = l;
00486 p += (l * 7 + 7) / 8;
00487 } else if (is8bit(dcs)) {
00488 l = packsms8(p + 1, udhl, udh, udl, ud);
00489 if (l < 0)
00490 l = 0;
00491 *p++ = l;
00492 p += l;
00493 } else {
00494 l = packsms16(p + 1, udhl, udh, udl, ud);
00495 if (l < 0)
00496 l = 0;
00497 *p++ = l;
00498 p += l;
00499 }
00500 }
00501 return p - base;
00502 }
00503
00504
00505
00506 static void packdate(unsigned char *o, time_t w)
00507 {
00508 struct ast_tm t;
00509 struct timeval tv = { w, 0 };
00510 int z;
00511
00512 ast_localtime(&tv, &t, NULL);
00513 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
00514 z = -t.tm_gmtoff / 60 / 15;
00515 #else
00516 z = timezone / 60 / 15;
00517 #endif
00518 *o++ = ((t.tm_year % 10) << 4) + (t.tm_year % 100) / 10;
00519 *o++ = (((t.tm_mon + 1) % 10) << 4) + (t.tm_mon + 1) / 10;
00520 *o++ = ((t.tm_mday % 10) << 4) + t.tm_mday / 10;
00521 *o++ = ((t.tm_hour % 10) << 4) + t.tm_hour / 10;
00522 *o++ = ((t.tm_min % 10) << 4) + t.tm_min / 10;
00523 *o++ = ((t.tm_sec % 10) << 4) + t.tm_sec / 10;
00524 if (z < 0)
00525 *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
00526 else
00527 *o++ = ((z % 10) << 4) + z / 10;
00528 }
00529
00530
00531 static struct timeval unpackdate(unsigned char *i)
00532 {
00533 struct ast_tm t;
00534
00535 t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
00536 t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
00537 t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
00538 t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
00539 t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
00540 t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
00541 t.tm_isdst = 0;
00542 if (i[6] & 0x08)
00543 t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00544 else
00545 t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00546
00547 return ast_mktime(&t, NULL);
00548 }
00549
00550
00551
00552
00553 static void unpacksms7(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00554 {
00555 unsigned char b = 0, p = 0;
00556 unsigned short *o = ud;
00557 *udhl = 0;
00558 if (udhi && l) {
00559 int h = i[p];
00560 *udhl = h;
00561 if (h) {
00562 b = 1;
00563 p++;
00564 l--;
00565 while (h-- && l) {
00566 *udh++ = i[p++];
00567 b += 8;
00568 while (b >= 7) {
00569 b -= 7;
00570 l--;
00571 if (!l)
00572 break;
00573 }
00574 }
00575
00576 if (b) {
00577 b = 7 - b;
00578 l--;
00579 }
00580 }
00581 }
00582 while (l--) {
00583 unsigned char v;
00584 if (b < 2)
00585 v = ((i[p] >> b) & 0x7F);
00586 else
00587 v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
00588 b += 7;
00589 if (b >= 8) {
00590 b -= 8;
00591 p++;
00592 }
00593
00594 if (o > ud && o[-1] == 0x00A0 && escapes[v])
00595 o[-1] = escapes[v];
00596 else
00597 *o++ = defaultalphabet[v];
00598 }
00599 *udl = (o - ud);
00600 }
00601
00602
00603
00604
00605 static void unpacksms8(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00606 {
00607 unsigned short *o = ud;
00608 *udhl = 0;
00609 if (udhi) {
00610 int n = *i;
00611 *udhl = n;
00612 if (n) {
00613 i++;
00614 l--;
00615 while (l && n) {
00616 l--;
00617 n--;
00618 *udh++ = *i++;
00619 }
00620 }
00621 }
00622 while (l--)
00623 *o++ = *i++;
00624 *udl = (o - ud);
00625 }
00626
00627
00628
00629
00630 static void unpacksms16(unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00631 {
00632 unsigned short *o = ud;
00633 *udhl = 0;
00634 if (udhi) {
00635 int n = *i;
00636 *udhl = n;
00637 if (n) {
00638 i++;
00639 l--;
00640 while (l && n) {
00641 l--;
00642 n--;
00643 *udh++ = *i++;
00644 }
00645 }
00646 }
00647 while (l--) {
00648 int v = *i++;
00649 if (l--)
00650 v = (v << 8) + *i++;
00651 *o++ = v;
00652 }
00653 *udl = (o - ud);
00654 }
00655
00656
00657 static int unpacksms(unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00658 {
00659 int l = *i++;
00660 if (is7bit(dcs)) {
00661 unpacksms7(i, l, udh, udhl, ud, udl, udhi);
00662 l = (l * 7 + 7) / 8;
00663 } else if (is8bit(dcs))
00664 unpacksms8(i, l, udh, udhl, ud, udl, udhi);
00665 else
00666 unpacksms16(i, l, udh, udhl, ud, udl, udhi);
00667 return l + 1;
00668 }
00669
00670
00671 static unsigned char unpackaddress(char *o, unsigned char *i)
00672 {
00673 unsigned char l = i[0],
00674 p;
00675 if (i[1] == 0x91)
00676 *o++ = '+';
00677 for (p = 0; p < l; p++) {
00678 if (p & 1)
00679 *o++ = (i[2 + p / 2] >> 4) + '0';
00680 else
00681 *o++ = (i[2 + p / 2] & 0xF) + '0';
00682 }
00683 *o = 0;
00684 return (l + 5) / 2;
00685 }
00686
00687
00688 static unsigned char packaddress(unsigned char *o, char *i)
00689 {
00690 unsigned char p = 2;
00691 o[0] = 0;
00692 if (*i == '+') {
00693 i++;
00694 o[1] = 0x91;
00695 } else
00696 o[1] = 0x81;
00697 for ( ; *i ; i++) {
00698 if (!isdigit(*i))
00699 continue;
00700 if (o[0] & 1)
00701 o[p++] |= ((*i & 0xF) << 4);
00702 else
00703 o[p] = (*i & 0xF);
00704 o[0]++;
00705 }
00706 if (o[0] & 1)
00707 o[p++] |= 0xF0;
00708 return p;
00709 }
00710
00711
00712 static void sms_log(sms_t * h, char status)
00713 {
00714 int o;
00715
00716 if (*h->oa == '\0' && *h->da == '\0')
00717 return;
00718 o = open(log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE);
00719 if (o >= 0) {
00720 char line[1000], mrs[3] = "", *p;
00721 char buf[30];
00722 unsigned char n;
00723
00724 if (h->mr >= 0)
00725 snprintf(mrs, sizeof(mrs), "%02X", h->mr);
00726 snprintf(line, sizeof(line), "%s %c%c%c%s %s %s %s ",
00727 isodate(time(NULL), buf, sizeof(buf)),
00728 status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue,
00729 S_OR(h->oa, "-"), S_OR(h->da, "-") );
00730 p = line + strlen(line);
00731 for (n = 0; n < h->udl; n++) {
00732 if (h->ud[n] == '\\') {
00733 *p++ = '\\';
00734 *p++ = '\\';
00735 } else if (h->ud[n] == '\n') {
00736 *p++ = '\\';
00737 *p++ = 'n';
00738 } else if (h->ud[n] == '\r') {
00739 *p++ = '\\';
00740 *p++ = 'r';
00741 } else if (h->ud[n] < 32 || h->ud[n] == 127)
00742 *p++ = 191;
00743 else
00744 *p++ = h->ud[n];
00745 }
00746 *p++ = '\n';
00747 *p = 0;
00748 if (write(o, line, strlen(line)) < 0) {
00749 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00750 }
00751 close(o);
00752 }
00753 *h->oa = *h->da = h->udl = 0;
00754 }
00755
00756
00757 static void sms_readfile(sms_t * h, char *fn)
00758 {
00759 char line[1000];
00760 FILE *s;
00761 char dcsset = 0;
00762 ast_log(LOG_EVENT, "Sending %s\n", fn);
00763 h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
00764 h->mr = -1;
00765 h->dcs = 0xF1;
00766 h->scts = ast_tvnow();
00767 s = fopen(fn, "r");
00768 if (s) {
00769 if (unlink(fn)) {
00770 fclose(s);
00771 return;
00772 }
00773 while (fgets (line, sizeof(line), s)) {
00774 char *p;
00775 void *pp = &p;
00776 for (p = line; *p && *p != '\n' && *p != '\r'; p++);
00777 *p = 0;
00778 p = line;
00779 if (!*p || *p == ';')
00780 continue;
00781 while (isalnum(*p)) {
00782 *p = tolower (*p);
00783 p++;
00784 }
00785 while (isspace (*p))
00786 *p++ = 0;
00787 if (*p == '=') {
00788 *p++ = 0;
00789 if (!strcmp(line, "ud")) {
00790 unsigned char o = 0;
00791 memcpy(h->udtxt, p, SMSLEN);
00792 while (*p && o < SMSLEN)
00793 h->ud[o++] = utf8decode(pp);
00794 h->udl = o;
00795 if (*p)
00796 ast_log(LOG_WARNING, "UD too long in %s\n", fn);
00797 } else {
00798 while (isspace (*p))
00799 p++;
00800 if (!strcmp(line, "oa") && strlen(p) < sizeof(h->oa))
00801 numcpy (h->oa, p);
00802 else if (!strcmp(line, "da") && strlen(p) < sizeof(h->oa))
00803 numcpy (h->da, p);
00804 else if (!strcmp(line, "pid"))
00805 h->pid = atoi(p);
00806 else if (!strcmp(line, "dcs")) {
00807 h->dcs = atoi(p);
00808 dcsset = 1;
00809 } else if (!strcmp(line, "mr"))
00810 h->mr = atoi(p);
00811 else if (!strcmp(line, "srr"))
00812 h->srr = (atoi(p) ? 1 : 0);
00813 else if (!strcmp(line, "vp"))
00814 h->vp = atoi(p);
00815 else if (!strcmp(line, "rp"))
00816 h->rp = (atoi(p) ? 1 : 0);
00817 else if (!strcmp(line, "scts")) {
00818 int Y,
00819 m,
00820 d,
00821 H,
00822 M,
00823 S;
00824 if (sscanf (p, "%d-%d-%dT%d:%d:%d", &Y, &m, &d, &H, &M, &S) == 6) {
00825 struct ast_tm t = { 0, };
00826 t.tm_year = Y - 1900;
00827 t.tm_mon = m - 1;
00828 t.tm_mday = d;
00829 t.tm_hour = H;
00830 t.tm_min = M;
00831 t.tm_sec = S;
00832 t.tm_isdst = -1;
00833 h->scts = ast_mktime(&t, NULL);
00834 if (h->scts.tv_sec == 0)
00835 ast_log(LOG_WARNING, "Bad date/timein %s: %s", fn, p);
00836 }
00837 } else
00838 ast_log(LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
00839 }
00840 } else if (*p == '#') {
00841 *p++ = 0;
00842 if (*p == '#') {
00843 p++;
00844 if (!strcmp(line, "ud")) {
00845 int o = 0;
00846 while (*p && o < SMSLEN) {
00847 if (isxdigit(*p) && isxdigit(p[1]) && isxdigit(p[2]) && isxdigit(p[3])) {
00848 h->ud[o++] =
00849 (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 12) +
00850 (((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
00851 (((isalpha(p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha(p[3]) ? 9 : 0) + (p[3] & 0xF));
00852 p += 4;
00853 } else
00854 break;
00855 }
00856 h->udl = o;
00857 if (*p)
00858 ast_log(LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
00859 } else
00860 ast_log(LOG_WARNING, "Only ud can use ## format, %s\n", fn);
00861 } else if (!strcmp(line, "ud")) {
00862 int o = 0;
00863 while (*p && o < SMSLEN) {
00864 if (isxdigit(*p) && isxdigit(p[1])) {
00865 h->ud[o++] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
00866 p += 2;
00867 } else
00868 break;
00869 }
00870 h->udl = o;
00871 if (*p)
00872 ast_log(LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
00873 } else if (!strcmp(line, "udh")) {
00874 unsigned char o = 0;
00875 h->udhi = 1;
00876 while (*p && o < SMSLEN) {
00877 if (isxdigit(*p) && isxdigit(p[1])) {
00878 h->udh[o] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
00879 o++;
00880 p += 2;
00881 } else
00882 break;
00883 }
00884 h->udhl = o;
00885 if (*p)
00886 ast_log(LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
00887 } else
00888 ast_log(LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
00889 } else
00890 ast_log(LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
00891 }
00892 fclose(s);
00893 if (!dcsset && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00894 if (packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) {
00895 if (packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0)
00896 ast_log(LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
00897 else {
00898 h->dcs = 0x08;
00899 ast_log(LOG_WARNING, "Sending in 16 bit format(%s)\n", fn);
00900 }
00901 } else {
00902 h->dcs = 0xF5;
00903 ast_log(LOG_WARNING, "Sending in 8 bit format(%s)\n", fn);
00904 }
00905 }
00906 if (is7bit(h->dcs) && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0)
00907 ast_log(LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
00908 if (is8bit(h->dcs) && packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0)
00909 ast_log(LOG_WARNING, "Invalid 8 bit data %s\n", fn);
00910 if (is16bit(h->dcs) && packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0)
00911 ast_log(LOG_WARNING, "Invalid 16 bit data %s\n", fn);
00912 }
00913 }
00914
00915
00916 static void sms_writefile(sms_t * h)
00917 {
00918 char fn[200] = "", fn2[200] = "";
00919 char buf[30];
00920 FILE *o;
00921
00922 snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
00923 ast_mkdir(fn, 0777);
00924 ast_copy_string(fn2, fn, sizeof(fn2));
00925 snprintf(fn2 + strlen(fn2), sizeof(fn2) - strlen(fn2), "/%s.%s-%d", h->queue, isodate(h->scts.tv_sec, buf, sizeof(buf)), seq++);
00926 snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/.%s", fn2 + strlen(fn) + 1);
00927 o = fopen(fn, "w");
00928 if (o == NULL)
00929 return;
00930
00931 if (*h->oa)
00932 fprintf(o, "oa=%s\n", h->oa);
00933 if (*h->da)
00934 fprintf(o, "da=%s\n", h->da);
00935 if (h->udhi) {
00936 unsigned int p;
00937 fprintf(o, "udh#");
00938 for (p = 0; p < h->udhl; p++)
00939 fprintf(o, "%02X", h->udh[p]);
00940 fprintf(o, "\n");
00941 }
00942 if (h->udl) {
00943 unsigned int p;
00944 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00945 if (p < h->udl)
00946 fputc(';', o);
00947 fprintf(o, "ud=");
00948 for (p = 0; p < h->udl; p++) {
00949 unsigned short v = h->ud[p];
00950 if (v < 32)
00951 fputc(191, o);
00952 else if (v < 0x80)
00953 fputc(v, o);
00954 else if (v < 0x800)
00955 {
00956 fputc(0xC0 + (v >> 6), o);
00957 fputc(0x80 + (v & 0x3F), o);
00958 } else
00959 {
00960 fputc(0xE0 + (v >> 12), o);
00961 fputc(0x80 + ((v >> 6) & 0x3F), o);
00962 fputc(0x80 + (v & 0x3F), o);
00963 }
00964 }
00965 fprintf(o, "\n");
00966 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00967 if (p < h->udl) {
00968 for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
00969 if (p == h->udl) {
00970 fprintf(o, "ud#");
00971 for (p = 0; p < h->udl; p++)
00972 fprintf(o, "%02X", h->ud[p]);
00973 fprintf(o, "\n");
00974 } else {
00975 fprintf(o, "ud##");
00976 for (p = 0; p < h->udl; p++)
00977 fprintf(o, "%04X", h->ud[p]);
00978 fprintf(o, "\n");
00979 }
00980 }
00981 }
00982 if (h->scts.tv_sec) {
00983 char buf[30];
00984 fprintf(o, "scts=%s\n", isodate(h->scts.tv_sec, buf, sizeof(buf)));
00985 }
00986 if (h->pid)
00987 fprintf(o, "pid=%d\n", h->pid);
00988 if (h->dcs != 0xF1)
00989 fprintf(o, "dcs=%d\n", h->dcs);
00990 if (h->vp)
00991 fprintf(o, "vp=%d\n", h->vp);
00992 if (h->srr)
00993 fprintf(o, "srr=1\n");
00994 if (h->mr >= 0)
00995 fprintf(o, "mr=%d\n", h->mr);
00996 if (h->rp)
00997 fprintf(o, "rp=1\n");
00998 fclose(o);
00999 if (rename(fn, fn2))
01000 unlink(fn);
01001 else
01002 ast_log(LOG_EVENT, "Received to %s\n", fn2);
01003 }
01004
01005
01006 static struct dirent *readdirqueue(DIR *d, char *queue)
01007 {
01008 struct dirent *f;
01009 do {
01010 f = readdir(d);
01011 } while (f && (*f->d_name == '.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] != '.'));
01012 return f;
01013 }
01014
01015
01016 static unsigned char sms_handleincoming (sms_t * h)
01017 {
01018 unsigned char p = 3;
01019 if (h->smsc) {
01020 if ((h->imsg[2] & 3) == 1) {
01021 h->udhl = h->udl = 0;
01022 h->vp = 0;
01023 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
01024 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
01025 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01026 ast_copy_string(h->oa, h->cli, sizeof(h->oa));
01027 h->scts = ast_tvnow();
01028 h->mr = h->imsg[p++];
01029 p += unpackaddress(h->da, h->imsg + p);
01030 h->pid = h->imsg[p++];
01031 h->dcs = h->imsg[p++];
01032 if ((h->imsg[2] & 0x18) == 0x10) {
01033 if (h->imsg[p] < 144)
01034 h->vp = (h->imsg[p] + 1) * 5;
01035 else if (h->imsg[p] < 168)
01036 h->vp = 720 + (h->imsg[p] - 143) * 30;
01037 else if (h->imsg[p] < 197)
01038 h->vp = (h->imsg[p] - 166) * 1440;
01039 else
01040 h->vp = (h->imsg[p] - 192) * 10080;
01041 p++;
01042 } else if (h->imsg[2] & 0x18)
01043 p += 7;
01044 p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01045 h->rx = 1;
01046 sms_writefile(h);
01047 if (p != h->imsg[1] + 2) {
01048 ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01049 return 0xFF;
01050 }
01051 } else {
01052 ast_log(LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
01053 return 0xFF;
01054 }
01055 } else {
01056 if (!(h->imsg[2] & 3)) {
01057 *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
01058 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
01059 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
01060 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01061 h->mr = -1;
01062 p += unpackaddress(h->oa, h->imsg + p);
01063 h->pid = h->imsg[p++];
01064 h->dcs = h->imsg[p++];
01065 h->scts = unpackdate(h->imsg + p);
01066 p += 7;
01067 p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01068 h->rx = 1;
01069 sms_writefile(h);
01070 if (p != h->imsg[1] + 2) {
01071 ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01072 return 0xFF;
01073 }
01074 } else {
01075 ast_log(LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
01076 return 0xFF;
01077 }
01078 }
01079 return 0;
01080 }
01081
01082 #ifdef SOLARIS
01083 #define NAME_MAX 1024
01084 #endif
01085
01086
01087
01088
01089
01090 static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
01091 {
01092 int x = h->omsg[1]+2;
01093 if (x == 2)
01094 x += 2;
01095 h->omsg[x++] = msg;
01096 h->omsg[x++] = (unsigned char)size;
01097 h->omsg[x++] = 0;
01098 for (; size > 0 ; size--)
01099 h->omsg[x++] = *data++;
01100 h->omsg[1] = x - 2;
01101 h->omsg[2] = x - 4;
01102 h->omsg[3] = 0;
01103 }
01104
01105 static void putdummydata_proto2(sms_t *h)
01106 {
01107 adddata_proto2(h, 0x10, "\0", 1);
01108 adddata_proto2(h, 0x11, "\0\0\0\0\0\0", 6);
01109 adddata_proto2(h, 0x12, "\2\0\4", 3);
01110 adddata_proto2(h, 0x13, h->udtxt, h->udl);
01111 }
01112
01113 static void sms_compose2(sms_t *h, int more)
01114 {
01115 struct ast_tm tm;
01116 struct timeval tv = h->scts;
01117 char stm[9];
01118
01119 h->omsg[0] = 0x00;
01120 h->omsg[1] = 0;
01121 putdummydata_proto2(h);
01122 if (h->smsc) {
01123 h->omsg[0] = 0x11;
01124
01125 ast_localtime(&tv, &tm, NULL);
01126 sprintf(stm, "%02d%02d%02d%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);
01127 adddata_proto2(h, 0x14, stm, 8);
01128 if (*h->oa == 0)
01129 strcpy(h->oa, "00000000");
01130 adddata_proto2(h, 0x15, h->oa, strlen(h->oa));
01131 adddata_proto2(h, 0x17, "\1", 1);
01132 } else {
01133 h->omsg[0] = 0x10;
01134
01135 adddata_proto2(h, 0x17, "\1", 1);
01136 if (*h->da == 0)
01137 strcpy(h->da, "00000000");
01138 adddata_proto2(h, 0x18, h->da, strlen(h->da));
01139 adddata_proto2(h, 0x1B, "\1", 1);
01140 adddata_proto2(h, 0x1C, "\0\0\0", 3);
01141 }
01142 }
01143
01144 static void putdummydata_proto2(sms_t *h);
01145
01146 #define MAX_DEBUG_LEN 300
01147 static char *sms_hexdump(unsigned char buf[], int size, char *s )
01148 {
01149 char *p;
01150 int f;
01151
01152 for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3)
01153 sprintf(p, "%02X ", (unsigned char)buf[f]);
01154 return(s);
01155 }
01156
01157
01158
01159 static int sms_handleincoming_proto2(sms_t *h)
01160 {
01161 int f, i, sz = 0;
01162 int msg, msgsz;
01163 struct ast_tm tm;
01164 struct timeval tv = { 0, 0 };
01165 char debug_buf[MAX_DEBUG_LEN * 3 + 1];
01166
01167 sz = h->imsg[1] + 2;
01168
01169
01170
01171 tv = h->scts = ast_tvnow();
01172 for (f = 4; f < sz; ) {
01173 msg = h->imsg[f++];
01174 msgsz = h->imsg[f++];
01175 msgsz += (h->imsg[f++] * 256);
01176 switch (msg) {
01177 case 0x13:
01178 ast_verb(3, "SMS-P2 Body#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]);
01179 if (msgsz >= sizeof(h->imsg))
01180 msgsz = sizeof(h->imsg) - 1;
01181 for (i = 0; i < msgsz; i++)
01182 h->ud[i] = h->imsg[f + i];
01183 h->udl = msgsz;
01184 break;
01185 case 0x14:
01186 tv = h->scts = ast_tvnow();
01187 ast_localtime(&tv, &tm, NULL);
01188 tm.tm_mon = ( (h->imsg[f] * 10) + h->imsg[f + 1] ) - 1;
01189 tm.tm_mday = ( (h->imsg[f + 2] * 10) + h->imsg[f + 3] );
01190 tm.tm_hour = ( (h->imsg[f + 4] * 10) + h->imsg[f + 5] );
01191 tm.tm_min = ( (h->imsg[f + 6] * 10) + h->imsg[f + 7] );
01192 tm.tm_sec = 0;
01193 h->scts = ast_mktime(&tm, NULL);
01194 ast_verb(3, "SMS-P2 Date#%02X=%02d/%02d %02d:%02d\n", msg, tm.tm_mday, tm.tm_mon + 1, tm.tm_hour, tm.tm_min);
01195 break;
01196 case 0x15:
01197 if (msgsz >= 20)
01198 msgsz = 20 - 1;
01199 ast_verb(3, "SMS-P2 Origin#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]);
01200 ast_copy_string(h->oa, (char *)(&h->imsg[f]), msgsz + 1);
01201 break;
01202 case 0x18:
01203 if (msgsz >= 20)
01204 msgsz = 20 - 1;
01205 ast_verb(3, "SMS-P2 Destination#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]);
01206 ast_copy_string(h->da, (char *)(&h->imsg[f]), msgsz + 1);
01207 break;
01208 case 0x1C:
01209 ast_verb(3, "SMS-P2 Notify#%02X=%s\n", msg, sms_hexdump(&h->imsg[f], 3, debug_buf));
01210 break;
01211 default:
01212 ast_verb(3, "SMS-P2 Par#%02X [%d]: %s\n", msg, msgsz, sms_hexdump(&h->imsg[f], msgsz, debug_buf));
01213 break;
01214 }
01215 f+=msgsz;
01216 }
01217 h->rx = 1;
01218 sms_writefile(h);
01219 return 0;
01220 }
01221
01222 #if 0
01223 static void smssend(sms_t *h, char *c)
01224 {
01225 int f, x;
01226 for (f = 0; f < strlen(c); f++) {
01227 sscanf(&c[f*3], "%x", &x);
01228 h->omsg[f] = x;
01229 }
01230 sms_messagetx(h);
01231 }
01232 #endif
01233
01234 static void sms_nextoutgoing (sms_t *h);
01235
01236 static void sms_messagerx2(sms_t * h)
01237 {
01238 int p = h->imsg[0] & DLL_SMS_MASK ;
01239 int cause;
01240
01241 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
01242 switch (p) {
01243 case DLL2_SMS_EST:
01244 sms_nextoutgoing (h);
01245
01246 break;
01247
01248 case DLL2_SMS_INFO_MO:
01249 case DLL2_SMS_INFO_MT:
01250 cause = sms_handleincoming_proto2(h);
01251 if (!cause)
01252 sms_log(h, 'Y');
01253 h->omsg[0] = DLL2_ACK(h);
01254 h->omsg[1] = 0x06;
01255 h->omsg[2] = 0x04;
01256 h->omsg[3] = 0x00;
01257 h->omsg[4] = 0x1f;
01258 h->omsg[5] = 0x01;
01259 h->omsg[6] = 0x00;
01260 h->omsg[7] = cause;
01261 sms_messagetx(h);
01262 break;
01263
01264 case DLL2_SMS_NACK:
01265 h->omsg[0] = DLL2_SMS_REL;
01266 h->omsg[1] = 0x00;
01267 sms_messagetx(h);
01268 break;
01269
01270 case DLL2_SMS_ACK0:
01271 case DLL2_SMS_ACK1:
01272
01273 if ( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
01274
01275 h->hangup = 1;
01276 } else {
01277
01278 ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY");
01279 sms_nextoutgoing (h);
01280 }
01281 break;
01282
01283 case DLL2_SMS_REL:
01284 h->omsg[0] = DLL2_ACK(h);
01285 h->omsg[1] = 0;
01286 sms_messagetx(h);
01287 break;
01288 }
01289 }
01290
01291
01292 static void sms_compose1(sms_t *h, int more)
01293 {
01294 unsigned int p = 2;
01295
01296 h->omsg[0] = 0x91;
01297 if (h->smsc) {
01298 h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
01299 p += packaddress(h->omsg + p, h->oa);
01300 h->omsg[p++] = h->pid;
01301 h->omsg[p++] = h->dcs;
01302 packdate(h->omsg + p, h->scts.tv_sec);
01303 p += 7;
01304 p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01305 } else {
01306 h->omsg[p++] =
01307 0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
01308 if (h->mr < 0)
01309 h->mr = message_ref++;
01310 h->omsg[p++] = h->mr;
01311 p += packaddress(h->omsg + p, h->da);
01312 h->omsg[p++] = h->pid;
01313 h->omsg[p++] = h->dcs;
01314 if (h->vp) {
01315 if (h->vp < 720)
01316 h->omsg[p++] = (h->vp + 4) / 5 - 1;
01317 else if (h->vp < 1440)
01318 h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
01319 else if (h->vp < 43200)
01320 h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
01321 else if (h->vp < 635040)
01322 h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
01323 else
01324 h->omsg[p++] = 255;
01325 }
01326 p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01327 }
01328 h->omsg[1] = p - 2;
01329 }
01330
01331
01332 static void sms_nextoutgoing (sms_t * h)
01333 {
01334 char fn[100 + NAME_MAX] = "";
01335 DIR *d;
01336 char more = 0;
01337
01338 *h->da = *h->oa = '\0';
01339 h->rx = 0;
01340 snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? "mttx" : "motx");
01341 ast_mkdir(fn, 0777);
01342 d = opendir(fn);
01343 if (d) {
01344 struct dirent *f = readdirqueue(d, h->queue);
01345 if (f) {
01346 snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", f->d_name);
01347 sms_readfile(h, fn);
01348 if (readdirqueue(d, h->queue))
01349 more = 1;
01350 }
01351 closedir(d);
01352 }
01353 if (*h->da || *h->oa) {
01354 if (h->protocol == 2)
01355 sms_compose2(h, more);
01356 else
01357 sms_compose1(h, more);
01358 } else {
01359 if (h->protocol == 2) {
01360 h->omsg[0] = 0x17;
01361 h->omsg[1] = 0;
01362 } else {
01363 h->omsg[0] = 0x94;
01364 h->omsg[1] = 0;
01365 }
01366 }
01367 sms_messagetx(h);
01368 }
01369
01370 #define DIR_RX 1
01371 #define DIR_TX 2
01372 static void sms_debug (int dir, sms_t *h)
01373 {
01374 char txt[259 * 3 + 1];
01375 char *p = txt;
01376 unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg;
01377 int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2;
01378 int q = 0;
01379 while (q < n && q < 30) {
01380 sprintf(p, " %02X", msg[q++]);
01381 p += 3;
01382 }
01383 if (q < n)
01384 sprintf(p, "...");
01385 ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt);
01386 }
01387
01388
01389 static void sms_messagerx(sms_t * h)
01390 {
01391 int cause;
01392
01393 sms_debug (DIR_RX, h);
01394 if (h->protocol == 2) {
01395 sms_messagerx2(h);
01396 return;
01397 }
01398
01399 switch (h->imsg[0]) {
01400 case 0x91:
01401 cause = sms_handleincoming (h);
01402 if (!cause) {
01403 sms_log(h, 'Y');
01404 h->omsg[0] = 0x95;
01405 h->omsg[1] = 0x02;
01406 h->omsg[2] = 0x00;
01407 h->omsg[3] = 0x00;
01408 } else {
01409 sms_log(h, 'N');
01410 h->omsg[0] = 0x96;
01411 h->omsg[1] = 3;
01412 h->omsg[2] = 0;
01413 h->omsg[3] = cause;
01414 h->omsg[4] = 0;
01415 }
01416 sms_messagetx(h);
01417 break;
01418
01419 case 0x92:
01420 h->err = 1;
01421 sms_messagetx(h);
01422 break;
01423 case 0x93:
01424 sms_nextoutgoing (h);
01425 break;
01426 case 0x94:
01427 h->hangup = 1;
01428 break;
01429 case 0x95:
01430 sms_log(h, 'Y');
01431 sms_nextoutgoing (h);
01432 break;
01433 case 0x96:
01434 h->err = 1;
01435 sms_log(h, 'N');
01436 sms_nextoutgoing (h);
01437 break;
01438 default:
01439 h->omsg[0] = 0x92;
01440 h->omsg[1] = 1;
01441 h->omsg[2] = 3;
01442 sms_messagetx(h);
01443 break;
01444 }
01445 }
01446
01447 static void sms_messagetx(sms_t * h)
01448 {
01449 unsigned char c = 0, p;
01450 int len = h->omsg[1] + 2;
01451
01452 for (p = 0; p < len; p++)
01453 c += h->omsg[p];
01454 h->omsg[len] = 0 - c;
01455 sms_debug(DIR_TX, h);
01456 h->framenumber++;
01457 h->obyte = 1;
01458 h->opause = 200;
01459
01460
01461
01462
01463 if (h->omsg[0] == 0x93)
01464 h->opause = 8 * h->opause_0;
01465 h->obytep = 0;
01466 h->obitp = 0;
01467 if (h->protocol == 2) {
01468 h->oseizure = 300;
01469 h->obyte = 0;
01470 h->opause = 400;
01471 } else {
01472 h->oseizure = 0;
01473 }
01474
01475 h->osync = OSYNC_BITS;
01476 h->obyten = len + 1;
01477 }
01478
01479
01480
01481
01482
01483 static int sms_generate(struct ast_channel *chan, void *data, int len, int samples)
01484 {
01485 struct ast_frame f = { 0 };
01486 #define MAXSAMPLES (800)
01487 output_t *buf;
01488 sms_t *h = data;
01489 int i;
01490
01491 if (samples > MAXSAMPLES) {
01492 ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n",
01493 MAXSAMPLES, samples);
01494 samples = MAXSAMPLES;
01495 }
01496 len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET;
01497 buf = alloca(len);
01498
01499 f.frametype = AST_FRAME_VOICE;
01500 f.subclass = __OUT_FMT;
01501 f.datalen = samples * sizeof(*buf);
01502 f.offset = AST_FRIENDLY_OFFSET;
01503 f.mallocd = 0;
01504 f.data = buf;
01505 f.samples = samples;
01506 f.src = "app_sms";
01507
01508 for (i = 0; i < samples; i++) {
01509 buf[i] = wave_out[0];
01510
01511 if (h->opause)
01512 h->opause--;
01513 else if (h->obyten || h->osync) {
01514 buf[i] = wave_out[h->ophase];
01515 h->ophase += (h->obyte & 1) ? 13 : 21;
01516 if (h->ophase >= 80)
01517 h->ophase -= 80;
01518 if ((h->ophasep += 12) >= 80) {
01519 h->ophasep -= 80;
01520 if (h->oseizure > 0) {
01521 h->oseizure--;
01522 h->obyte ^= 1;
01523 } else if (h->osync) {
01524 h->obyte = 1;
01525 h->osync--;
01526 if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) {
01527 h->obytep = h->obyten = 0;
01528 }
01529 } else {
01530 h->obitp++;
01531 if (h->obitp == 1)
01532 h->obyte = 0;
01533 else if (h->obitp == 2)
01534 h->obyte = h->omsg[h->obytep];
01535 else if (h->obitp == 10) {
01536 h->obyte = 1;
01537 h->obitp = 0;
01538 h->obytep++;
01539 if (h->obytep == h->obyten) {
01540 h->obytep = h->obyten = 0;
01541 h->osync = 10;
01542 }
01543 } else
01544 h->obyte >>= 1;
01545 }
01546 }
01547 }
01548 }
01549 if (ast_write(chan, &f) < 0) {
01550 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
01551 return -1;
01552 }
01553 return 0;
01554 #undef MAXSAMPLES
01555 }
01556
01557
01558
01559
01560 static void *sms_alloc(struct ast_channel *chan, void *sms_t_ptr)
01561 {
01562 return sms_t_ptr;
01563 }
01564
01565 static void sms_release(struct ast_channel *chan, void *data)
01566 {
01567 return;
01568 }
01569
01570 static struct ast_generator smsgen = {
01571 .alloc = sms_alloc,
01572 .release = sms_release,
01573 .generate = sms_generate,
01574 };
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588 static void sms_process(sms_t * h, int samples, signed short *data)
01589 {
01590 int bit;
01591
01592
01593
01594
01595
01596
01597
01598
01599 if (h->obyten || h->osync)
01600 return;
01601 for ( ; samples-- ; data++) {
01602 unsigned long long m0, m1;
01603 if (abs(*data) > h->imag)
01604 h->imag = abs(*data);
01605 else
01606 h->imag = h->imag * 7 / 8;
01607 if (h->imag <= 500) {
01608 if (h->idle++ == 80000) {
01609 ast_log(LOG_NOTICE, "No data, hanging up\n");
01610 h->hangup = 1;
01611 h->err = 1;
01612 }
01613 if (h->ierr) {
01614 ast_log(LOG_NOTICE, "Error %d, hanging up\n", h->ierr);
01615
01616 h->err = 1;
01617 h->omsg[0] = 0x92;
01618 h->omsg[1] = 1;
01619 h->omsg[2] = h->ierr;
01620 sms_messagetx(h);
01621 }
01622 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01623 continue;
01624 }
01625 h->idle = 0;
01626
01627
01628 h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
01629 h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
01630 h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
01631 h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
01632
01633 m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
01634 m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
01635
01636
01637 if ((h->ips0 += 21) >= 80)
01638 h->ips0 -= 80;
01639 if ((h->ipc0 += 21) >= 80)
01640 h->ipc0 -= 80;
01641 if ((h->ips1 += 13) >= 80)
01642 h->ips1 -= 80;
01643 if ((h->ipc1 += 13) >= 80)
01644 h->ipc1 -= 80;
01645
01646
01647 h->ibith <<= 1;
01648 if (m1 > m0)
01649 h->ibith |= 1;
01650 if (h->ibith & 8)
01651 h->ibitt--;
01652 if (h->ibith & 1)
01653 h->ibitt++;
01654 bit = ((h->ibitt > 1) ? 1 : 0);
01655 if (bit != h->ibitl)
01656 h->ibitc = 1;
01657 else
01658 h->ibitc++;
01659 h->ibitl = bit;
01660 if (!h->ibitn && h->ibitc == 4 && !bit) {
01661 h->ibitn = 1;
01662 h->iphasep = 0;
01663 }
01664 if (bit && h->ibitc == 200) {
01665
01666 if (h->framenumber < 0 && h->ibytec >= 160 && !memcmp(h->imsg, "UUUUUUUUUUUUUUUUUUUU", 20)) {
01667 h->framenumber = 1;
01668 ast_verb(3, "SMS protocol 2 detected\n");
01669 h->protocol = 2;
01670 h->imsg[0] = 0xff;
01671 h->imsg[1] = h->imsg[2] = 0x00;
01672 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01673 sms_messagerx(h);
01674 }
01675 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01676 }
01677 if (h->ibitn) {
01678 h->iphasep += 12;
01679 if (h->iphasep >= 80) {
01680 h->iphasep -= 80;
01681 if (h->ibitn++ == 9) {
01682 if (!bit) {
01683 ast_log(LOG_NOTICE, "bad stop bit");
01684 h->ierr = 0xFF;
01685 } else {
01686 if (h->ibytep < sizeof(h->imsg)) {
01687 h->imsg[h->ibytep] = h->ibytev;
01688 h->ibytec += h->ibytev;
01689 h->ibytep++;
01690 } else if (h->ibytep == sizeof(h->imsg)) {
01691 ast_log(LOG_NOTICE, "msg too large");
01692 h->ierr = 2;
01693 }
01694 if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
01695 if (!h->ibytec)
01696 sms_messagerx(h);
01697 else {
01698 ast_log(LOG_NOTICE, "bad checksum");
01699 h->ierr = 1;
01700 }
01701 }
01702 }
01703 h->ibitn = 0;
01704 }
01705 h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
01706 }
01707 }
01708 }
01709 }
01710
01711
01712
01713
01714
01715
01716
01717
01718 enum {
01719 OPTION_BE_SMSC = (1 << 0),
01720 OPTION_ANSWER = (1 << 1),
01721 OPTION_TWO = (1 << 2),
01722 OPTION_PAUSE = (1 << 3),
01723 OPTION_SRR = (1 << 4),
01724 OPTION_DCS = (1 << 5),
01725 } sms_flags;
01726
01727 enum {
01728 OPTION_ARG_PAUSE = 0,
01729 OPTION_ARG_ARRAY_SIZE
01730 } sms_opt_args;
01731
01732 AST_APP_OPTIONS(sms_options, {
01733 AST_APP_OPTION('s', OPTION_BE_SMSC),
01734 AST_APP_OPTION('a', OPTION_ANSWER),
01735 AST_APP_OPTION('t', OPTION_TWO),
01736 AST_APP_OPTION('r', OPTION_SRR),
01737 AST_APP_OPTION('o', OPTION_DCS),
01738 AST_APP_OPTION_ARG('p', OPTION_PAUSE, OPTION_ARG_PAUSE),
01739 } );
01740
01741 static int sms_exec(struct ast_channel *chan, void *data)
01742 {
01743 int res = -1;
01744 sms_t h = { 0 };
01745
01746 struct ast_flags sms_flags;
01747 char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, };
01748 char *p;
01749 AST_DECLARE_APP_ARGS(sms_args,
01750 AST_APP_ARG(queue);
01751 AST_APP_ARG(options);
01752 AST_APP_ARG(addr);
01753 AST_APP_ARG(body);
01754 );
01755
01756 if (!data) {
01757 ast_log(LOG_ERROR, "Requires queue name at least\n");
01758 return -1;
01759 }
01760
01761 parse = ast_strdupa(data);
01762 AST_STANDARD_APP_ARGS(sms_args, parse);
01763 if (sms_args.argc > 1)
01764 ast_app_parse_options(sms_options, &sms_flags, sms_opts, sms_args.options);
01765
01766 ast_verb(1, "sms argc %d queue <%s> opts <%s> addr <%s> body <%s>\n",
01767 sms_args.argc, S_OR(sms_args.queue, ""),
01768 S_OR(sms_args.options, ""),
01769 S_OR(sms_args.addr, ""),
01770 S_OR(sms_args.body, "") );
01771
01772 h.ipc0 = h.ipc1 = 20;
01773 h.dcs = 0xF1;
01774
01775 if (chan->cid.cid_num)
01776 ast_copy_string(h.cli, chan->cid.cid_num, sizeof(h.cli));
01777
01778 if (ast_strlen_zero(sms_args.queue)) {
01779 ast_log(LOG_ERROR, "Requires queue name\n");
01780 goto done;
01781 }
01782 if (strlen(sms_args.queue) >= sizeof(h.queue)) {
01783 ast_log(LOG_ERROR, "Queue name too long\n");
01784 goto done;
01785 }
01786 ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue));
01787
01788 for (p = h.queue; *p; p++)
01789 if (!isalnum(*p))
01790 *p = '-';
01791
01792 h.smsc = ast_test_flag(&sms_flags, OPTION_BE_SMSC);
01793 h.protocol = ast_test_flag(&sms_flags, OPTION_TWO) ? 2 : 1;
01794 if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE]))
01795 h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
01796 if (h.opause_0 < 25 || h.opause_0 > 2000)
01797 h.opause_0 = 300;
01798 ast_verb(1, "initial delay %dms\n", h.opause_0);
01799
01800
01801
01802 if (ast_test_flag(&sms_flags, OPTION_SRR))
01803 h.srr = 1;
01804 if (ast_test_flag(&sms_flags, OPTION_DCS))
01805 h.dcs = 1;
01806 #if 0
01807 case '1':
01808 case '2':
01809 case '3':
01810 case '4':
01811 case '5':
01812 case '6':
01813 case '7':
01814 h.pid = 0x40 + (*d & 0xF);
01815 break;
01816 }
01817 #endif
01818 if (sms_args.argc > 2) {
01819 unsigned char *up;
01820
01821
01822
01823 h.scts = ast_tvnow();
01824 if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) {
01825 ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr);
01826 goto done;
01827 }
01828 if (h.smsc)
01829 ast_copy_string(h.oa, sms_args.addr, sizeof(h.oa));
01830 else {
01831 ast_copy_string(h.da, sms_args.addr, sizeof(h.da));
01832 ast_copy_string(h.oa, h.cli, sizeof(h.oa));
01833 }
01834 h.udl = 0;
01835 if (ast_strlen_zero(sms_args.body)) {
01836 ast_log(LOG_ERROR, "Missing body for %s\n", sms_args.addr);
01837 goto done;
01838 }
01839 up = (unsigned char *)sms_args.body;
01840 while (*up && h.udl < SMSLEN)
01841 h.ud[h.udl++] = utf8decode(&up);
01842 if (is7bit(h.dcs) && packsms7(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01843 ast_log(LOG_WARNING, "Invalid 7 bit GSM data\n");
01844 goto done;
01845 }
01846 if (is8bit(h.dcs) && packsms8(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01847 ast_log(LOG_WARNING, "Invalid 8 bit data\n");
01848 goto done;
01849 }
01850 if (is16bit(h.dcs) && packsms16(0, h.udhl, h.udh, h.udl, h.ud) < 0) {
01851 ast_log(LOG_WARNING, "Invalid 16 bit data\n");
01852 goto done;
01853 }
01854 h.rx = 0;
01855 h.mr = -1;
01856 sms_writefile(&h);
01857 res = h.err;
01858 goto done;
01859 }
01860
01861 if (ast_test_flag(&sms_flags, OPTION_ANSWER)) {
01862 h.framenumber = 1;
01863
01864 if (h.protocol == 2) {
01865 h.omsg[0] = DLL2_SMS_EST;
01866 h.omsg[1] = 0;
01867 } else {
01868 h.omsg[0] = DLL1_SMS_EST | DLL1_SMS_COMPLETE;
01869 h.omsg[1] = 0;
01870 }
01871 sms_messagetx(&h);
01872 }
01873
01874 if (chan->_state != AST_STATE_UP)
01875 ast_answer(chan);
01876
01877 res = ast_set_write_format(chan, __OUT_FMT);
01878 if (res >= 0)
01879 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
01880 if (res < 0) {
01881 ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n");
01882 goto done;
01883 }
01884
01885 if ( (res = ast_activate_generator(chan, &smsgen, &h)) < 0) {
01886 ast_log(LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
01887 goto done;
01888 }
01889
01890
01891 for (;;) {
01892 struct ast_frame *f;
01893 int i = ast_waitfor(chan, -1);
01894 if (i < 0) {
01895 ast_log(LOG_NOTICE, "waitfor failed\n");
01896 break;
01897 }
01898 if (h.hangup) {
01899 ast_log(LOG_NOTICE, "channel hangup\n");
01900 break;
01901 }
01902 f = ast_read(chan);
01903 if (!f) {
01904 ast_log(LOG_NOTICE, "ast_read failed\n");
01905 break;
01906 }
01907 if (f->frametype == AST_FRAME_VOICE) {
01908 sms_process(&h, f->samples, f->data);
01909 }
01910
01911 ast_frfree(f);
01912 }
01913 res = h.err;
01914
01915 sms_log(&h, '?');
01916 done:
01917 return (res);
01918 }
01919
01920 static int unload_module(void)
01921 {
01922 return ast_unregister_application(app);
01923 }
01924
01925 static int load_module(void)
01926 {
01927 #ifdef OUTALAW
01928 int p;
01929 for (p = 0; p < 80; p++)
01930 wavea[p] = AST_LIN2A (wave[p]);
01931 #endif
01932 snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR);
01933 return ast_register_application(app, sms_exec, synopsis, descrip);
01934 }
01935
01936 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SMS/PSTN handler");