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 #include "asterisk.h"
00026
00027 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 289424 $")
00028
00029 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <unistd.h>
00033 #include <errno.h>
00034 #include <dirent.h>
00035 #include <ctype.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038
00039 #include "asterisk/lock.h"
00040 #include "asterisk/file.h"
00041 #include "asterisk/logger.h"
00042 #include "asterisk/options.h"
00043 #include "asterisk/channel.h"
00044 #include "asterisk/pbx.h"
00045 #include "asterisk/module.h"
00046 #include "asterisk/alaw.h"
00047 #include "asterisk/callerid.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 static volatile unsigned char message_ref;
00059 static volatile unsigned int seq;
00060
00061 static char log_file[255];
00062 static char spool_dir[255];
00063
00064 static char *app = "SMS";
00065
00066 static char *synopsis = "Communicates with SMS service centres and SMS capable analogue phones";
00067
00068 static char *descrip =
00069 " SMS(name|[a][s]): SMS handles exchange of SMS data with a call to/from SMS capabale\n"
00070 "phone or SMS PSTN service center. Can send and/or receive SMS messages.\n"
00071 "Works to ETSI ES 201 912 compatible with BT SMS PSTN service in UK\n"
00072 "Typical usage is to use to handle called from the SMS service centre CLI,\n"
00073 "or to set up a call using 'outgoing' or manager interface to connect\n"
00074 "service centre to SMS()\n"
00075 "name is the name of the queue used in /var/spool/asterisk/sms\n"
00076 "Arguments:\n"
00077 " a: answer, i.e. send initial FSK packet.\n"
00078 " s: act as service centre talking to a phone.\n"
00079 "Messages are processed as per text file message queues.\n"
00080 "smsq (a separate software) is a command to generate message\n"
00081 "queues and send messages.\n";
00082
00083 static signed short wave[] = {
00084 0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
00085 5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
00086 0, -392, -782, -1167,
00087 -1545, -1913, -2270, -2612, -2939, -3247, -3536, -3802, -4045, -4263, -4455, -4619, -4755, -4862, -4938, -4985, -5000,
00088 -4985, -4938, -4862,
00089 -4755, -4619, -4455, -4263, -4045, -3802, -3536, -3247, -2939, -2612, -2270, -1913, -1545, -1167, -782, -392
00090 };
00091
00092 #ifdef OUTALAW
00093 static unsigned char wavea[80];
00094 #endif
00095
00096
00097
00098 static const unsigned short defaultalphabet[] = {
00099 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
00100 0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
00101 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
00102 0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
00103 ' ', '!', '"', '#', 164, '%', '&', 39, '(', ')', '*', '+', ',', '-', '.', '/',
00104 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
00105 161, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
00106 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 196, 214, 209, 220, 167,
00107 191, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
00108 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 228, 246, 241, 252, 224,
00109 };
00110
00111 static const unsigned short escapes[] = {
00112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x000C, 0, 0, 0, 0, 0,
00113 0, 0, 0, 0, 0x005E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00114 0, 0, 0, 0, 0, 0, 0, 0, 0x007B, 0x007D, 0, 0, 0, 0, 0, 0x005C,
00115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x005B, 0x007E, 0x005D, 0,
00116 0x007C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00118 0, 0, 0, 0, 0, 0x20AC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00120 };
00121
00122 #define SMSLEN 160
00123
00124 typedef struct sms_s
00125 {
00126 unsigned char hangup;
00127 unsigned char err;
00128 unsigned char smsc:1;
00129 unsigned char rx:1;
00130 char queue[30];
00131 char oa[20];
00132 char da[20];
00133 time_t scts;
00134 unsigned char pid;
00135 unsigned char dcs;
00136 short mr;
00137 int udl;
00138 int udhl;
00139 unsigned char srr:1;
00140 unsigned char udhi:1;
00141 unsigned char rp:1;
00142 unsigned int vp;
00143 unsigned short ud[SMSLEN];
00144 unsigned char udh[SMSLEN];
00145 char cli[20];
00146 unsigned char ophase;
00147 unsigned char ophasep;
00148 unsigned char obyte;
00149 unsigned int opause;
00150 unsigned char obitp;
00151 unsigned char osync;
00152 unsigned char obytep;
00153 unsigned char obyten;
00154 unsigned char omsg[256];
00155 unsigned char imsg[200];
00156 signed long long ims0,
00157 imc0,
00158 ims1,
00159 imc1;
00160 unsigned int idle;
00161 unsigned short imag;
00162 unsigned char ips0,
00163 ips1,
00164 ipc0,
00165 ipc1;
00166 unsigned char ibitl;
00167 unsigned char ibitc;
00168 unsigned char iphasep;
00169 unsigned char ibitn;
00170 unsigned char ibytev;
00171 unsigned char ibytep;
00172 unsigned char ibytec;
00173 unsigned char ierr;
00174 unsigned char ibith;
00175 unsigned char ibitt;
00176
00177 } sms_t;
00178
00179
00180 #define is7bit(dcs) (((dcs)&0xC0)?(!((dcs)&4)):(!((dcs)&12)))
00181 #define is8bit(dcs) (((dcs)&0xC0)?(((dcs)&4)):(((dcs)&12)==4))
00182 #define is16bit(dcs) (((dcs)&0xC0)?0:(((dcs)&12)==8))
00183
00184 static void *sms_alloc (struct ast_channel *chan, void *params)
00185 {
00186 return params;
00187 }
00188
00189 static void sms_release (struct ast_channel *chan, void *data)
00190 {
00191 return;
00192 }
00193
00194 static void sms_messagetx (sms_t * h);
00195
00196
00197 static void numcpy (char *d, char *s)
00198 {
00199 if (*s == '+')
00200 *d++ = *s++;
00201 while (*s) {
00202 if (isdigit (*s))
00203 *d++ = *s;
00204 s++;
00205 }
00206 *d = 0;
00207 }
00208
00209
00210 static char * isodate (time_t t)
00211 {
00212 static char date[20];
00213 strftime (date, sizeof (date), "%Y-%m-%dT%H:%M:%S", localtime (&t));
00214 return date;
00215 }
00216
00217
00218
00219
00220 static long utf8decode (unsigned char **pp)
00221 {
00222 unsigned char *p = *pp;
00223 if (!*p)
00224 return 0;
00225 (*pp)++;
00226 if (*p < 0xC0)
00227 return *p;
00228 if (*p < 0xE0) {
00229 if (*p < 0xC2 || (p[1] & 0xC0) != 0x80)
00230 return *p;
00231 (*pp)++;
00232 return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
00233 }
00234 if (*p < 0xF0) {
00235 if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80)
00236 return *p;
00237 (*pp) += 2;
00238 return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
00239 }
00240 if (*p < 0xF8) {
00241 if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80)
00242 return *p;
00243 (*pp) += 3;
00244 return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
00245 }
00246 if (*p < 0xFC) {
00247 if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00248 || (p[4] & 0xC0) != 0x80)
00249 return *p;
00250 (*pp) += 4;
00251 return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
00252 }
00253 if (*p < 0xFE) {
00254 if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00255 || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80)
00256 return *p;
00257 (*pp) += 5;
00258 return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
00259 }
00260 return *p;
00261 }
00262
00263
00264
00265
00266
00267 static int packsms7 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00268 {
00269 unsigned char p = 0, b = 0, n = 0;
00270
00271 if (udhl) {
00272 if (o)
00273 o[p++] = udhl;
00274 b = 1;
00275 n = 1;
00276 while (udhl--) {
00277 if (o)
00278 o[p++] = *udh++;
00279 b += 8;
00280 while (b >= 7) {
00281 b -= 7;
00282 n++;
00283 }
00284 if (n >= SMSLEN)
00285 return n;
00286 }
00287 if (b) {
00288 b = 7 - b;
00289 if (++n >= SMSLEN)
00290 return n;
00291 };
00292 }
00293 if (o)
00294 o[p] = 0;
00295
00296 while (udl--) {
00297 long u;
00298 unsigned char v;
00299 u = *ud++;
00300 for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
00301 if (v == 128 && u && n + 1 < SMSLEN) {
00302 for (v = 0; v < 128 && escapes[v] != u; v++);
00303 if (v < 128) {
00304 if (o)
00305 o[p] |= (27 << b);
00306 b += 7;
00307 if (b >= 8) {
00308 b -= 8;
00309 p++;
00310 if (o)
00311 o[p] = (27 >> (7 - b));
00312 }
00313 n++;
00314 }
00315 }
00316 if (v == 128)
00317 return -1;
00318 if (o)
00319 o[p] |= (v << b);
00320 b += 7;
00321 if (b >= 8) {
00322 b -= 8;
00323 p++;
00324 if (o)
00325 o[p] = (v >> (7 - b));
00326 }
00327 if (++n >= SMSLEN)
00328 return n;
00329 }
00330 return n;
00331 }
00332
00333
00334
00335
00336
00337 static int packsms8 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00338 {
00339 unsigned char p = 0;
00340
00341
00342 if (udhl) {
00343 if (o)
00344 o[p++] = udhl;
00345 while (udhl--) {
00346 if (o)
00347 o[p++] = *udh++;
00348 if (p >= 140)
00349 return p;
00350 }
00351 }
00352 while (udl--) {
00353 long u;
00354 u = *ud++;
00355 if (u < 0 || u > 0xFF)
00356 return -1;
00357 if (o)
00358 o[p++] = u;
00359 if (p >= 140)
00360 return p;
00361 }
00362 return p;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 static int packsms16 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00374 {
00375 unsigned char p = 0;
00376
00377 if (udhl) {
00378 if (o)
00379 o[p++] = udhl;
00380 while (udhl--) {
00381 if (o)
00382 o[p++] = *udh++;
00383 if (p >= 140)
00384 return p;
00385 }
00386 }
00387 while (udl--) {
00388 long u;
00389 u = *ud++;
00390 if (o)
00391 o[p++] = (u >> 8);
00392 if (p >= 140)
00393 return p - 1;
00394 if (o)
00395 o[p++] = u;
00396 if (p >= 140)
00397 return p;
00398 }
00399 return p;
00400 }
00401
00402
00403
00404 static int packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
00405 {
00406 unsigned char *p = base;
00407 if (udl) {
00408 int l = 0;
00409 if (is7bit (dcs)) {
00410 l = packsms7 (p + 1, udhl, udh, udl, ud);
00411 if (l < 0)
00412 l = 0;
00413 *p++ = l;
00414 p += (l * 7 + 7) / 8;
00415 } else if (is8bit (dcs)) {
00416 l = packsms8 (p + 1, udhl, udh, udl, ud);
00417 if (l < 0)
00418 l = 0;
00419 *p++ = l;
00420 p += l;
00421 } else {
00422 l = packsms16 (p + 1, udhl, udh, udl, ud);
00423 if (l < 0)
00424 l = 0;
00425 *p++ = l;
00426 p += l;
00427 }
00428 } else
00429 *p++ = 0;
00430 return p - base;
00431 }
00432
00433
00434
00435 static void packdate (unsigned char *o, time_t w)
00436 {
00437 struct tm *t = localtime (&w);
00438 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
00439 int z = -t->tm_gmtoff / 60 / 15;
00440 #else
00441 int z = timezone / 60 / 15;
00442 #endif
00443 *o++ = ((t->tm_year % 10) << 4) + (t->tm_year % 100) / 10;
00444 *o++ = (((t->tm_mon + 1) % 10) << 4) + (t->tm_mon + 1) / 10;
00445 *o++ = ((t->tm_mday % 10) << 4) + t->tm_mday / 10;
00446 *o++ = ((t->tm_hour % 10) << 4) + t->tm_hour / 10;
00447 *o++ = ((t->tm_min % 10) << 4) + t->tm_min / 10;
00448 *o++ = ((t->tm_sec % 10) << 4) + t->tm_sec / 10;
00449 if (z < 0)
00450 *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
00451 else
00452 *o++ = ((z % 10) << 4) + z / 10;
00453 }
00454
00455
00456 static time_t unpackdate (unsigned char *i)
00457 {
00458 struct tm t;
00459 t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
00460 t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
00461 t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
00462 t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
00463 t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
00464 t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
00465 t.tm_isdst = 0;
00466 if (i[6] & 0x08)
00467 t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00468 else
00469 t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00470 return ast_mktime(&t, NULL);
00471 }
00472
00473
00474
00475
00476 static void unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00477 {
00478 unsigned char b = 0, p = 0;
00479 unsigned short *o = ud;
00480 *udhl = 0;
00481 if (udhi && l) {
00482 int h = i[p];
00483 *udhl = h;
00484 if (h) {
00485 b = 1;
00486 p++;
00487 l--;
00488 while (h-- && l) {
00489 *udh++ = i[p++];
00490 b += 8;
00491 while (b >= 7) {
00492 b -= 7;
00493 l--;
00494 if (!l)
00495 break;
00496 }
00497 }
00498
00499 if (b) {
00500 b = 7 - b;
00501 l--;
00502 }
00503 }
00504 }
00505 while (l--) {
00506 unsigned char v;
00507 if (b < 2)
00508 v = ((i[p] >> b) & 0x7F);
00509 else
00510 v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
00511 b += 7;
00512 if (b >= 8) {
00513 b -= 8;
00514 p++;
00515 }
00516 if (o > ud && o[-1] == 0x00A0 && escapes[v])
00517 o[-1] = escapes[v];
00518 else
00519 *o++ = defaultalphabet[v];
00520 }
00521 *udl = (o - ud);
00522 }
00523
00524
00525
00526
00527 static void unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00528 {
00529 unsigned short *o = ud;
00530 *udhl = 0;
00531 if (udhi) {
00532 int n = *i;
00533 *udhl = n;
00534 if (n) {
00535 i++;
00536 l--;
00537 while (l && n) {
00538 l--;
00539 n--;
00540 *udh++ = *i++;
00541 }
00542 }
00543 }
00544 while (l--)
00545 *o++ = *i++;
00546 *udl = (o - ud);
00547 }
00548
00549
00550
00551
00552 static void unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00553 {
00554 unsigned short *o = ud;
00555 *udhl = 0;
00556 if (udhi) {
00557 int n = *i;
00558 *udhl = n;
00559 if (n) {
00560 i++;
00561 l--;
00562 while (l && n) {
00563 l--;
00564 n--;
00565 *udh++ = *i++;
00566 }
00567 }
00568 }
00569 while (l--) {
00570 int v = *i++;
00571 if (l--)
00572 v = (v << 8) + *i++;
00573 *o++ = v;
00574 }
00575 *udl = (o - ud);
00576 }
00577
00578
00579 static int unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00580 {
00581 int l = *i++;
00582 if (is7bit (dcs)) {
00583 unpacksms7 (i, l, udh, udhl, ud, udl, udhi);
00584 l = (l * 7 + 7) / 8;
00585 } else if (is8bit (dcs))
00586 unpacksms8 (i, l, udh, udhl, ud, udl, udhi);
00587 else
00588 unpacksms16 (i, l, udh, udhl, ud, udl, udhi);
00589 return l + 1;
00590 }
00591
00592
00593 static unsigned char unpackaddress (char *o, unsigned char *i)
00594 {
00595 unsigned char l = i[0],
00596 p;
00597 if (i[1] == 0x91)
00598 *o++ = '+';
00599 for (p = 0; p < l; p++) {
00600 if (p & 1)
00601 *o++ = (i[2 + p / 2] >> 4) + '0';
00602 else
00603 *o++ = (i[2 + p / 2] & 0xF) + '0';
00604 }
00605 *o = 0;
00606 return (l + 5) / 2;
00607 }
00608
00609
00610 static unsigned char packaddress (unsigned char *o, char *i)
00611 {
00612 unsigned char p = 2;
00613 o[0] = 0;
00614 if (*i == '+') {
00615 i++;
00616 o[1] = 0x91;
00617 } else
00618 o[1] = 0x81;
00619 while (*i)
00620 if (isdigit (*i)) {
00621 if (o[0] & 1)
00622 o[p++] |= ((*i & 0xF) << 4);
00623 else
00624 o[p] = (*i & 0xF);
00625 o[0]++;
00626 i++;
00627 } else
00628 i++;
00629 if (o[0] & 1)
00630 o[p++] |= 0xF0;
00631 return p;
00632 }
00633
00634
00635 static void sms_log (sms_t * h, char status)
00636 {
00637 if (*h->oa || *h->da) {
00638 int o = open (log_file, O_CREAT | O_APPEND | O_WRONLY, 0666);
00639 if (o >= 0) {
00640 char line[1000], mrs[3] = "", *p;
00641 unsigned char n;
00642
00643 if (h->mr >= 0)
00644 snprintf (mrs, sizeof (mrs), "%02X", h->mr);
00645 snprintf (line, sizeof (line), "%s %c%c%c%s %s %s %s ",
00646 isodate (time (0)), status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue, *h->oa ? h->oa : "-",
00647 *h->da ? h->da : "-");
00648 p = line + strlen (line);
00649 for (n = 0; n < h->udl; n++)
00650 if (h->ud[n] == '\\') {
00651 *p++ = '\\';
00652 *p++ = '\\';
00653 } else if (h->ud[n] == '\n') {
00654 *p++ = '\\';
00655 *p++ = 'n';
00656 } else if (h->ud[n] == '\r') {
00657 *p++ = '\\';
00658 *p++ = 'r';
00659 } else if (h->ud[n] < 32 || h->ud[n] == 127)
00660 *p++ = 191;
00661 else
00662 *p++ = h->ud[n];
00663 *p++ = '\n';
00664 *p = 0;
00665 if (write (o, line, strlen (line)) < 0) {
00666 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00667 }
00668 close (o);
00669 }
00670 *h->oa = *h->da = h->udl = 0;
00671 }
00672 }
00673
00674
00675 static void sms_readfile (sms_t * h, char *fn)
00676 {
00677 char line[1000];
00678 FILE *s;
00679 char dcsset = 0;
00680 ast_log (LOG_EVENT, "Sending %s\n", fn);
00681 h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
00682 h->mr = -1;
00683 h->dcs = 0xF1;
00684 h->scts = time (0);
00685 s = fopen (fn, "r");
00686 if (s)
00687 {
00688 if (unlink (fn))
00689 {
00690 fclose (s);
00691 return;
00692 }
00693 while (fgets (line, sizeof (line), s))
00694 {
00695 char *p;
00696 void *pp = &p;
00697 for (p = line; *p && *p != '\n' && *p != '\r'; p++);
00698 *p = 0;
00699 p = line;
00700 if (!*p || *p == ';')
00701 continue;
00702 while (isalnum (*p))
00703 {
00704 *p = tolower (*p);
00705 p++;
00706 }
00707 while (isspace (*p))
00708 *p++ = 0;
00709 if (*p == '=')
00710 {
00711 *p++ = 0;
00712 if (!strcmp (line, "ud"))
00713 {
00714 unsigned char o = 0;
00715 while (*p && o < SMSLEN)
00716 h->ud[o++] = utf8decode(pp);
00717 h->udl = o;
00718 if (*p)
00719 ast_log (LOG_WARNING, "UD too long in %s\n", fn);
00720 } else
00721 {
00722 while (isspace (*p))
00723 p++;
00724 if (!strcmp (line, "oa") && strlen (p) < sizeof (h->oa))
00725 numcpy (h->oa, p);
00726 else if (!strcmp (line, "da") && strlen (p) < sizeof (h->oa))
00727 numcpy (h->da, p);
00728 else if (!strcmp (line, "pid"))
00729 h->pid = atoi (p);
00730 else if (!strcmp (line, "dcs"))
00731 {
00732 h->dcs = atoi (p);
00733 dcsset = 1;
00734 } else if (!strcmp (line, "mr"))
00735 h->mr = atoi (p);
00736 else if (!strcmp (line, "srr"))
00737 h->srr = (atoi (p) ? 1 : 0);
00738 else if (!strcmp (line, "vp"))
00739 h->vp = atoi (p);
00740 else if (!strcmp (line, "rp"))
00741 h->rp = (atoi (p) ? 1 : 0);
00742 else if (!strcmp (line, "scts"))
00743 {
00744 int Y,
00745 m,
00746 d,
00747 H,
00748 M,
00749 S;
00750 if (sscanf (p, "%30d-%30d-%30dT%30d:%30d:%30d", &Y, &m, &d, &H, &M, &S) == 6)
00751 {
00752 struct tm t;
00753 t.tm_year = Y - 1900;
00754 t.tm_mon = m - 1;
00755 t.tm_mday = d;
00756 t.tm_hour = H;
00757 t.tm_min = M;
00758 t.tm_sec = S;
00759 t.tm_isdst = -1;
00760 h->scts = ast_mktime(&t, NULL);
00761 if (h->scts == (time_t) - 1)
00762 ast_log (LOG_WARNING, "Bad date/timein %s: %s", fn, p);
00763 }
00764 } else
00765 ast_log (LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
00766 }
00767 } else if (*p == '#')
00768 {
00769 *p++ = 0;
00770 if (*p == '#')
00771 {
00772 p++;
00773 if (!strcmp (line, "ud"))
00774 {
00775 int o = 0;
00776 while (*p && o < SMSLEN)
00777 {
00778 if (isxdigit (*p) && isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3]))
00779 {
00780 h->ud[o++] =
00781 (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 12) +
00782 (((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
00783 (((isalpha (p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha (p[3]) ? 9 : 0) + (p[3] & 0xF));
00784 p += 4;
00785 } else
00786 break;
00787 }
00788 h->udl = o;
00789 if (*p)
00790 ast_log (LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
00791 } else
00792 ast_log (LOG_WARNING, "Only ud can use ## format, %s\n", fn);
00793 } else if (!strcmp (line, "ud"))
00794 {
00795 int o = 0;
00796 while (*p && o < SMSLEN)
00797 {
00798 if (isxdigit (*p) && isxdigit (p[1]))
00799 {
00800 h->ud[o++] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
00801 p += 2;
00802 } else
00803 break;
00804 }
00805 h->udl = o;
00806 if (*p)
00807 ast_log (LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
00808 } else if (!strcmp (line, "udh"))
00809 {
00810 unsigned char o = 0;
00811 h->udhi = 1;
00812 while (*p && o < SMSLEN)
00813 {
00814 if (isxdigit (*p) && isxdigit (p[1]))
00815 {
00816 h->udh[o] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
00817 o++;
00818 p += 2;
00819 } else
00820 break;
00821 }
00822 h->udhl = o;
00823 if (*p)
00824 ast_log (LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
00825 } else
00826 ast_log (LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
00827 } else
00828 ast_log (LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
00829 }
00830 fclose (s);
00831 if (!dcsset && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00832 {
00833 if (packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00834 {
00835 if (packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00836 ast_log (LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
00837 else
00838 {
00839 h->dcs = 0x08;
00840 ast_log (LOG_WARNING, "Sending in 16 bit format (%s)\n", fn);
00841 }
00842 } else
00843 {
00844 h->dcs = 0xF5;
00845 ast_log (LOG_WARNING, "Sending in 8 bit format (%s)\n", fn);
00846 }
00847 }
00848 if (is7bit (h->dcs) && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00849 ast_log (LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
00850 if (is8bit (h->dcs) && packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00851 ast_log (LOG_WARNING, "Invalid 8 bit data %s\n", fn);
00852 if (is16bit (h->dcs) && packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00853 ast_log (LOG_WARNING, "Invalid 16 bit data %s\n", fn);
00854 }
00855 }
00856
00857
00858 static void sms_writefile (sms_t * h)
00859 {
00860 char fn[200] = "", fn2[200] = "";
00861 FILE *o;
00862 ast_copy_string (fn, spool_dir, sizeof (fn));
00863 mkdir (fn, 0777);
00864 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
00865 mkdir (fn, 0777);
00866 ast_copy_string (fn2, fn, sizeof (fn2));
00867 snprintf (fn2 + strlen (fn2), sizeof (fn2) - strlen (fn2), "/%s.%s-%d", h->queue, isodate (h->scts), seq++);
00868 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/.%s", fn2 + strlen (fn) + 1);
00869 o = fopen (fn, "w");
00870 if (o) {
00871 if (*h->oa)
00872 fprintf (o, "oa=%s\n", h->oa);
00873 if (*h->da)
00874 fprintf (o, "da=%s\n", h->da);
00875 if (h->udhi) {
00876 unsigned int p;
00877 fprintf (o, "udh#");
00878 for (p = 0; p < h->udhl; p++)
00879 fprintf (o, "%02X", h->udh[p]);
00880 fprintf (o, "\n");
00881 }
00882 if (h->udl) {
00883 unsigned int p;
00884 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00885 if (p < h->udl)
00886 fputc (';', o);
00887 fprintf (o, "ud=");
00888 for (p = 0; p < h->udl; p++) {
00889 unsigned short v = h->ud[p];
00890 if (v < 32)
00891 fputc (191, o);
00892 else if (v < 0x80)
00893 fputc (v, o);
00894 else if (v < 0x800)
00895 {
00896 fputc (0xC0 + (v >> 6), o);
00897 fputc (0x80 + (v & 0x3F), o);
00898 } else
00899 {
00900 fputc (0xE0 + (v >> 12), o);
00901 fputc (0x80 + ((v >> 6) & 0x3F), o);
00902 fputc (0x80 + (v & 0x3F), o);
00903 }
00904 }
00905 fprintf (o, "\n");
00906 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00907 if (p < h->udl) {
00908 for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
00909 if (p == h->udl) {
00910 fprintf (o, "ud#");
00911 for (p = 0; p < h->udl; p++)
00912 fprintf (o, "%02X", h->ud[p]);
00913 fprintf (o, "\n");
00914 } else {
00915 fprintf (o, "ud##");
00916 for (p = 0; p < h->udl; p++)
00917 fprintf (o, "%04X", h->ud[p]);
00918 fprintf (o, "\n");
00919 }
00920 }
00921 }
00922 if (h->scts)
00923 fprintf (o, "scts=%s\n", isodate (h->scts));
00924 if (h->pid)
00925 fprintf (o, "pid=%d\n", h->pid);
00926 if (h->dcs != 0xF1)
00927 fprintf (o, "dcs=%d\n", h->dcs);
00928 if (h->vp)
00929 fprintf (o, "vp=%d\n", h->vp);
00930 if (h->srr)
00931 fprintf (o, "srr=1\n");
00932 if (h->mr >= 0)
00933 fprintf (o, "mr=%d\n", h->mr);
00934 if (h->rp)
00935 fprintf (o, "rp=1\n");
00936 fclose (o);
00937 if (rename (fn, fn2))
00938 unlink (fn);
00939 else
00940 ast_log (LOG_EVENT, "Received to %s\n", fn2);
00941 }
00942 }
00943
00944
00945 static struct dirent *readdirqueue (DIR * d, char *queue)
00946 {
00947 struct dirent *f;
00948 do {
00949 f = readdir (d);
00950 } while (f && (*f->d_name == '.' || strncmp (f->d_name, queue, strlen (queue)) || f->d_name[strlen (queue)] != '.'));
00951 return f;
00952 }
00953
00954
00955 static unsigned char sms_handleincoming (sms_t * h)
00956 {
00957 unsigned char p = 3;
00958 if (h->smsc) {
00959 if ((h->imsg[2] & 3) == 1) {
00960 h->udhl = h->udl = 0;
00961 h->vp = 0;
00962 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
00963 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
00964 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
00965 ast_copy_string (h->oa, h->cli, sizeof (h->oa));
00966 h->scts = time (0);
00967 h->mr = h->imsg[p++];
00968 p += unpackaddress (h->da, h->imsg + p);
00969 h->pid = h->imsg[p++];
00970 h->dcs = h->imsg[p++];
00971 if ((h->imsg[2] & 0x18) == 0x10) {
00972 if (h->imsg[p] < 144)
00973 h->vp = (h->imsg[p] + 1) * 5;
00974 else if (h->imsg[p] < 168)
00975 h->vp = 720 + (h->imsg[p] - 143) * 30;
00976 else if (h->imsg[p] < 197)
00977 h->vp = (h->imsg[p] - 166) * 1440;
00978 else
00979 h->vp = (h->imsg[p] - 192) * 10080;
00980 p++;
00981 } else if (h->imsg[2] & 0x18)
00982 p += 7;
00983 p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
00984 h->rx = 1;
00985 sms_writefile (h);
00986 if (p != h->imsg[1] + 2) {
00987 ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
00988 return 0xFF;
00989 }
00990 } else {
00991 ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
00992 return 0xFF;
00993 }
00994 } else {
00995 if (!(h->imsg[2] & 3)) {
00996 *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
00997 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
00998 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
00999 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
01000 h->mr = -1;
01001 p += unpackaddress (h->oa, h->imsg + p);
01002 h->pid = h->imsg[p++];
01003 h->dcs = h->imsg[p++];
01004 h->scts = unpackdate (h->imsg + p);
01005 p += 7;
01006 p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01007 h->rx = 1;
01008 sms_writefile (h);
01009 if (p != h->imsg[1] + 2) {
01010 ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01011 return 0xFF;
01012 }
01013 } else {
01014 ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
01015 return 0xFF;
01016 }
01017 }
01018 return 0;
01019 }
01020
01021 #ifdef SOLARIS
01022 #define NAME_MAX 1024
01023 #endif
01024
01025
01026 static void sms_nextoutgoing (sms_t * h)
01027 {
01028 char fn[100 + NAME_MAX] = "";
01029 DIR *d;
01030 char more = 0;
01031 ast_copy_string (fn, spool_dir, sizeof (fn));
01032 mkdir (fn, 0777);
01033 h->rx = 0;
01034 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? "mttx" : "motx");
01035 mkdir (fn, 0777);
01036 d = opendir (fn);
01037 if (d) {
01038 struct dirent *f = readdirqueue (d, h->queue);
01039 if (f) {
01040 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", f->d_name);
01041 sms_readfile (h, fn);
01042 if (readdirqueue (d, h->queue))
01043 more = 1;
01044 }
01045 closedir (d);
01046 }
01047 if (*h->da || *h->oa) {
01048 unsigned char p = 2;
01049 h->omsg[0] = 0x91;
01050 if (h->smsc) {
01051 h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
01052 p += packaddress (h->omsg + p, h->oa);
01053 h->omsg[p++] = h->pid;
01054 h->omsg[p++] = h->dcs;
01055 packdate (h->omsg + p, h->scts);
01056 p += 7;
01057 p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01058 } else {
01059 h->omsg[p++] =
01060 0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
01061 if (h->mr < 0)
01062 h->mr = message_ref++;
01063 h->omsg[p++] = h->mr;
01064 p += packaddress (h->omsg + p, h->da);
01065 h->omsg[p++] = h->pid;
01066 h->omsg[p++] = h->dcs;
01067 if (h->vp) {
01068 if (h->vp < 720)
01069 h->omsg[p++] = (h->vp + 4) / 5 - 1;
01070 else if (h->vp < 1440)
01071 h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
01072 else if (h->vp < 43200)
01073 h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
01074 else if (h->vp < 635040)
01075 h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
01076 else
01077 h->omsg[p++] = 255;
01078 }
01079 p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01080 }
01081 h->omsg[1] = p - 2;
01082 sms_messagetx (h);
01083 } else {
01084 h->omsg[0] = 0x94;
01085 h->omsg[1] = 0;
01086 sms_messagetx (h);
01087 }
01088 }
01089
01090 static void sms_debug (char *dir, unsigned char *msg)
01091 {
01092 char txt[259 * 3 + 1],
01093 *p = txt;
01094 int n = msg[1] + 3,
01095 q = 0;
01096 while (q < n && q < 30) {
01097 sprintf (p, " %02X", msg[q++]);
01098 p += 3;
01099 }
01100 if (q < n)
01101 sprintf (p, "...");
01102 if (option_verbose > 2)
01103 ast_verbose (VERBOSE_PREFIX_3 "SMS %s%s\n", dir, txt);
01104 }
01105
01106 static void sms_messagerx(sms_t * h)
01107 {
01108 sms_debug ("RX", h->imsg);
01109
01110 switch (h->imsg[0]) {
01111 case 0x91:
01112 {
01113 unsigned char cause = sms_handleincoming (h);
01114 if (!cause) {
01115 sms_log (h, 'Y');
01116 h->omsg[0] = 0x95;
01117 h->omsg[1] = 0x02;
01118 h->omsg[2] = 0x00;
01119 h->omsg[3] = 0x00;
01120 } else {
01121 sms_log (h, 'N');
01122 h->omsg[0] = 0x96;
01123 h->omsg[1] = 3;
01124 h->omsg[2] = 0;
01125 h->omsg[3] = cause;
01126 h->omsg[4] = 0;
01127 }
01128 sms_messagetx (h);
01129 }
01130 break;
01131 case 0x92:
01132 h->err = 1;
01133 sms_messagetx (h);
01134 break;
01135 case 0x93:
01136 sms_nextoutgoing (h);
01137 break;
01138 case 0x94:
01139 h->hangup = 1;
01140 break;
01141 case 0x95:
01142 sms_log (h, 'Y');
01143 sms_nextoutgoing (h);
01144 break;
01145 case 0x96:
01146 h->err = 1;
01147 sms_log (h, 'N');
01148 sms_nextoutgoing (h);
01149 break;
01150 default:
01151 h->omsg[0] = 0x92;
01152 h->omsg[1] = 1;
01153 h->omsg[2] = 3;
01154 sms_messagetx (h);
01155 break;
01156 }
01157 }
01158
01159 static void sms_messagetx(sms_t * h)
01160 {
01161 unsigned char c = 0, p;
01162 for (p = 0; p < h->omsg[1] + 2; p++)
01163 c += h->omsg[p];
01164 h->omsg[h->omsg[1] + 2] = 0 - c;
01165 sms_debug ("TX", h->omsg);
01166 h->obyte = 1;
01167 h->opause = 200;
01168 if (h->omsg[0] == 0x93)
01169 h->opause = 2400;
01170 h->obytep = 0;
01171 h->obitp = 0;
01172 h->osync = 80;
01173 h->obyten = h->omsg[1] + 3;
01174 }
01175
01176 static int sms_generate (struct ast_channel *chan, void *data, int len, int samples)
01177 {
01178 struct ast_frame f = { 0 };
01179 #define MAXSAMPLES (800)
01180 #ifdef OUTALAW
01181 unsigned char *buf;
01182 #else
01183 short *buf;
01184 #endif
01185 #define SAMPLE2LEN sizeof(*buf)
01186 sms_t *h = data;
01187 int i;
01188
01189 if (samples > MAXSAMPLES) {
01190 ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
01191 MAXSAMPLES, samples);
01192 samples = MAXSAMPLES;
01193 }
01194 len = samples * SAMPLE2LEN + AST_FRIENDLY_OFFSET;
01195 buf = alloca(len);
01196
01197 f.frametype = AST_FRAME_VOICE;
01198 #ifdef OUTALAW
01199 f.subclass = AST_FORMAT_ALAW;
01200 #else
01201 f.subclass = AST_FORMAT_SLINEAR;
01202 #endif
01203 f.datalen = samples * SAMPLE2LEN;
01204 f.offset = AST_FRIENDLY_OFFSET;
01205 f.mallocd = 0;
01206 f.data = buf;
01207 f.samples = samples;
01208 f.src = "app_sms";
01209
01210 for (i = 0; i < samples; i++) {
01211 #ifdef OUTALAW
01212 buf[i] = wavea[0];
01213 #else
01214 buf[i] = wave[0];
01215 #endif
01216 if (h->opause)
01217 h->opause--;
01218 else if (h->obyten || h->osync) {
01219 #ifdef OUTALAW
01220 buf[i] = wavea[h->ophase];
01221 #else
01222 buf[i] = wave[h->ophase];
01223 #endif
01224 if ((h->ophase += ((h->obyte & 1) ? 13 : 21)) >= 80)
01225 h->ophase -= 80;
01226 if ((h->ophasep += 12) >= 80) {
01227 h->ophasep -= 80;
01228 if (h->osync)
01229 h->osync--;
01230 else {
01231 h->obyte >>= 1;
01232 h->obitp++;
01233 if (h->obitp == 1)
01234 h->obyte = 0;
01235 else if (h->obitp == 2)
01236 h->obyte = h->omsg[h->obytep];
01237 else if (h->obitp == 10) {
01238 h->obyte = 1;
01239 h->obitp = 0;
01240 h->obytep++;
01241 if (h->obytep == h->obyten) {
01242 h->obytep = h->obyten = 0;
01243 h->osync = 10;
01244 }
01245 }
01246 }
01247 }
01248 }
01249 }
01250 if (ast_write (chan, &f) < 0) {
01251 ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror (errno));
01252 return -1;
01253 }
01254 return 0;
01255 #undef SAMPLE2LEN
01256 #undef MAXSAMPLES
01257 }
01258
01259 static void sms_process (sms_t * h, int samples, signed short *data)
01260 {
01261 if (h->obyten || h->osync)
01262 return;
01263 while (samples--) {
01264 unsigned long long m0, m1;
01265 if (abs (*data) > h->imag)
01266 h->imag = abs (*data);
01267 else
01268 h->imag = h->imag * 7 / 8;
01269 if (h->imag > 500) {
01270 h->idle = 0;
01271 h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
01272 h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
01273 h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
01274 h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
01275 m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
01276 m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
01277 if ((h->ips0 += 21) >= 80)
01278 h->ips0 -= 80;
01279 if ((h->ipc0 += 21) >= 80)
01280 h->ipc0 -= 80;
01281 if ((h->ips1 += 13) >= 80)
01282 h->ips1 -= 80;
01283 if ((h->ipc1 += 13) >= 80)
01284 h->ipc1 -= 80;
01285 {
01286 char bit;
01287 h->ibith <<= 1;
01288 if (m1 > m0)
01289 h->ibith |= 1;
01290 if (h->ibith & 8)
01291 h->ibitt--;
01292 if (h->ibith & 1)
01293 h->ibitt++;
01294 bit = ((h->ibitt > 1) ? 1 : 0);
01295 if (bit != h->ibitl)
01296 h->ibitc = 1;
01297 else
01298 h->ibitc++;
01299 h->ibitl = bit;
01300 if (!h->ibitn && h->ibitc == 4 && !bit) {
01301 h->ibitn = 1;
01302 h->iphasep = 0;
01303 }
01304 if (bit && h->ibitc == 200) {
01305 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01306 }
01307 if (h->ibitn) {
01308 h->iphasep += 12;
01309 if (h->iphasep >= 80) {
01310 h->iphasep -= 80;
01311 if (h->ibitn++ == 9) {
01312 if (!bit)
01313 h->ierr = 0xFF;
01314 else {
01315 if (h->ibytep < sizeof (h->imsg)) {
01316 h->imsg[h->ibytep] = h->ibytev;
01317 h->ibytec += h->ibytev;
01318 h->ibytep++;
01319 } else if (h->ibytep == sizeof (h->imsg))
01320 h->ierr = 2;
01321 if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
01322 if (!h->ibytec)
01323 sms_messagerx (h);
01324 else
01325 h->ierr = 1;
01326 }
01327 }
01328 h->ibitn = 0;
01329 }
01330 h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
01331 }
01332 }
01333 }
01334 } else {
01335 if (h->idle++ == 80000) {
01336 ast_log (LOG_EVENT, "No data, hanging up\n");
01337 h->hangup = 1;
01338 h->err = 1;
01339 }
01340 if (h->ierr) {
01341 h->err = 1;
01342 h->omsg[0] = 0x92;
01343 h->omsg[1] = 1;
01344 h->omsg[2] = h->ierr;
01345 sms_messagetx (h);
01346 }
01347 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01348 }
01349 data++;
01350 }
01351 }
01352
01353 static struct ast_generator smsgen = {
01354 alloc:sms_alloc,
01355 release:sms_release,
01356 generate:sms_generate,
01357 };
01358
01359 static int sms_exec (struct ast_channel *chan, void *data)
01360 {
01361 int res = -1;
01362 struct ast_module_user *u;
01363 struct ast_frame *f;
01364 sms_t h = { 0 };
01365
01366 u = ast_module_user_add(chan);
01367
01368 h.ipc0 = h.ipc1 = 20;
01369 h.dcs = 0xF1;
01370 if (!data) {
01371 ast_log (LOG_ERROR, "Requires queue name at least\n");
01372 ast_module_user_remove(u);
01373 return -1;
01374 }
01375
01376 if (chan->cid.cid_num)
01377 ast_copy_string (h.cli, chan->cid.cid_num, sizeof (h.cli));
01378
01379 {
01380 unsigned char *p;
01381 unsigned char *d = data,
01382 answer = 0;
01383 if (!*d || *d == '|') {
01384 ast_log (LOG_ERROR, "Requires queue name\n");
01385 ast_module_user_remove(u);
01386 return -1;
01387 }
01388 for (p = d; *p && *p != '|'; p++);
01389 if (p - d >= sizeof (h.queue)) {
01390 ast_log (LOG_ERROR, "Queue name too long\n");
01391 ast_module_user_remove(u);
01392 return -1;
01393 }
01394 strncpy(h.queue, (char *)d, p - d);
01395 if (*p == '|')
01396 p++;
01397 d = p;
01398 for (p = (unsigned char *)h.queue; *p; p++)
01399 if (!isalnum (*p))
01400 *p = '-';
01401 while (*d && *d != '|') {
01402 switch (*d) {
01403 case 'a':
01404 answer = 1;
01405 break;
01406 case 's':
01407 h.smsc = 1;
01408 break;
01409
01410 case 'r':
01411 h.srr = 1;
01412 break;
01413 case 'o':
01414 h.dcs |= 4;
01415 break;
01416 case '1':
01417 case '2':
01418 case '3':
01419 case '4':
01420 case '5':
01421 case '6':
01422 case '7':
01423 h.pid = 0x40 + (*d & 0xF);
01424 break;
01425 }
01426 d++;
01427 }
01428 if (*d == '|') {
01429
01430
01431 d++;
01432 h.scts = time (0);
01433 for (p = d; *p && *p != '|'; p++);
01434 if (*p)
01435 *p++ = 0;
01436 if (strlen ((char *)d) >= sizeof (h.oa)) {
01437 ast_log (LOG_ERROR, "Address too long %s\n", d);
01438 return 0;
01439 }
01440 if (h.smsc) {
01441 ast_copy_string (h.oa, (char *)d, sizeof (h.oa));
01442 } else {
01443 ast_copy_string (h.da, (char *)d, sizeof (h.da));
01444 }
01445 if (!h.smsc)
01446 ast_copy_string (h.oa, h.cli, sizeof (h.oa));
01447 d = p;
01448 h.udl = 0;
01449 while (*p && h.udl < SMSLEN)
01450 h.ud[h.udl++] = utf8decode(&p);
01451 if (is7bit (h.dcs) && packsms7 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01452 ast_log (LOG_WARNING, "Invalid 7 bit GSM data\n");
01453 if (is8bit (h.dcs) && packsms8 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01454 ast_log (LOG_WARNING, "Invalid 8 bit data\n");
01455 if (is16bit (h.dcs) && packsms16 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01456 ast_log (LOG_WARNING, "Invalid 16 bit data\n");
01457 h.rx = 0;
01458 h.mr = -1;
01459 sms_writefile (&h);
01460 ast_module_user_remove(u);
01461 return 0;
01462 }
01463
01464 if (answer) {
01465
01466 h.omsg[0] = 0x93;
01467 h.omsg[1] = 0;
01468 sms_messagetx (&h);
01469 }
01470 }
01471
01472 if (chan->_state != AST_STATE_UP)
01473 ast_answer (chan);
01474
01475 #ifdef OUTALAW
01476 res = ast_set_write_format (chan, AST_FORMAT_ALAW);
01477 #else
01478 res = ast_set_write_format (chan, AST_FORMAT_SLINEAR);
01479 #endif
01480 if (res >= 0)
01481 res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
01482 if (res < 0) {
01483 ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
01484 ast_module_user_remove(u);
01485 return -1;
01486 }
01487
01488 if (ast_activate_generator (chan, &smsgen, &h) < 0) {
01489 ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
01490 ast_module_user_remove(u);
01491 return -1;
01492 }
01493
01494
01495 while (ast_waitfor (chan, -1) > -1 && !h.hangup)
01496 {
01497 f = ast_read (chan);
01498 if (!f)
01499 break;
01500 if (f->frametype == AST_FRAME_VOICE) {
01501 sms_process (&h, f->samples, f->data);
01502 }
01503
01504 ast_frfree (f);
01505 }
01506
01507 sms_log (&h, '?');
01508
01509
01510
01511
01512
01513 ast_deactivate_generator(chan);
01514
01515 ast_module_user_remove(u);
01516 return (h.err);
01517 }
01518
01519 static int unload_module(void)
01520 {
01521 int res;
01522
01523 res = ast_unregister_application (app);
01524
01525 ast_module_user_hangup_all();
01526
01527 return res;
01528 }
01529
01530 static int load_module(void)
01531 {
01532 #ifdef OUTALAW
01533 {
01534 int p;
01535 for (p = 0; p < 80; p++)
01536 wavea[p] = AST_LIN2A (wave[p]);
01537 }
01538 #endif
01539 snprintf (log_file, sizeof (log_file), "%s/sms", ast_config_AST_LOG_DIR);
01540 snprintf (spool_dir, sizeof (spool_dir), "%s/sms", ast_config_AST_SPOOL_DIR);
01541 return ast_register_application (app, sms_exec, synopsis, descrip);
01542 }
01543
01544 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SMS/PSTN handler");