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