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