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: 107461 $")
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 write (o, line, strlen (line));
00666 close (o);
00667 }
00668 *h->oa = *h->da = h->udl = 0;
00669 }
00670 }
00671
00672
00673 static void sms_readfile (sms_t * h, char *fn)
00674 {
00675 char line[1000];
00676 FILE *s;
00677 char dcsset = 0;
00678 ast_log (LOG_EVENT, "Sending %s\n", fn);
00679 h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
00680 h->mr = -1;
00681 h->dcs = 0xF1;
00682 h->scts = time (0);
00683 s = fopen (fn, "r");
00684 if (s)
00685 {
00686 if (unlink (fn))
00687 {
00688 fclose (s);
00689 return;
00690 }
00691 while (fgets (line, sizeof (line), s))
00692 {
00693 char *p;
00694 void *pp = &p;
00695 for (p = line; *p && *p != '\n' && *p != '\r'; p++);
00696 *p = 0;
00697 p = line;
00698 if (!*p || *p == ';')
00699 continue;
00700 while (isalnum (*p))
00701 {
00702 *p = tolower (*p);
00703 p++;
00704 }
00705 while (isspace (*p))
00706 *p++ = 0;
00707 if (*p == '=')
00708 {
00709 *p++ = 0;
00710 if (!strcmp (line, "ud"))
00711 {
00712 unsigned char o = 0;
00713 while (*p && o < SMSLEN)
00714 h->ud[o++] = utf8decode(pp);
00715 h->udl = o;
00716 if (*p)
00717 ast_log (LOG_WARNING, "UD too long in %s\n", fn);
00718 } else
00719 {
00720 while (isspace (*p))
00721 p++;
00722 if (!strcmp (line, "oa") && strlen (p) < sizeof (h->oa))
00723 numcpy (h->oa, p);
00724 else if (!strcmp (line, "da") && strlen (p) < sizeof (h->oa))
00725 numcpy (h->da, p);
00726 else if (!strcmp (line, "pid"))
00727 h->pid = atoi (p);
00728 else if (!strcmp (line, "dcs"))
00729 {
00730 h->dcs = atoi (p);
00731 dcsset = 1;
00732 } else if (!strcmp (line, "mr"))
00733 h->mr = atoi (p);
00734 else if (!strcmp (line, "srr"))
00735 h->srr = (atoi (p) ? 1 : 0);
00736 else if (!strcmp (line, "vp"))
00737 h->vp = atoi (p);
00738 else if (!strcmp (line, "rp"))
00739 h->rp = (atoi (p) ? 1 : 0);
00740 else if (!strcmp (line, "scts"))
00741 {
00742 int Y,
00743 m,
00744 d,
00745 H,
00746 M,
00747 S;
00748 if (sscanf (p, "%d-%d-%dT%d:%d:%d", &Y, &m, &d, &H, &M, &S) == 6)
00749 {
00750 struct tm t;
00751 t.tm_year = Y - 1900;
00752 t.tm_mon = m - 1;
00753 t.tm_mday = d;
00754 t.tm_hour = H;
00755 t.tm_min = M;
00756 t.tm_sec = S;
00757 t.tm_isdst = -1;
00758 h->scts = ast_mktime(&t, NULL);
00759 if (h->scts == (time_t) - 1)
00760 ast_log (LOG_WARNING, "Bad date/timein %s: %s", fn, p);
00761 }
00762 } else
00763 ast_log (LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
00764 }
00765 } else if (*p == '#')
00766 {
00767 *p++ = 0;
00768 if (*p == '#')
00769 {
00770 p++;
00771 if (!strcmp (line, "ud"))
00772 {
00773 int o = 0;
00774 while (*p && o < SMSLEN)
00775 {
00776 if (isxdigit (*p) && isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3]))
00777 {
00778 h->ud[o++] =
00779 (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 12) +
00780 (((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
00781 (((isalpha (p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha (p[3]) ? 9 : 0) + (p[3] & 0xF));
00782 p += 4;
00783 } else
00784 break;
00785 }
00786 h->udl = o;
00787 if (*p)
00788 ast_log (LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
00789 } else
00790 ast_log (LOG_WARNING, "Only ud can use ## format, %s\n", fn);
00791 } else if (!strcmp (line, "ud"))
00792 {
00793 int o = 0;
00794 while (*p && o < SMSLEN)
00795 {
00796 if (isxdigit (*p) && isxdigit (p[1]))
00797 {
00798 h->ud[o++] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
00799 p += 2;
00800 } else
00801 break;
00802 }
00803 h->udl = o;
00804 if (*p)
00805 ast_log (LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
00806 } else if (!strcmp (line, "udh"))
00807 {
00808 unsigned char o = 0;
00809 h->udhi = 1;
00810 while (*p && o < SMSLEN)
00811 {
00812 if (isxdigit (*p) && isxdigit (p[1]))
00813 {
00814 h->udh[o] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
00815 o++;
00816 p += 2;
00817 } else
00818 break;
00819 }
00820 h->udhl = o;
00821 if (*p)
00822 ast_log (LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
00823 } else
00824 ast_log (LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
00825 } else
00826 ast_log (LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
00827 }
00828 fclose (s);
00829 if (!dcsset && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00830 {
00831 if (packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00832 {
00833 if (packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00834 ast_log (LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
00835 else
00836 {
00837 h->dcs = 0x08;
00838 ast_log (LOG_WARNING, "Sending in 16 bit format (%s)\n", fn);
00839 }
00840 } else
00841 {
00842 h->dcs = 0xF5;
00843 ast_log (LOG_WARNING, "Sending in 8 bit format (%s)\n", fn);
00844 }
00845 }
00846 if (is7bit (h->dcs) && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00847 ast_log (LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
00848 if (is8bit (h->dcs) && packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00849 ast_log (LOG_WARNING, "Invalid 8 bit data %s\n", fn);
00850 if (is16bit (h->dcs) && packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00851 ast_log (LOG_WARNING, "Invalid 16 bit data %s\n", fn);
00852 }
00853 }
00854
00855
00856 static void sms_writefile (sms_t * h)
00857 {
00858 char fn[200] = "", fn2[200] = "";
00859 FILE *o;
00860 ast_copy_string (fn, spool_dir, sizeof (fn));
00861 mkdir (fn, 0777);
00862 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
00863 mkdir (fn, 0777);
00864 ast_copy_string (fn2, fn, sizeof (fn2));
00865 snprintf (fn2 + strlen (fn2), sizeof (fn2) - strlen (fn2), "/%s.%s-%d", h->queue, isodate (h->scts), seq++);
00866 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/.%s", fn2 + strlen (fn) + 1);
00867 o = fopen (fn, "w");
00868 if (o) {
00869 if (*h->oa)
00870 fprintf (o, "oa=%s\n", h->oa);
00871 if (*h->da)
00872 fprintf (o, "da=%s\n", h->da);
00873 if (h->udhi) {
00874 unsigned int p;
00875 fprintf (o, "udh#");
00876 for (p = 0; p < h->udhl; p++)
00877 fprintf (o, "%02X", h->udh[p]);
00878 fprintf (o, "\n");
00879 }
00880 if (h->udl) {
00881 unsigned int p;
00882 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00883 if (p < h->udl)
00884 fputc (';', o);
00885 fprintf (o, "ud=");
00886 for (p = 0; p < h->udl; p++) {
00887 unsigned short v = h->ud[p];
00888 if (v < 32)
00889 fputc (191, o);
00890 else if (v < 0x80)
00891 fputc (v, o);
00892 else if (v < 0x800)
00893 {
00894 fputc (0xC0 + (v >> 6), o);
00895 fputc (0x80 + (v & 0x3F), o);
00896 } else
00897 {
00898 fputc (0xE0 + (v >> 12), o);
00899 fputc (0x80 + ((v >> 6) & 0x3F), o);
00900 fputc (0x80 + (v & 0x3F), o);
00901 }
00902 }
00903 fprintf (o, "\n");
00904 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00905 if (p < h->udl) {
00906 for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
00907 if (p == h->udl) {
00908 fprintf (o, "ud#");
00909 for (p = 0; p < h->udl; p++)
00910 fprintf (o, "%02X", h->ud[p]);
00911 fprintf (o, "\n");
00912 } else {
00913 fprintf (o, "ud##");
00914 for (p = 0; p < h->udl; p++)
00915 fprintf (o, "%04X", h->ud[p]);
00916 fprintf (o, "\n");
00917 }
00918 }
00919 }
00920 if (h->scts)
00921 fprintf (o, "scts=%s\n", isodate (h->scts));
00922 if (h->pid)
00923 fprintf (o, "pid=%d\n", h->pid);
00924 if (h->dcs != 0xF1)
00925 fprintf (o, "dcs=%d\n", h->dcs);
00926 if (h->vp)
00927 fprintf (o, "vp=%d\n", h->vp);
00928 if (h->srr)
00929 fprintf (o, "srr=1\n");
00930 if (h->mr >= 0)
00931 fprintf (o, "mr=%d\n", h->mr);
00932 if (h->rp)
00933 fprintf (o, "rp=1\n");
00934 fclose (o);
00935 if (rename (fn, fn2))
00936 unlink (fn);
00937 else
00938 ast_log (LOG_EVENT, "Received to %s\n", fn2);
00939 }
00940 }
00941
00942
00943 static struct dirent *readdirqueue (DIR * d, char *queue)
00944 {
00945 struct dirent *f;
00946 do {
00947 f = readdir (d);
00948 } while (f && (*f->d_name == '.' || strncmp (f->d_name, queue, strlen (queue)) || f->d_name[strlen (queue)] != '.'));
00949 return f;
00950 }
00951
00952
00953 static unsigned char sms_handleincoming (sms_t * h)
00954 {
00955 unsigned char p = 3;
00956 if (h->smsc) {
00957 if ((h->imsg[2] & 3) == 1) {
00958 h->udhl = h->udl = 0;
00959 h->vp = 0;
00960 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
00961 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
00962 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
00963 ast_copy_string (h->oa, h->cli, sizeof (h->oa));
00964 h->scts = time (0);
00965 h->mr = h->imsg[p++];
00966 p += unpackaddress (h->da, h->imsg + p);
00967 h->pid = h->imsg[p++];
00968 h->dcs = h->imsg[p++];
00969 if ((h->imsg[2] & 0x18) == 0x10) {
00970 if (h->imsg[p] < 144)
00971 h->vp = (h->imsg[p] + 1) * 5;
00972 else if (h->imsg[p] < 168)
00973 h->vp = 720 + (h->imsg[p] - 143) * 30;
00974 else if (h->imsg[p] < 197)
00975 h->vp = (h->imsg[p] - 166) * 1440;
00976 else
00977 h->vp = (h->imsg[p] - 192) * 10080;
00978 p++;
00979 } else if (h->imsg[2] & 0x18)
00980 p += 7;
00981 p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
00982 h->rx = 1;
00983 sms_writefile (h);
00984 if (p != h->imsg[1] + 2) {
00985 ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
00986 return 0xFF;
00987 }
00988 } else {
00989 ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
00990 return 0xFF;
00991 }
00992 } else {
00993 if (!(h->imsg[2] & 3)) {
00994 *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
00995 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
00996 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
00997 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
00998 h->mr = -1;
00999 p += unpackaddress (h->oa, h->imsg + p);
01000 h->pid = h->imsg[p++];
01001 h->dcs = h->imsg[p++];
01002 h->scts = unpackdate (h->imsg + p);
01003 p += 7;
01004 p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
01005 h->rx = 1;
01006 sms_writefile (h);
01007 if (p != h->imsg[1] + 2) {
01008 ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
01009 return 0xFF;
01010 }
01011 } else {
01012 ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
01013 return 0xFF;
01014 }
01015 }
01016 return 0;
01017 }
01018
01019 #ifdef SOLARIS
01020 #define NAME_MAX 1024
01021 #endif
01022
01023
01024 static void sms_nextoutgoing (sms_t * h)
01025 {
01026 char fn[100 + NAME_MAX] = "";
01027 DIR *d;
01028 char more = 0;
01029 ast_copy_string (fn, spool_dir, sizeof (fn));
01030 mkdir (fn, 0777);
01031 h->rx = 0;
01032 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? "mttx" : "motx");
01033 mkdir (fn, 0777);
01034 d = opendir (fn);
01035 if (d) {
01036 struct dirent *f = readdirqueue (d, h->queue);
01037 if (f) {
01038 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", f->d_name);
01039 sms_readfile (h, fn);
01040 if (readdirqueue (d, h->queue))
01041 more = 1;
01042 }
01043 closedir (d);
01044 }
01045 if (*h->da || *h->oa) {
01046 unsigned char p = 2;
01047 h->omsg[0] = 0x91;
01048 if (h->smsc) {
01049 h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0);
01050 p += packaddress (h->omsg + p, h->oa);
01051 h->omsg[p++] = h->pid;
01052 h->omsg[p++] = h->dcs;
01053 packdate (h->omsg + p, h->scts);
01054 p += 7;
01055 p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01056 } else {
01057 h->omsg[p++] =
01058 0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0);
01059 if (h->mr < 0)
01060 h->mr = message_ref++;
01061 h->omsg[p++] = h->mr;
01062 p += packaddress (h->omsg + p, h->da);
01063 h->omsg[p++] = h->pid;
01064 h->omsg[p++] = h->dcs;
01065 if (h->vp) {
01066 if (h->vp < 720)
01067 h->omsg[p++] = (h->vp + 4) / 5 - 1;
01068 else if (h->vp < 1440)
01069 h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143;
01070 else if (h->vp < 43200)
01071 h->omsg[p++] = (h->vp + 1439) / 1440 + 166;
01072 else if (h->vp < 635040)
01073 h->omsg[p++] = (h->vp + 10079) / 10080 + 192;
01074 else
01075 h->omsg[p++] = 255;
01076 }
01077 p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud);
01078 }
01079 h->omsg[1] = p - 2;
01080 sms_messagetx (h);
01081 } else {
01082 h->omsg[0] = 0x94;
01083 h->omsg[1] = 0;
01084 sms_messagetx (h);
01085 }
01086 }
01087
01088 static void sms_debug (char *dir, unsigned char *msg)
01089 {
01090 char txt[259 * 3 + 1],
01091 *p = txt;
01092 int n = msg[1] + 3,
01093 q = 0;
01094 while (q < n && q < 30) {
01095 sprintf (p, " %02X", msg[q++]);
01096 p += 3;
01097 }
01098 if (q < n)
01099 sprintf (p, "...");
01100 if (option_verbose > 2)
01101 ast_verbose (VERBOSE_PREFIX_3 "SMS %s%s\n", dir, txt);
01102 }
01103
01104 static void sms_messagerx(sms_t * h)
01105 {
01106 sms_debug ("RX", h->imsg);
01107
01108 switch (h->imsg[0]) {
01109 case 0x91:
01110 {
01111 unsigned char cause = sms_handleincoming (h);
01112 if (!cause) {
01113 sms_log (h, 'Y');
01114 h->omsg[0] = 0x95;
01115 h->omsg[1] = 0x02;
01116 h->omsg[2] = 0x00;
01117 h->omsg[3] = 0x00;
01118 } else {
01119 sms_log (h, 'N');
01120 h->omsg[0] = 0x96;
01121 h->omsg[1] = 3;
01122 h->omsg[2] = 0;
01123 h->omsg[3] = cause;
01124 h->omsg[4] = 0;
01125 }
01126 sms_messagetx (h);
01127 }
01128 break;
01129 case 0x92:
01130 h->err = 1;
01131 sms_messagetx (h);
01132 break;
01133 case 0x93:
01134 sms_nextoutgoing (h);
01135 break;
01136 case 0x94:
01137 h->hangup = 1;
01138 break;
01139 case 0x95:
01140 sms_log (h, 'Y');
01141 sms_nextoutgoing (h);
01142 break;
01143 case 0x96:
01144 h->err = 1;
01145 sms_log (h, 'N');
01146 sms_nextoutgoing (h);
01147 break;
01148 default:
01149 h->omsg[0] = 0x92;
01150 h->omsg[1] = 1;
01151 h->omsg[2] = 3;
01152 sms_messagetx (h);
01153 break;
01154 }
01155 }
01156
01157 static void sms_messagetx(sms_t * h)
01158 {
01159 unsigned char c = 0, p;
01160 for (p = 0; p < h->omsg[1] + 2; p++)
01161 c += h->omsg[p];
01162 h->omsg[h->omsg[1] + 2] = 0 - c;
01163 sms_debug ("TX", h->omsg);
01164 h->obyte = 1;
01165 h->opause = 200;
01166 if (h->omsg[0] == 0x93)
01167 h->opause = 2400;
01168 h->obytep = 0;
01169 h->obitp = 0;
01170 h->osync = 80;
01171 h->obyten = h->omsg[1] + 3;
01172 }
01173
01174 static int sms_generate (struct ast_channel *chan, void *data, int len, int samples)
01175 {
01176 struct ast_frame f = { 0 };
01177 #define MAXSAMPLES (800)
01178 #ifdef OUTALAW
01179 unsigned char *buf;
01180 #else
01181 short *buf;
01182 #endif
01183 #define SAMPLE2LEN sizeof(*buf)
01184 sms_t *h = data;
01185 int i;
01186
01187 if (samples > MAXSAMPLES) {
01188 ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
01189 MAXSAMPLES, samples);
01190 samples = MAXSAMPLES;
01191 }
01192 len = samples * SAMPLE2LEN + AST_FRIENDLY_OFFSET;
01193 buf = alloca(len);
01194
01195 f.frametype = AST_FRAME_VOICE;
01196 #ifdef OUTALAW
01197 f.subclass = AST_FORMAT_ALAW;
01198 #else
01199 f.subclass = AST_FORMAT_SLINEAR;
01200 #endif
01201 f.datalen = samples * SAMPLE2LEN;
01202 f.offset = AST_FRIENDLY_OFFSET;
01203 f.mallocd = 0;
01204 f.data = buf;
01205 f.samples = samples;
01206 f.src = "app_sms";
01207
01208 for (i = 0; i < samples; i++) {
01209 #ifdef OUTALAW
01210 buf[i] = wavea[0];
01211 #else
01212 buf[i] = wave[0];
01213 #endif
01214 if (h->opause)
01215 h->opause--;
01216 else if (h->obyten || h->osync) {
01217 #ifdef OUTALAW
01218 buf[i] = wavea[h->ophase];
01219 #else
01220 buf[i] = wave[h->ophase];
01221 #endif
01222 if ((h->ophase += ((h->obyte & 1) ? 13 : 21)) >= 80)
01223 h->ophase -= 80;
01224 if ((h->ophasep += 12) >= 80) {
01225 h->ophasep -= 80;
01226 if (h->osync)
01227 h->osync--;
01228 else {
01229 h->obyte >>= 1;
01230 h->obitp++;
01231 if (h->obitp == 1)
01232 h->obyte = 0;
01233 else if (h->obitp == 2)
01234 h->obyte = h->omsg[h->obytep];
01235 else if (h->obitp == 10) {
01236 h->obyte = 1;
01237 h->obitp = 0;
01238 h->obytep++;
01239 if (h->obytep == h->obyten) {
01240 h->obytep = h->obyten = 0;
01241 h->osync = 10;
01242 }
01243 }
01244 }
01245 }
01246 }
01247 }
01248 if (ast_write (chan, &f) < 0) {
01249 ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror (errno));
01250 return -1;
01251 }
01252 return 0;
01253 #undef SAMPLE2LEN
01254 #undef MAXSAMPLES
01255 }
01256
01257 static void sms_process (sms_t * h, int samples, signed short *data)
01258 {
01259 if (h->obyten || h->osync)
01260 return;
01261 while (samples--) {
01262 unsigned long long m0, m1;
01263 if (abs (*data) > h->imag)
01264 h->imag = abs (*data);
01265 else
01266 h->imag = h->imag * 7 / 8;
01267 if (h->imag > 500) {
01268 h->idle = 0;
01269 h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
01270 h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
01271 h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
01272 h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
01273 m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
01274 m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
01275 if ((h->ips0 += 21) >= 80)
01276 h->ips0 -= 80;
01277 if ((h->ipc0 += 21) >= 80)
01278 h->ipc0 -= 80;
01279 if ((h->ips1 += 13) >= 80)
01280 h->ips1 -= 80;
01281 if ((h->ipc1 += 13) >= 80)
01282 h->ipc1 -= 80;
01283 {
01284 char bit;
01285 h->ibith <<= 1;
01286 if (m1 > m0)
01287 h->ibith |= 1;
01288 if (h->ibith & 8)
01289 h->ibitt--;
01290 if (h->ibith & 1)
01291 h->ibitt++;
01292 bit = ((h->ibitt > 1) ? 1 : 0);
01293 if (bit != h->ibitl)
01294 h->ibitc = 1;
01295 else
01296 h->ibitc++;
01297 h->ibitl = bit;
01298 if (!h->ibitn && h->ibitc == 4 && !bit) {
01299 h->ibitn = 1;
01300 h->iphasep = 0;
01301 }
01302 if (bit && h->ibitc == 200) {
01303 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01304 }
01305 if (h->ibitn) {
01306 h->iphasep += 12;
01307 if (h->iphasep >= 80) {
01308 h->iphasep -= 80;
01309 if (h->ibitn++ == 9) {
01310 if (!bit)
01311 h->ierr = 0xFF;
01312 else {
01313 if (h->ibytep < sizeof (h->imsg)) {
01314 h->imsg[h->ibytep] = h->ibytev;
01315 h->ibytec += h->ibytev;
01316 h->ibytep++;
01317 } else if (h->ibytep == sizeof (h->imsg))
01318 h->ierr = 2;
01319 if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
01320 if (!h->ibytec)
01321 sms_messagerx (h);
01322 else
01323 h->ierr = 1;
01324 }
01325 }
01326 h->ibitn = 0;
01327 }
01328 h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
01329 }
01330 }
01331 }
01332 } else {
01333 if (h->idle++ == 80000) {
01334 ast_log (LOG_EVENT, "No data, hanging up\n");
01335 h->hangup = 1;
01336 h->err = 1;
01337 }
01338 if (h->ierr) {
01339 h->err = 1;
01340 h->omsg[0] = 0x92;
01341 h->omsg[1] = 1;
01342 h->omsg[2] = h->ierr;
01343 sms_messagetx (h);
01344 }
01345 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01346 }
01347 data++;
01348 }
01349 }
01350
01351 static struct ast_generator smsgen = {
01352 alloc:sms_alloc,
01353 release:sms_release,
01354 generate:sms_generate,
01355 };
01356
01357 static int sms_exec (struct ast_channel *chan, void *data)
01358 {
01359 int res = -1;
01360 struct ast_module_user *u;
01361 struct ast_frame *f;
01362 sms_t h = { 0 };
01363
01364 u = ast_module_user_add(chan);
01365
01366 h.ipc0 = h.ipc1 = 20;
01367 h.dcs = 0xF1;
01368 if (!data) {
01369 ast_log (LOG_ERROR, "Requires queue name at least\n");
01370 ast_module_user_remove(u);
01371 return -1;
01372 }
01373
01374 if (chan->cid.cid_num)
01375 ast_copy_string (h.cli, chan->cid.cid_num, sizeof (h.cli));
01376
01377 {
01378 unsigned char *p;
01379 unsigned char *d = data,
01380 answer = 0;
01381 if (!*d || *d == '|') {
01382 ast_log (LOG_ERROR, "Requires queue name\n");
01383 ast_module_user_remove(u);
01384 return -1;
01385 }
01386 for (p = d; *p && *p != '|'; p++);
01387 if (p - d >= sizeof (h.queue)) {
01388 ast_log (LOG_ERROR, "Queue name too long\n");
01389 ast_module_user_remove(u);
01390 return -1;
01391 }
01392 strncpy(h.queue, (char *)d, p - d);
01393 if (*p == '|')
01394 p++;
01395 d = p;
01396 for (p = (unsigned char *)h.queue; *p; p++)
01397 if (!isalnum (*p))
01398 *p = '-';
01399 while (*d && *d != '|') {
01400 switch (*d) {
01401 case 'a':
01402 answer = 1;
01403 break;
01404 case 's':
01405 h.smsc = 1;
01406 break;
01407
01408 case 'r':
01409 h.srr = 1;
01410 break;
01411 case 'o':
01412 h.dcs |= 4;
01413 break;
01414 case '1':
01415 case '2':
01416 case '3':
01417 case '4':
01418 case '5':
01419 case '6':
01420 case '7':
01421 h.pid = 0x40 + (*d & 0xF);
01422 break;
01423 }
01424 d++;
01425 }
01426 if (*d == '|') {
01427
01428
01429 d++;
01430 h.scts = time (0);
01431 for (p = d; *p && *p != '|'; p++);
01432 if (*p)
01433 *p++ = 0;
01434 if (strlen ((char *)d) >= sizeof (h.oa)) {
01435 ast_log (LOG_ERROR, "Address too long %s\n", d);
01436 return 0;
01437 }
01438 if (h.smsc) {
01439 ast_copy_string (h.oa, (char *)d, sizeof (h.oa));
01440 } else {
01441 ast_copy_string (h.da, (char *)d, sizeof (h.da));
01442 }
01443 if (!h.smsc)
01444 ast_copy_string (h.oa, h.cli, sizeof (h.oa));
01445 d = p;
01446 h.udl = 0;
01447 while (*p && h.udl < SMSLEN)
01448 h.ud[h.udl++] = utf8decode(&p);
01449 if (is7bit (h.dcs) && packsms7 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01450 ast_log (LOG_WARNING, "Invalid 7 bit GSM data\n");
01451 if (is8bit (h.dcs) && packsms8 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01452 ast_log (LOG_WARNING, "Invalid 8 bit data\n");
01453 if (is16bit (h.dcs) && packsms16 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01454 ast_log (LOG_WARNING, "Invalid 16 bit data\n");
01455 h.rx = 0;
01456 h.mr = -1;
01457 sms_writefile (&h);
01458 ast_module_user_remove(u);
01459 return 0;
01460 }
01461
01462 if (answer) {
01463
01464 h.omsg[0] = 0x93;
01465 h.omsg[1] = 0;
01466 sms_messagetx (&h);
01467 }
01468 }
01469
01470 if (chan->_state != AST_STATE_UP)
01471 ast_answer (chan);
01472
01473 #ifdef OUTALAW
01474 res = ast_set_write_format (chan, AST_FORMAT_ALAW);
01475 #else
01476 res = ast_set_write_format (chan, AST_FORMAT_SLINEAR);
01477 #endif
01478 if (res >= 0)
01479 res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
01480 if (res < 0) {
01481 ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
01482 ast_module_user_remove(u);
01483 return -1;
01484 }
01485
01486 if (ast_activate_generator (chan, &smsgen, &h) < 0) {
01487 ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
01488 ast_module_user_remove(u);
01489 return -1;
01490 }
01491
01492
01493 while (ast_waitfor (chan, -1) > -1 && !h.hangup)
01494 {
01495 f = ast_read (chan);
01496 if (!f)
01497 break;
01498 if (f->frametype == AST_FRAME_VOICE) {
01499 sms_process (&h, f->samples, f->data);
01500 }
01501
01502 ast_frfree (f);
01503 }
01504
01505 sms_log (&h, '?');
01506
01507 ast_module_user_remove(u);
01508 return (h.err);
01509 }
01510
01511 static int unload_module(void)
01512 {
01513 int res;
01514
01515 res = ast_unregister_application (app);
01516
01517 ast_module_user_hangup_all();
01518
01519 return res;
01520 }
01521
01522 static int load_module(void)
01523 {
01524 #ifdef OUTALAW
01525 {
01526 int p;
01527 for (p = 0; p < 80; p++)
01528 wavea[p] = AST_LIN2A (wave[p]);
01529 }
01530 #endif
01531 snprintf (log_file, sizeof (log_file), "%s/sms", ast_config_AST_LOG_DIR);
01532 snprintf (spool_dir, sizeof (spool_dir), "%s/sms", ast_config_AST_SPOOL_DIR);
01533 return ast_register_application (app, sms_exec, synopsis, descrip);
01534 }
01535
01536 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SMS/PSTN handler");