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: 7634 $")
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 unsigned char waste[AST_FRIENDLY_OFFSET];
01182 #ifdef OUTALAW
01183 unsigned char buf[800];
01184 #else
01185 signed short buf[800];
01186 #endif
01187 sms_t *h = data;
01188 int i;
01189
01190 if (len > sizeof (buf)) {
01191 ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
01192 len = sizeof (buf);
01193 #ifdef OUTALAW
01194 samples = len;
01195 #else
01196 samples = len / 2;
01197 #endif
01198 }
01199 waste[0] = 0;
01200 f.frametype = AST_FRAME_VOICE;
01201 #ifdef OUTALAW
01202 f.subclass = AST_FORMAT_ALAW;
01203 f.datalen = samples;
01204 #else
01205 f.subclass = AST_FORMAT_SLINEAR;
01206 f.datalen = samples * 2;
01207 #endif
01208 f.offset = AST_FRIENDLY_OFFSET;
01209 f.mallocd = 0;
01210 f.data = buf;
01211 f.samples = samples;
01212 f.src = "app_sms";
01213
01214 for (i = 0; i < samples; i++) {
01215 #ifdef OUTALAW
01216 buf[i] = wavea[0];
01217 #else
01218 buf[i] = wave[0];
01219 #endif
01220 if (h->opause)
01221 h->opause--;
01222 else if (h->obyten || h->osync) {
01223 #ifdef OUTALAW
01224 buf[i] = wavea[h->ophase];
01225 #else
01226 buf[i] = wave[h->ophase];
01227 #endif
01228 if ((h->ophase += ((h->obyte & 1) ? 13 : 21)) >= 80)
01229 h->ophase -= 80;
01230 if ((h->ophasep += 12) >= 80) {
01231 h->ophasep -= 80;
01232 if (h->osync)
01233 h->osync--;
01234 else {
01235 h->obyte >>= 1;
01236 h->obitp++;
01237 if (h->obitp == 1)
01238 h->obyte = 0;
01239 else if (h->obitp == 2)
01240 h->obyte = h->omsg[h->obytep];
01241 else if (h->obitp == 10) {
01242 h->obyte = 1;
01243 h->obitp = 0;
01244 h->obytep++;
01245 if (h->obytep == h->obyten) {
01246 h->obytep = h->obyten = 0;
01247 h->osync = 10;
01248 }
01249 }
01250 }
01251 }
01252 }
01253 }
01254 if (ast_write (chan, &f) < 0) {
01255 ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror (errno));
01256 return -1;
01257 }
01258 return 0;
01259 }
01260
01261 static void sms_process (sms_t * h, int samples, signed short *data)
01262 {
01263 if (h->obyten || h->osync)
01264 return;
01265 while (samples--) {
01266 unsigned long long m0, m1;
01267 if (abs (*data) > h->imag)
01268 h->imag = abs (*data);
01269 else
01270 h->imag = h->imag * 7 / 8;
01271 if (h->imag > 500) {
01272 h->idle = 0;
01273 h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7;
01274 h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7;
01275 h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7;
01276 h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7;
01277 m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
01278 m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1;
01279 if ((h->ips0 += 21) >= 80)
01280 h->ips0 -= 80;
01281 if ((h->ipc0 += 21) >= 80)
01282 h->ipc0 -= 80;
01283 if ((h->ips1 += 13) >= 80)
01284 h->ips1 -= 80;
01285 if ((h->ipc1 += 13) >= 80)
01286 h->ipc1 -= 80;
01287 {
01288 char bit;
01289 h->ibith <<= 1;
01290 if (m1 > m0)
01291 h->ibith |= 1;
01292 if (h->ibith & 8)
01293 h->ibitt--;
01294 if (h->ibith & 1)
01295 h->ibitt++;
01296 bit = ((h->ibitt > 1) ? 1 : 0);
01297 if (bit != h->ibitl)
01298 h->ibitc = 1;
01299 else
01300 h->ibitc++;
01301 h->ibitl = bit;
01302 if (!h->ibitn && h->ibitc == 4 && !bit) {
01303 h->ibitn = 1;
01304 h->iphasep = 0;
01305 }
01306 if (bit && h->ibitc == 200) {
01307 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01308 }
01309 if (h->ibitn) {
01310 h->iphasep += 12;
01311 if (h->iphasep >= 80) {
01312 h->iphasep -= 80;
01313 if (h->ibitn++ == 9) {
01314 if (!bit)
01315 h->ierr = 0xFF;
01316 else {
01317 if (h->ibytep < sizeof (h->imsg)) {
01318 h->imsg[h->ibytep] = h->ibytev;
01319 h->ibytec += h->ibytev;
01320 h->ibytep++;
01321 } else if (h->ibytep == sizeof (h->imsg))
01322 h->ierr = 2;
01323 if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) {
01324 if (!h->ibytec)
01325 sms_messagerx (h);
01326 else
01327 h->ierr = 1;
01328 }
01329 }
01330 h->ibitn = 0;
01331 }
01332 h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0);
01333 }
01334 }
01335 }
01336 } else {
01337 if (h->idle++ == 80000) {
01338 ast_log (LOG_EVENT, "No data, hanging up\n");
01339 h->hangup = 1;
01340 h->err = 1;
01341 }
01342 if (h->ierr) {
01343 h->err = 1;
01344 h->omsg[0] = 0x92;
01345 h->omsg[1] = 1;
01346 h->omsg[2] = h->ierr;
01347 sms_messagetx (h);
01348 }
01349 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0;
01350 }
01351 data++;
01352 }
01353 }
01354
01355 static struct ast_generator smsgen = {
01356 alloc:sms_alloc,
01357 release:sms_release,
01358 generate:sms_generate,
01359 };
01360
01361 static int sms_exec (struct ast_channel *chan, void *data)
01362 {
01363 int res = -1;
01364 struct localuser *u;
01365 struct ast_frame *f;
01366 sms_t h = { 0 };
01367
01368 LOCAL_USER_ADD(u);
01369
01370 h.ipc0 = h.ipc1 = 20;
01371 h.dcs = 0xF1;
01372 if (!data) {
01373 ast_log (LOG_ERROR, "Requires queue name at least\n");
01374 LOCAL_USER_REMOVE(u);
01375 return -1;
01376 }
01377
01378 if (chan->cid.cid_num)
01379 ast_copy_string (h.cli, chan->cid.cid_num, sizeof (h.cli));
01380
01381 {
01382 unsigned char *p;
01383 unsigned char *d = data,
01384 answer = 0;
01385 if (!*d || *d == '|') {
01386 ast_log (LOG_ERROR, "Requires queue name\n");
01387 LOCAL_USER_REMOVE(u);
01388 return -1;
01389 }
01390 for (p = d; *p && *p != '|'; p++);
01391 if (p - d >= sizeof (h.queue)) {
01392 ast_log (LOG_ERROR, "Queue name too long\n");
01393 LOCAL_USER_REMOVE(u);
01394 return -1;
01395 }
01396 strncpy (h.queue, d, p - d);
01397 if (*p == '|')
01398 p++;
01399 d = p;
01400 for (p = h.queue; *p; p++)
01401 if (!isalnum (*p))
01402 *p = '-';
01403 while (*d && *d != '|') {
01404 switch (*d) {
01405 case 'a':
01406 answer = 1;
01407 break;
01408 case 's':
01409 h.smsc = 1;
01410 break;
01411
01412 case 'r':
01413 h.srr = 1;
01414 break;
01415 case 'o':
01416 h.dcs |= 4;
01417 break;
01418 case '1':
01419 case '2':
01420 case '3':
01421 case '4':
01422 case '5':
01423 case '6':
01424 case '7':
01425 h.pid = 0x40 + (*d & 0xF);
01426 break;
01427 }
01428 d++;
01429 }
01430 if (*d == '|') {
01431
01432
01433 d++;
01434 h.scts = time (0);
01435 for (p = d; *p && *p != '|'; p++);
01436 if (*p)
01437 *p++ = 0;
01438 if (strlen (d) >= sizeof (h.oa)) {
01439 ast_log (LOG_ERROR, "Address too long %s\n", d);
01440 return 0;
01441 }
01442 if (h.smsc) {
01443 ast_copy_string (h.oa, d, sizeof (h.oa));
01444 } else {
01445 ast_copy_string (h.da, d, sizeof (h.da));
01446 }
01447 if (!h.smsc)
01448 ast_copy_string (h.oa, h.cli, sizeof (h.oa));
01449 d = p;
01450 h.udl = 0;
01451 while (*p && h.udl < SMSLEN)
01452 h.ud[h.udl++] = utf8decode(&p);
01453 if (is7bit (h.dcs) && packsms7 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01454 ast_log (LOG_WARNING, "Invalid 7 bit GSM data\n");
01455 if (is8bit (h.dcs) && packsms8 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01456 ast_log (LOG_WARNING, "Invalid 8 bit data\n");
01457 if (is16bit (h.dcs) && packsms16 (0, h.udhl, h.udh, h.udl, h.ud) < 0)
01458 ast_log (LOG_WARNING, "Invalid 16 bit data\n");
01459 h.rx = 0;
01460 h.mr = -1;
01461 sms_writefile (&h);
01462 LOCAL_USER_REMOVE(u);
01463 return 0;
01464 }
01465
01466 if (answer) {
01467
01468 h.omsg[0] = 0x93;
01469 h.omsg[1] = 0;
01470 sms_messagetx (&h);
01471 }
01472 }
01473
01474 if (chan->_state != AST_STATE_UP)
01475 ast_answer (chan);
01476
01477 #ifdef OUTALAW
01478 res = ast_set_write_format (chan, AST_FORMAT_ALAW);
01479 #else
01480 res = ast_set_write_format (chan, AST_FORMAT_SLINEAR);
01481 #endif
01482 if (res >= 0)
01483 res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
01484 if (res < 0) {
01485 ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
01486 LOCAL_USER_REMOVE (u);
01487 return -1;
01488 }
01489
01490 if (ast_activate_generator (chan, &smsgen, &h) < 0) {
01491 ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
01492 LOCAL_USER_REMOVE (u);
01493 return -1;
01494 }
01495
01496
01497 while (ast_waitfor (chan, -1) > -1 && !h.hangup)
01498 {
01499 f = ast_read (chan);
01500 if (!f)
01501 break;
01502 if (f->frametype == AST_FRAME_VOICE) {
01503 sms_process (&h, f->samples, f->data);
01504 }
01505
01506 ast_frfree (f);
01507 }
01508
01509 sms_log (&h, '?');
01510
01511 LOCAL_USER_REMOVE (u);
01512 return (h.err);
01513 }
01514
01515 int unload_module (void)
01516 {
01517 int res;
01518
01519 res = ast_unregister_application (app);
01520
01521 STANDARD_HANGUP_LOCALUSERS;
01522
01523 return res;
01524 }
01525
01526 int load_module (void)
01527 {
01528 #ifdef OUTALAW
01529 {
01530 int p;
01531 for (p = 0; p < 80; p++)
01532 wavea[p] = AST_LIN2A (wave[p]);
01533 }
01534 #endif
01535 snprintf (log_file, sizeof (log_file), "%s/sms", ast_config_AST_LOG_DIR);
01536 snprintf (spool_dir, sizeof (spool_dir), "%s/sms", ast_config_AST_SPOOL_DIR);
01537 return ast_register_application (app, sms_exec, synopsis, descrip);
01538 }
01539
01540 char *description (void)
01541 {
01542 return tdesc;
01543 }
01544
01545 int usecount (void)
01546 {
01547 int res;
01548 STANDARD_USECOUNT (res);
01549 return res;
01550 }
01551
01552 char *key ()
01553 {
01554 return ASTERISK_GPL_KEY;
01555 }