#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
Go to the source code of this file.
Data Structures | |
struct | sms_s |
Defines | |
#define | is16bit(dcs) (((dcs)&0xC0)?0:(((dcs)&12)==8)) |
#define | is7bit(dcs) (((dcs)&0xC0)?(!((dcs)&4)):(!((dcs)&12))) |
#define | is8bit(dcs) (((dcs)&0xC0)?(((dcs)&4)):(((dcs)&12)==4)) |
#define | MAXSAMPLES (800) |
#define | SAMPLE2LEN sizeof(*buf) |
#define | SMSLEN 160 |
Typedefs | |
typedef sms_s | sms_t |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static char * | isodate (time_t t) |
static, return a date/time in ISO format | |
static int | load_module (void) |
static void | numcpy (char *d, char *s) |
copy number, skipping non digits apart from leading + | |
static unsigned char | packaddress (unsigned char *o, char *i) |
store an address at o, and return number of bytes used | |
static void | packdate (unsigned char *o, time_t w) |
pack a date and return | |
static int | packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud) |
general pack, with length and data, returns number of bytes of target used | |
static int | packsms16 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud) |
takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 16 bit UCS-2 character codes The return value is the number of bytes packed in to o, which is internally limited to 140 o can be null, in which case this is used to validate or count only if the input contains invalid characters then the return value is -1 | |
static int | packsms7 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud) |
takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using SMS 7 bit character codes | |
static int | packsms8 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud) |
takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 8 bit character codes | |
static struct dirent * | readdirqueue (DIR *d, char *queue) |
read dir skipping dot files... | |
static void * | sms_alloc (struct ast_channel *chan, void *params) |
static void | sms_debug (char *dir, unsigned char *msg) |
static int | sms_exec (struct ast_channel *chan, void *data) |
static int | sms_generate (struct ast_channel *chan, void *data, int len, int samples) |
static unsigned char | sms_handleincoming (sms_t *h) |
handle the incoming message | |
static void | sms_log (sms_t *h, char status) |
Log the output, and remove file. | |
static void | sms_messagerx (sms_t *h) |
static void | sms_messagetx (sms_t *h) |
static void | sms_nextoutgoing (sms_t *h) |
find and fill in next message, or send a REL if none waiting | |
static void | sms_process (sms_t *h, int samples, signed short *data) |
static void | sms_readfile (sms_t *h, char *fn) |
parse and delete a file | |
static void | sms_release (struct ast_channel *chan, void *data) |
static void | sms_writefile (sms_t *h) |
white a received text message to a file | |
static int | unload_module (void) |
static unsigned char | unpackaddress (char *o, unsigned char *i) |
unpack an address from i, return byte length, unpack to o | |
static time_t | unpackdate (unsigned char *i) |
unpack a date and return | |
static int | unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi) |
general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length | |
static void | unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi) |
unpacks bytes (16 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set | |
static void | unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi) |
unpacks bytes (7 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set | |
static void | unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi) |
unpacks bytes (8 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set | |
static long | utf8decode (unsigned char **pp) |
reads next UCS character from null terminated UTF-8 string and advanced pointer | |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "SMS/PSTN handler" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } |
static char * | app = "SMS" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static const unsigned short | defaultalphabet [] |
static char * | descrip |
static const unsigned short | escapes [] |
static char | log_file [255] |
static volatile unsigned char | message_ref |
static volatile unsigned int | seq |
static struct ast_generator | smsgen |
static char | spool_dir [255] |
static char * | synopsis = "Communicates with SMS service centres and SMS capable analogue phones" |
static signed short | wave [] |
Definition in file app_sms.c.
#define is16bit | ( | dcs | ) | (((dcs)&0xC0)?0:(((dcs)&12)==8)) |
#define is7bit | ( | dcs | ) | (((dcs)&0xC0)?(!((dcs)&4)):(!((dcs)&12))) |
#define is8bit | ( | dcs | ) | (((dcs)&0xC0)?(((dcs)&4)):(((dcs)&12)==4)) |
#define MAXSAMPLES (800) |
Referenced by sms_generate().
#define SAMPLE2LEN sizeof(*buf) |
Referenced by sms_generate().
#define SMSLEN 160 |
static char* isodate | ( | time_t | t | ) | [static] |
static, return a date/time in ISO format
Definition at line 210 of file app_sms.c.
Referenced by sms_log(), and sms_writefile().
00211 { 00212 static char date[20]; 00213 strftime (date, sizeof (date), "%Y-%m-%dT%H:%M:%S", localtime (&t)); 00214 return date; 00215 }
static int load_module | ( | void | ) | [static] |
Definition at line 1530 of file app_sms.c.
References ast_config_AST_LOG_DIR, ast_config_AST_SPOOL_DIR, AST_LIN2A, ast_register_application(), and sms_exec().
01531 { 01532 #ifdef OUTALAW 01533 { 01534 int p; 01535 for (p = 0; p < 80; p++) 01536 wavea[p] = AST_LIN2A (wave[p]); 01537 } 01538 #endif 01539 snprintf (log_file, sizeof (log_file), "%s/sms", ast_config_AST_LOG_DIR); 01540 snprintf (spool_dir, sizeof (spool_dir), "%s/sms", ast_config_AST_SPOOL_DIR); 01541 return ast_register_application (app, sms_exec, synopsis, descrip); 01542 }
static void numcpy | ( | char * | d, | |
char * | s | |||
) | [static] |
static unsigned char packaddress | ( | unsigned char * | o, | |
char * | i | |||
) | [static] |
store an address at o, and return number of bytes used
Definition at line 610 of file app_sms.c.
Referenced by sms_nextoutgoing().
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; /* pad */ 00631 return p; 00632 }
static void packdate | ( | unsigned char * | o, | |
time_t | w | |||
) | [static] |
pack a date and return
Definition at line 435 of file app_sms.c.
References t.
Referenced by sms_nextoutgoing().
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 }
static int packsms | ( | unsigned char | dcs, | |
unsigned char * | base, | |||
unsigned int | udhl, | |||
unsigned char * | udh, | |||
int | udl, | |||
unsigned short * | ud | |||
) | [static] |
general pack, with length and data, returns number of bytes of target used
Definition at line 404 of file app_sms.c.
References is7bit, is8bit, packsms16(), packsms7(), and packsms8().
Referenced by sms_nextoutgoing().
00405 { 00406 unsigned char *p = base; 00407 if (udl) { 00408 int l = 0; 00409 if (is7bit (dcs)) { /* 7 bit */ 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)) { /* 8 bit */ 00416 l = packsms8 (p + 1, udhl, udh, udl, ud); 00417 if (l < 0) 00418 l = 0; 00419 *p++ = l; 00420 p += l; 00421 } else { /* UCS-2 */ 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; /* no user data */ 00430 return p - base; 00431 }
static int packsms16 | ( | unsigned char * | o, | |
int | udhl, | |||
unsigned char * | udh, | |||
int | udl, | |||
unsigned short * | ud | |||
) | [static] |
takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 16 bit UCS-2 character codes The return value is the number of bytes packed in to o, which is internally limited to 140 o can be null, in which case this is used to validate or count only if the input contains invalid characters then the return value is -1
Definition at line 373 of file app_sms.c.
Referenced by packsms(), and sms_readfile().
00374 { 00375 unsigned char p = 0; 00376 /* header - no encoding */ 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; /* could not fit last character */ 00394 if (o) 00395 o[p++] = u; 00396 if (p >= 140) 00397 return p; 00398 } 00399 return p; 00400 }
static int packsms7 | ( | unsigned char * | o, | |
int | udhl, | |||
unsigned char * | udh, | |||
int | udl, | |||
unsigned short * | ud | |||
) | [static] |
takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using SMS 7 bit character codes
Definition at line 267 of file app_sms.c.
References SMSLEN.
Referenced by packsms(), and sms_readfile().
00268 { 00269 unsigned char p = 0, b = 0, n = 0; 00270 00271 if (udhl) { /* header */ 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 }; /* filling to septet boundary */ 00292 } 00293 if (o) 00294 o[p] = 0; 00295 /* message */ 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) { /* escaped sequence */ 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; /* invalid character */ 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 }
static int packsms8 | ( | unsigned char * | o, | |
int | udhl, | |||
unsigned char * | udh, | |||
int | udl, | |||
unsigned short * | ud | |||
) | [static] |
takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 8 bit character codes
Definition at line 337 of file app_sms.c.
Referenced by packsms(), and sms_readfile().
00338 { 00339 unsigned char p = 0; 00340 00341 /* header - no encoding */ 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; /* not valid */ 00357 if (o) 00358 o[p++] = u; 00359 if (p >= 140) 00360 return p; 00361 } 00362 return p; 00363 }
static struct dirent* readdirqueue | ( | DIR * | d, | |
char * | queue | |||
) | [static] |
read dir skipping dot files...
Definition at line 945 of file app_sms.c.
References f.
Referenced by sms_nextoutgoing().
00946 { 00947 struct dirent *f; 00948 do { 00949 f = readdir (d); 00950 } while (f && (*f->d_name == '.' || strncmp (f->d_name, queue, strlen (queue)) || f->d_name[strlen (queue)] != '.')); 00951 return f; 00952 }
static void* sms_alloc | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
static void sms_debug | ( | char * | dir, | |
unsigned char * | msg | |||
) | [static] |
Definition at line 1090 of file app_sms.c.
References ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.
Referenced by sms_messagerx(), and sms_messagetx().
01091 { 01092 char txt[259 * 3 + 1], 01093 *p = txt; /* always long enough */ 01094 int n = msg[1] + 3, 01095 q = 0; 01096 while (q < n && q < 30) { 01097 sprintf (p, " %02X", msg[q++]); 01098 p += 3; 01099 } 01100 if (q < n) 01101 sprintf (p, "..."); 01102 if (option_verbose > 2) 01103 ast_verbose (VERBOSE_PREFIX_3 "SMS %s%s\n", dir, txt); 01104 }
static int sms_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 1359 of file app_sms.c.
References answer, ast_copy_string(), ast_log(), ast_module_user_add, ast_module_user_remove, ast_channel::cid, ast_callerid::cid_num, sms_s::cli, sms_s::dcs, f, sms_s::ipc0, sms_s::ipc1, LOG_ERROR, sms_s::oa, sms_s::pid, sms_s::queue, sms_s::scts, sms_s::smsc, and sms_s::srr.
Referenced by load_module().
01360 { 01361 int res = -1; 01362 struct ast_module_user *u; 01363 struct ast_frame *f; 01364 sms_t h = { 0 }; 01365 01366 u = ast_module_user_add(chan); 01367 01368 h.ipc0 = h.ipc1 = 20; /* phase for cosine */ 01369 h.dcs = 0xF1; /* default */ 01370 if (!data) { 01371 ast_log (LOG_ERROR, "Requires queue name at least\n"); 01372 ast_module_user_remove(u); 01373 return -1; 01374 } 01375 01376 if (chan->cid.cid_num) 01377 ast_copy_string (h.cli, chan->cid.cid_num, sizeof (h.cli)); 01378 01379 { 01380 unsigned char *p; 01381 unsigned char *d = data, 01382 answer = 0; 01383 if (!*d || *d == '|') { 01384 ast_log (LOG_ERROR, "Requires queue name\n"); 01385 ast_module_user_remove(u); 01386 return -1; 01387 } 01388 for (p = d; *p && *p != '|'; p++); 01389 if (p - d >= sizeof (h.queue)) { 01390 ast_log (LOG_ERROR, "Queue name too long\n"); 01391 ast_module_user_remove(u); 01392 return -1; 01393 } 01394 strncpy(h.queue, (char *)d, p - d); 01395 if (*p == '|') 01396 p++; 01397 d = p; 01398 for (p = (unsigned char *)h.queue; *p; p++) 01399 if (!isalnum (*p)) 01400 *p = '-'; /* make very safe for filenames */ 01401 while (*d && *d != '|') { 01402 switch (*d) { 01403 case 'a': /* we have to send the initial FSK sequence */ 01404 answer = 1; 01405 break; 01406 case 's': /* we are acting as a service centre talking to a phone */ 01407 h.smsc = 1; 01408 break; 01409 /* the following apply if there is an arg3/4 and apply to the created message file */ 01410 case 'r': 01411 h.srr = 1; 01412 break; 01413 case 'o': 01414 h.dcs |= 4; /* octets */ 01415 break; 01416 case '1': 01417 case '2': 01418 case '3': 01419 case '4': 01420 case '5': 01421 case '6': 01422 case '7': /* set the pid for saved local message */ 01423 h.pid = 0x40 + (*d & 0xF); 01424 break; 01425 } 01426 d++; 01427 } 01428 if (*d == '|') { 01429 /* submitting a message, not taking call. */ 01430 /* deprecated, use smsq instead */ 01431 d++; 01432 h.scts = time (0); 01433 for (p = d; *p && *p != '|'; p++); 01434 if (*p) 01435 *p++ = 0; 01436 if (strlen ((char *)d) >= sizeof (h.oa)) { 01437 ast_log (LOG_ERROR, "Address too long %s\n", d); 01438 return 0; 01439 } 01440 if (h.smsc) { 01441 ast_copy_string (h.oa, (char *)d, sizeof (h.oa)); 01442 } else { 01443 ast_copy_string (h.da, (char *)d, sizeof (h.da)); 01444 } 01445 if (!h.smsc) 01446 ast_copy_string (h.oa, h.cli, sizeof (h.oa)); 01447 d = p; 01448 h.udl = 0; 01449 while (*p && h.udl < SMSLEN) 01450 h.ud[h.udl++] = utf8decode(&p); 01451 if (is7bit (h.dcs) && packsms7 (0, h.udhl, h.udh, h.udl, h.ud) < 0) 01452 ast_log (LOG_WARNING, "Invalid 7 bit GSM data\n"); 01453 if (is8bit (h.dcs) && packsms8 (0, h.udhl, h.udh, h.udl, h.ud) < 0) 01454 ast_log (LOG_WARNING, "Invalid 8 bit data\n"); 01455 if (is16bit (h.dcs) && packsms16 (0, h.udhl, h.udh, h.udl, h.ud) < 0) 01456 ast_log (LOG_WARNING, "Invalid 16 bit data\n"); 01457 h.rx = 0; /* sent message */ 01458 h.mr = -1; 01459 sms_writefile (&h); 01460 ast_module_user_remove(u); 01461 return 0; 01462 } 01463 01464 if (answer) { 01465 /* set up SMS_EST initial message */ 01466 h.omsg[0] = 0x93; 01467 h.omsg[1] = 0; 01468 sms_messagetx (&h); 01469 } 01470 } 01471 01472 if (chan->_state != AST_STATE_UP) 01473 ast_answer (chan); 01474 01475 #ifdef OUTALAW 01476 res = ast_set_write_format (chan, AST_FORMAT_ALAW); 01477 #else 01478 res = ast_set_write_format (chan, AST_FORMAT_SLINEAR); 01479 #endif 01480 if (res >= 0) 01481 res = ast_set_read_format (chan, AST_FORMAT_SLINEAR); 01482 if (res < 0) { 01483 ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n"); 01484 ast_module_user_remove(u); 01485 return -1; 01486 } 01487 01488 if (ast_activate_generator (chan, &smsgen, &h) < 0) { 01489 ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name); 01490 ast_module_user_remove(u); 01491 return -1; 01492 } 01493 01494 /* Do our thing here */ 01495 while (ast_waitfor (chan, -1) > -1 && !h.hangup) 01496 { 01497 f = ast_read (chan); 01498 if (!f) 01499 break; 01500 if (f->frametype == AST_FRAME_VOICE) { 01501 sms_process (&h, f->samples, f->data); 01502 } 01503 01504 ast_frfree (f); 01505 } 01506 01507 sms_log (&h, '?'); /* log incomplete message */ 01508 01509 /* 01510 * The SMS generator data is on the stack. We _MUST_ make sure the generator 01511 * is stopped before returning from this function. 01512 */ 01513 ast_deactivate_generator(chan); 01514 01515 ast_module_user_remove(u); 01516 return (h.err); 01517 }
static int sms_generate | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 1176 of file app_sms.c.
References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), f, LOG_WARNING, MAXSAMPLES, sms_s::obitp, sms_s::obyte, sms_s::obyten, sms_s::obytep, sms_s::omsg, sms_s::opause, sms_s::ophase, sms_s::ophasep, sms_s::osync, and SAMPLE2LEN.
01177 { 01178 struct ast_frame f = { 0 }; 01179 #define MAXSAMPLES (800) 01180 #ifdef OUTALAW 01181 unsigned char *buf; 01182 #else 01183 short *buf; 01184 #endif 01185 #define SAMPLE2LEN sizeof(*buf) 01186 sms_t *h = data; 01187 int i; 01188 01189 if (samples > MAXSAMPLES) { 01190 ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n", 01191 MAXSAMPLES, samples); 01192 samples = MAXSAMPLES; 01193 } 01194 len = samples * SAMPLE2LEN + AST_FRIENDLY_OFFSET; 01195 buf = alloca(len); 01196 01197 f.frametype = AST_FRAME_VOICE; 01198 #ifdef OUTALAW 01199 f.subclass = AST_FORMAT_ALAW; 01200 #else 01201 f.subclass = AST_FORMAT_SLINEAR; 01202 #endif 01203 f.datalen = samples * SAMPLE2LEN; 01204 f.offset = AST_FRIENDLY_OFFSET; 01205 f.mallocd = 0; 01206 f.data = buf; 01207 f.samples = samples; 01208 f.src = "app_sms"; 01209 /* create a buffer containing the digital sms pattern */ 01210 for (i = 0; i < samples; i++) { 01211 #ifdef OUTALAW 01212 buf[i] = wavea[0]; 01213 #else 01214 buf[i] = wave[0]; 01215 #endif 01216 if (h->opause) 01217 h->opause--; 01218 else if (h->obyten || h->osync) { /* sending data */ 01219 #ifdef OUTALAW 01220 buf[i] = wavea[h->ophase]; 01221 #else 01222 buf[i] = wave[h->ophase]; 01223 #endif 01224 if ((h->ophase += ((h->obyte & 1) ? 13 : 21)) >= 80) 01225 h->ophase -= 80; 01226 if ((h->ophasep += 12) >= 80) { /* next bit */ 01227 h->ophasep -= 80; 01228 if (h->osync) 01229 h->osync--; /* sending sync bits */ 01230 else { 01231 h->obyte >>= 1; 01232 h->obitp++; 01233 if (h->obitp == 1) 01234 h->obyte = 0; /* start bit; */ 01235 else if (h->obitp == 2) 01236 h->obyte = h->omsg[h->obytep]; 01237 else if (h->obitp == 10) { 01238 h->obyte = 1; /* stop bit */ 01239 h->obitp = 0; 01240 h->obytep++; 01241 if (h->obytep == h->obyten) { 01242 h->obytep = h->obyten = 0; /* sent */ 01243 h->osync = 10; /* trailing marks */ 01244 } 01245 } 01246 } 01247 } 01248 } 01249 } 01250 if (ast_write (chan, &f) < 0) { 01251 ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror (errno)); 01252 return -1; 01253 } 01254 return 0; 01255 #undef SAMPLE2LEN 01256 #undef MAXSAMPLES 01257 }
static unsigned char sms_handleincoming | ( | sms_t * | h | ) | [static] |
handle the incoming message
Definition at line 955 of file app_sms.c.
References ast_copy_string(), ast_log(), sms_s::cli, sms_s::da, sms_s::dcs, sms_s::imsg, LOG_WARNING, sms_s::mr, sms_s::oa, sms_s::pid, sms_s::rp, sms_s::rx, sms_s::scts, sms_writefile(), sms_s::smsc, sms_s::srr, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, unpackaddress(), unpackdate(), unpacksms(), and sms_s::vp.
Referenced by sms_messagerx().
00956 { 00957 unsigned char p = 3; 00958 if (h->smsc) { /* SMSC */ 00959 if ((h->imsg[2] & 3) == 1) { /* SMS-SUBMIT */ 00960 h->udhl = h->udl = 0; 00961 h->vp = 0; 00962 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0); 00963 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0); 00964 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0); 00965 ast_copy_string (h->oa, h->cli, sizeof (h->oa)); 00966 h->scts = time (0); 00967 h->mr = h->imsg[p++]; 00968 p += unpackaddress (h->da, h->imsg + p); 00969 h->pid = h->imsg[p++]; 00970 h->dcs = h->imsg[p++]; 00971 if ((h->imsg[2] & 0x18) == 0x10) { /* relative VP */ 00972 if (h->imsg[p] < 144) 00973 h->vp = (h->imsg[p] + 1) * 5; 00974 else if (h->imsg[p] < 168) 00975 h->vp = 720 + (h->imsg[p] - 143) * 30; 00976 else if (h->imsg[p] < 197) 00977 h->vp = (h->imsg[p] - 166) * 1440; 00978 else 00979 h->vp = (h->imsg[p] - 192) * 10080; 00980 p++; 00981 } else if (h->imsg[2] & 0x18) 00982 p += 7; /* ignore enhanced / absolute VP */ 00983 p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi); 00984 h->rx = 1; /* received message */ 00985 sms_writefile (h); /* write the file */ 00986 if (p != h->imsg[1] + 2) { 00987 ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2); 00988 return 0xFF; /* duh! */ 00989 } 00990 } else { 00991 ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]); 00992 return 0xFF; 00993 } 00994 } else { /* client */ 00995 if (!(h->imsg[2] & 3)) { /* SMS-DELIVER */ 00996 *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0; 00997 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0); 00998 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0); 00999 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0); 01000 h->mr = -1; 01001 p += unpackaddress (h->oa, h->imsg + p); 01002 h->pid = h->imsg[p++]; 01003 h->dcs = h->imsg[p++]; 01004 h->scts = unpackdate (h->imsg + p); 01005 p += 7; 01006 p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi); 01007 h->rx = 1; /* received message */ 01008 sms_writefile (h); /* write the file */ 01009 if (p != h->imsg[1] + 2) { 01010 ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2); 01011 return 0xFF; /* duh! */ 01012 } 01013 } else { 01014 ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]); 01015 return 0xFF; 01016 } 01017 } 01018 return 0; /* no error */ 01019 }
static void sms_log | ( | sms_t * | h, | |
char | status | |||
) | [static] |
Log the output, and remove file.
Definition at line 635 of file app_sms.c.
References sms_s::da, isodate(), sms_s::mr, sms_s::oa, sms_s::queue, sms_s::rx, sms_s::smsc, sms_s::ud, and sms_s::udl.
Referenced by sms_messagerx().
00636 { 00637 if (*h->oa || *h->da) { 00638 int o = open (log_file, O_CREAT | O_APPEND | O_WRONLY, 0666); 00639 if (o >= 0) { 00640 char line[1000], mrs[3] = "", *p; 00641 unsigned char n; 00642 00643 if (h->mr >= 0) 00644 snprintf (mrs, sizeof (mrs), "%02X", h->mr); 00645 snprintf (line, sizeof (line), "%s %c%c%c%s %s %s %s ", 00646 isodate (time (0)), status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue, *h->oa ? h->oa : "-", 00647 *h->da ? h->da : "-"); 00648 p = line + strlen (line); 00649 for (n = 0; n < h->udl; n++) 00650 if (h->ud[n] == '\\') { 00651 *p++ = '\\'; 00652 *p++ = '\\'; 00653 } else if (h->ud[n] == '\n') { 00654 *p++ = '\\'; 00655 *p++ = 'n'; 00656 } else if (h->ud[n] == '\r') { 00657 *p++ = '\\'; 00658 *p++ = 'r'; 00659 } else if (h->ud[n] < 32 || h->ud[n] == 127) 00660 *p++ = 191; 00661 else 00662 *p++ = h->ud[n]; 00663 *p++ = '\n'; 00664 *p = 0; 00665 if (write (o, line, strlen (line)) < 0) { 00666 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00667 } 00668 close (o); 00669 } 00670 *h->oa = *h->da = h->udl = 0; 00671 } 00672 }
static void sms_messagerx | ( | sms_t * | h | ) | [static] |
Definition at line 1106 of file app_sms.c.
References sms_s::err, sms_s::hangup, sms_s::imsg, sms_s::omsg, sms_debug(), sms_handleincoming(), sms_log(), sms_messagetx(), and sms_nextoutgoing().
Referenced by sms_process().
01107 { 01108 sms_debug ("RX", h->imsg); 01109 /* testing */ 01110 switch (h->imsg[0]) { 01111 case 0x91: /* SMS_DATA */ 01112 { 01113 unsigned char cause = sms_handleincoming (h); 01114 if (!cause) { 01115 sms_log (h, 'Y'); 01116 h->omsg[0] = 0x95; /* SMS_ACK */ 01117 h->omsg[1] = 0x02; 01118 h->omsg[2] = 0x00; /* deliver report */ 01119 h->omsg[3] = 0x00; /* no parameters */ 01120 } else { /* NACK */ 01121 sms_log (h, 'N'); 01122 h->omsg[0] = 0x96; /* SMS_NACK */ 01123 h->omsg[1] = 3; 01124 h->omsg[2] = 0; /* delivery report */ 01125 h->omsg[3] = cause; /* cause */ 01126 h->omsg[4] = 0; /* no parameters */ 01127 } 01128 sms_messagetx (h); 01129 } 01130 break; 01131 case 0x92: /* SMS_ERROR */ 01132 h->err = 1; 01133 sms_messagetx (h); /* send whatever we sent again */ 01134 break; 01135 case 0x93: /* SMS_EST */ 01136 sms_nextoutgoing (h); 01137 break; 01138 case 0x94: /* SMS_REL */ 01139 h->hangup = 1; /* hangup */ 01140 break; 01141 case 0x95: /* SMS_ACK */ 01142 sms_log (h, 'Y'); 01143 sms_nextoutgoing (h); 01144 break; 01145 case 0x96: /* SMS_NACK */ 01146 h->err = 1; 01147 sms_log (h, 'N'); 01148 sms_nextoutgoing (h); 01149 break; 01150 default: /* Unknown */ 01151 h->omsg[0] = 0x92; /* SMS_ERROR */ 01152 h->omsg[1] = 1; 01153 h->omsg[2] = 3; /* unknown message type; */ 01154 sms_messagetx (h); 01155 break; 01156 } 01157 }
static void sms_messagetx | ( | sms_t * | h | ) | [static] |
Definition at line 1159 of file app_sms.c.
References sms_s::obitp, sms_s::obyte, sms_s::obyten, sms_s::obytep, sms_s::omsg, sms_s::opause, sms_s::osync, and sms_debug().
Referenced by sms_messagerx(), sms_nextoutgoing(), and sms_process().
01160 { 01161 unsigned char c = 0, p; 01162 for (p = 0; p < h->omsg[1] + 2; p++) 01163 c += h->omsg[p]; 01164 h->omsg[h->omsg[1] + 2] = 0 - c; 01165 sms_debug ("TX", h->omsg); 01166 h->obyte = 1; 01167 h->opause = 200; 01168 if (h->omsg[0] == 0x93) 01169 h->opause = 2400; /* initial message delay 300ms (for BT) */ 01170 h->obytep = 0; 01171 h->obitp = 0; 01172 h->osync = 80; 01173 h->obyten = h->omsg[1] + 3; 01174 }
static void sms_nextoutgoing | ( | sms_t * | h | ) | [static] |
find and fill in next message, or send a REL if none waiting
Definition at line 1026 of file app_sms.c.
References ast_copy_string(), sms_s::da, sms_s::dcs, f, sms_s::mr, sms_s::oa, sms_s::omsg, packaddress(), packdate(), packsms(), sms_s::pid, sms_s::queue, readdirqueue(), sms_s::rp, sms_s::rx, sms_s::scts, sms_messagetx(), sms_readfile(), sms_s::smsc, sms_s::srr, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, and sms_s::vp.
Referenced by sms_messagerx().
01027 { 01028 char fn[100 + NAME_MAX] = ""; 01029 DIR *d; 01030 char more = 0; 01031 ast_copy_string (fn, spool_dir, sizeof (fn)); 01032 mkdir (fn, 0777); /* ensure it exists */ 01033 h->rx = 0; /* outgoing message */ 01034 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? "mttx" : "motx"); 01035 mkdir (fn, 0777); /* ensure it exists */ 01036 d = opendir (fn); 01037 if (d) { 01038 struct dirent *f = readdirqueue (d, h->queue); 01039 if (f) { 01040 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", f->d_name); 01041 sms_readfile (h, fn); 01042 if (readdirqueue (d, h->queue)) 01043 more = 1; /* more to send */ 01044 } 01045 closedir (d); 01046 } 01047 if (*h->da || *h->oa) { /* message to send */ 01048 unsigned char p = 2; 01049 h->omsg[0] = 0x91; /* SMS_DATA */ 01050 if (h->smsc) { /* deliver */ 01051 h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0); 01052 p += packaddress (h->omsg + p, h->oa); 01053 h->omsg[p++] = h->pid; 01054 h->omsg[p++] = h->dcs; 01055 packdate (h->omsg + p, h->scts); 01056 p += 7; 01057 p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud); 01058 } else { /* submit */ 01059 h->omsg[p++] = 01060 0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0); 01061 if (h->mr < 0) 01062 h->mr = message_ref++; 01063 h->omsg[p++] = h->mr; 01064 p += packaddress (h->omsg + p, h->da); 01065 h->omsg[p++] = h->pid; 01066 h->omsg[p++] = h->dcs; 01067 if (h->vp) { /* relative VP */ 01068 if (h->vp < 720) 01069 h->omsg[p++] = (h->vp + 4) / 5 - 1; 01070 else if (h->vp < 1440) 01071 h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143; 01072 else if (h->vp < 43200) 01073 h->omsg[p++] = (h->vp + 1439) / 1440 + 166; 01074 else if (h->vp < 635040) 01075 h->omsg[p++] = (h->vp + 10079) / 10080 + 192; 01076 else 01077 h->omsg[p++] = 255; /* max */ 01078 } 01079 p += packsms (h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud); 01080 } 01081 h->omsg[1] = p - 2; 01082 sms_messagetx (h); 01083 } else { /* no message */ 01084 h->omsg[0] = 0x94; /* SMS_REL */ 01085 h->omsg[1] = 0; 01086 sms_messagetx (h); 01087 } 01088 }
static void sms_process | ( | sms_t * | h, | |
int | samples, | |||
signed short * | data | |||
) | [static] |
Definition at line 1259 of file app_sms.c.
References ast_log(), sms_s::err, sms_s::hangup, sms_s::ibitc, sms_s::ibith, sms_s::ibitl, sms_s::ibitn, sms_s::ibitt, sms_s::ibytec, sms_s::ibytep, sms_s::ibytev, sms_s::idle, sms_s::ierr, sms_s::imag, sms_s::imc0, sms_s::imc1, sms_s::ims0, sms_s::ims1, sms_s::imsg, sms_s::ipc0, sms_s::ipc1, sms_s::iphasep, sms_s::ips0, sms_s::ips1, LOG_EVENT, m1, sms_s::obyten, sms_s::omsg, sms_s::osync, sms_messagerx(), and sms_messagetx().
01260 { 01261 if (h->obyten || h->osync) 01262 return; /* sending */ 01263 while (samples--) { 01264 unsigned long long m0, m1; 01265 if (abs (*data) > h->imag) 01266 h->imag = abs (*data); 01267 else 01268 h->imag = h->imag * 7 / 8; 01269 if (h->imag > 500) { 01270 h->idle = 0; 01271 h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7; 01272 h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7; 01273 h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7; 01274 h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7; 01275 m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0; 01276 m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1; 01277 if ((h->ips0 += 21) >= 80) 01278 h->ips0 -= 80; 01279 if ((h->ipc0 += 21) >= 80) 01280 h->ipc0 -= 80; 01281 if ((h->ips1 += 13) >= 80) 01282 h->ips1 -= 80; 01283 if ((h->ipc1 += 13) >= 80) 01284 h->ipc1 -= 80; 01285 { 01286 char bit; 01287 h->ibith <<= 1; 01288 if (m1 > m0) 01289 h->ibith |= 1; 01290 if (h->ibith & 8) 01291 h->ibitt--; 01292 if (h->ibith & 1) 01293 h->ibitt++; 01294 bit = ((h->ibitt > 1) ? 1 : 0); 01295 if (bit != h->ibitl) 01296 h->ibitc = 1; 01297 else 01298 h->ibitc++; 01299 h->ibitl = bit; 01300 if (!h->ibitn && h->ibitc == 4 && !bit) { 01301 h->ibitn = 1; 01302 h->iphasep = 0; 01303 } 01304 if (bit && h->ibitc == 200) { /* sync, restart message */ 01305 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0; 01306 } 01307 if (h->ibitn) { 01308 h->iphasep += 12; 01309 if (h->iphasep >= 80) { /* next bit */ 01310 h->iphasep -= 80; 01311 if (h->ibitn++ == 9) { /* end of byte */ 01312 if (!bit) /* bad stop bit */ 01313 h->ierr = 0xFF; /* unknown error */ 01314 else { 01315 if (h->ibytep < sizeof (h->imsg)) { 01316 h->imsg[h->ibytep] = h->ibytev; 01317 h->ibytec += h->ibytev; 01318 h->ibytep++; 01319 } else if (h->ibytep == sizeof (h->imsg)) 01320 h->ierr = 2; /* bad message length */ 01321 if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) { 01322 if (!h->ibytec) 01323 sms_messagerx (h); 01324 else 01325 h->ierr = 1; /* bad checksum */ 01326 } 01327 } 01328 h->ibitn = 0; 01329 } 01330 h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0); 01331 } 01332 } 01333 } 01334 } else { /* lost carrier */ 01335 if (h->idle++ == 80000) { /* nothing happening */ 01336 ast_log (LOG_EVENT, "No data, hanging up\n"); 01337 h->hangup = 1; 01338 h->err = 1; 01339 } 01340 if (h->ierr) { /* error */ 01341 h->err = 1; 01342 h->omsg[0] = 0x92; /* error */ 01343 h->omsg[1] = 1; 01344 h->omsg[2] = h->ierr; 01345 sms_messagetx (h); /* send error */ 01346 } 01347 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0; 01348 } 01349 data++; 01350 } 01351 }
static void sms_readfile | ( | sms_t * | h, | |
char * | fn | |||
) | [static] |
parse and delete a file
Definition at line 675 of file app_sms.c.
References ast_log(), ast_mktime(), sms_s::da, sms_s::dcs, is16bit, is7bit, is8bit, LOG_EVENT, LOG_WARNING, sms_s::mr, numcpy(), sms_s::oa, packsms16(), packsms7(), packsms8(), sms_s::pid, sms_s::rp, sms_s::rx, S, s, sms_s::scts, SMSLEN, sms_s::srr, t, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, utf8decode(), and sms_s::vp.
Referenced by sms_nextoutgoing().
00676 { 00677 char line[1000]; 00678 FILE *s; 00679 char dcsset = 0; /* if DSC set */ 00680 ast_log (LOG_EVENT, "Sending %s\n", fn); 00681 h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0; 00682 h->mr = -1; 00683 h->dcs = 0xF1; /* normal messages class 1 */ 00684 h->scts = time (0); 00685 s = fopen (fn, "r"); 00686 if (s) 00687 { 00688 if (unlink (fn)) 00689 { /* concurrent access, we lost */ 00690 fclose (s); 00691 return; 00692 } 00693 while (fgets (line, sizeof (line), s)) 00694 { /* process line in file */ 00695 char *p; 00696 void *pp = &p; 00697 for (p = line; *p && *p != '\n' && *p != '\r'; p++); 00698 *p = 0; /* strip eoln */ 00699 p = line; 00700 if (!*p || *p == ';') 00701 continue; /* blank line or comment, ignore */ 00702 while (isalnum (*p)) 00703 { 00704 *p = tolower (*p); 00705 p++; 00706 } 00707 while (isspace (*p)) 00708 *p++ = 0; 00709 if (*p == '=') 00710 { 00711 *p++ = 0; 00712 if (!strcmp (line, "ud")) 00713 { /* parse message (UTF-8) */ 00714 unsigned char o = 0; 00715 while (*p && o < SMSLEN) 00716 h->ud[o++] = utf8decode(pp); 00717 h->udl = o; 00718 if (*p) 00719 ast_log (LOG_WARNING, "UD too long in %s\n", fn); 00720 } else 00721 { 00722 while (isspace (*p)) 00723 p++; 00724 if (!strcmp (line, "oa") && strlen (p) < sizeof (h->oa)) 00725 numcpy (h->oa, p); 00726 else if (!strcmp (line, "da") && strlen (p) < sizeof (h->oa)) 00727 numcpy (h->da, p); 00728 else if (!strcmp (line, "pid")) 00729 h->pid = atoi (p); 00730 else if (!strcmp (line, "dcs")) 00731 { 00732 h->dcs = atoi (p); 00733 dcsset = 1; 00734 } else if (!strcmp (line, "mr")) 00735 h->mr = atoi (p); 00736 else if (!strcmp (line, "srr")) 00737 h->srr = (atoi (p) ? 1 : 0); 00738 else if (!strcmp (line, "vp")) 00739 h->vp = atoi (p); 00740 else if (!strcmp (line, "rp")) 00741 h->rp = (atoi (p) ? 1 : 0); 00742 else if (!strcmp (line, "scts")) 00743 { /* get date/time */ 00744 int Y, 00745 m, 00746 d, 00747 H, 00748 M, 00749 S; 00750 if (sscanf (p, "%30d-%30d-%30dT%30d:%30d:%30d", &Y, &m, &d, &H, &M, &S) == 6) 00751 { 00752 struct tm t; 00753 t.tm_year = Y - 1900; 00754 t.tm_mon = m - 1; 00755 t.tm_mday = d; 00756 t.tm_hour = H; 00757 t.tm_min = M; 00758 t.tm_sec = S; 00759 t.tm_isdst = -1; 00760 h->scts = ast_mktime(&t, NULL); 00761 if (h->scts == (time_t) - 1) 00762 ast_log (LOG_WARNING, "Bad date/timein %s: %s", fn, p); 00763 } 00764 } else 00765 ast_log (LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p); 00766 } 00767 } else if (*p == '#') 00768 { /* raw hex format */ 00769 *p++ = 0; 00770 if (*p == '#') 00771 { 00772 p++; 00773 if (!strcmp (line, "ud")) 00774 { /* user data */ 00775 int o = 0; 00776 while (*p && o < SMSLEN) 00777 { 00778 if (isxdigit (*p) && isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3])) 00779 { 00780 h->ud[o++] = 00781 (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 12) + 00782 (((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) + 00783 (((isalpha (p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha (p[3]) ? 9 : 0) + (p[3] & 0xF)); 00784 p += 4; 00785 } else 00786 break; 00787 } 00788 h->udl = o; 00789 if (*p) 00790 ast_log (LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn); 00791 } else 00792 ast_log (LOG_WARNING, "Only ud can use ## format, %s\n", fn); 00793 } else if (!strcmp (line, "ud")) 00794 { /* user data */ 00795 int o = 0; 00796 while (*p && o < SMSLEN) 00797 { 00798 if (isxdigit (*p) && isxdigit (p[1])) 00799 { 00800 h->ud[o++] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)); 00801 p += 2; 00802 } else 00803 break; 00804 } 00805 h->udl = o; 00806 if (*p) 00807 ast_log (LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn); 00808 } else if (!strcmp (line, "udh")) 00809 { /* user data header */ 00810 unsigned char o = 0; 00811 h->udhi = 1; 00812 while (*p && o < SMSLEN) 00813 { 00814 if (isxdigit (*p) && isxdigit (p[1])) 00815 { 00816 h->udh[o] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)); 00817 o++; 00818 p += 2; 00819 } else 00820 break; 00821 } 00822 h->udhl = o; 00823 if (*p) 00824 ast_log (LOG_WARNING, "UDH too long / invalid hex in %s\n", fn); 00825 } else 00826 ast_log (LOG_WARNING, "Only ud and udh can use # format, %s\n", fn); 00827 } else 00828 ast_log (LOG_WARNING, "Cannot parse in %s: %s\n", fn, line); 00829 } 00830 fclose (s); 00831 if (!dcsset && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0) 00832 { 00833 if (packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0) 00834 { 00835 if (packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0) 00836 ast_log (LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn); 00837 else 00838 { 00839 h->dcs = 0x08; /* default to 16 bit */ 00840 ast_log (LOG_WARNING, "Sending in 16 bit format (%s)\n", fn); 00841 } 00842 } else 00843 { 00844 h->dcs = 0xF5; /* default to 8 bit */ 00845 ast_log (LOG_WARNING, "Sending in 8 bit format (%s)\n", fn); 00846 } 00847 } 00848 if (is7bit (h->dcs) && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0) 00849 ast_log (LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn); 00850 if (is8bit (h->dcs) && packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0) 00851 ast_log (LOG_WARNING, "Invalid 8 bit data %s\n", fn); 00852 if (is16bit (h->dcs) && packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0) 00853 ast_log (LOG_WARNING, "Invalid 16 bit data %s\n", fn); 00854 } 00855 }
static void sms_release | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
static void sms_writefile | ( | sms_t * | h | ) | [static] |
white a received text message to a file
Definition at line 858 of file app_sms.c.
References ast_copy_string(), sms_s::da, isodate(), sms_s::oa, sms_s::queue, sms_s::rx, sms_s::scts, sms_s::smsc, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, and sms_s::udl.
Referenced by sms_handleincoming().
00859 { 00860 char fn[200] = "", fn2[200] = ""; 00861 FILE *o; 00862 ast_copy_string (fn, spool_dir, sizeof (fn)); 00863 mkdir (fn, 0777); /* ensure it exists */ 00864 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx"); 00865 mkdir (fn, 0777); /* ensure it exists */ 00866 ast_copy_string (fn2, fn, sizeof (fn2)); 00867 snprintf (fn2 + strlen (fn2), sizeof (fn2) - strlen (fn2), "/%s.%s-%d", h->queue, isodate (h->scts), seq++); 00868 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/.%s", fn2 + strlen (fn) + 1); 00869 o = fopen (fn, "w"); 00870 if (o) { 00871 if (*h->oa) 00872 fprintf (o, "oa=%s\n", h->oa); 00873 if (*h->da) 00874 fprintf (o, "da=%s\n", h->da); 00875 if (h->udhi) { 00876 unsigned int p; 00877 fprintf (o, "udh#"); 00878 for (p = 0; p < h->udhl; p++) 00879 fprintf (o, "%02X", h->udh[p]); 00880 fprintf (o, "\n"); 00881 } 00882 if (h->udl) { 00883 unsigned int p; 00884 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++); 00885 if (p < h->udl) 00886 fputc (';', o); /* cannot use ud=, but include as a comment for human readable */ 00887 fprintf (o, "ud="); 00888 for (p = 0; p < h->udl; p++) { 00889 unsigned short v = h->ud[p]; 00890 if (v < 32) 00891 fputc (191, o); 00892 else if (v < 0x80) 00893 fputc (v, o); 00894 else if (v < 0x800) 00895 { 00896 fputc (0xC0 + (v >> 6), o); 00897 fputc (0x80 + (v & 0x3F), o); 00898 } else 00899 { 00900 fputc (0xE0 + (v >> 12), o); 00901 fputc (0x80 + ((v >> 6) & 0x3F), o); 00902 fputc (0x80 + (v & 0x3F), o); 00903 } 00904 } 00905 fprintf (o, "\n"); 00906 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++); 00907 if (p < h->udl) { 00908 for (p = 0; p < h->udl && h->ud[p] < 0x100; p++); 00909 if (p == h->udl) { /* can write in ucs-1 hex */ 00910 fprintf (o, "ud#"); 00911 for (p = 0; p < h->udl; p++) 00912 fprintf (o, "%02X", h->ud[p]); 00913 fprintf (o, "\n"); 00914 } else { /* write in UCS-2 */ 00915 fprintf (o, "ud##"); 00916 for (p = 0; p < h->udl; p++) 00917 fprintf (o, "%04X", h->ud[p]); 00918 fprintf (o, "\n"); 00919 } 00920 } 00921 } 00922 if (h->scts) 00923 fprintf (o, "scts=%s\n", isodate (h->scts)); 00924 if (h->pid) 00925 fprintf (o, "pid=%d\n", h->pid); 00926 if (h->dcs != 0xF1) 00927 fprintf (o, "dcs=%d\n", h->dcs); 00928 if (h->vp) 00929 fprintf (o, "vp=%d\n", h->vp); 00930 if (h->srr) 00931 fprintf (o, "srr=1\n"); 00932 if (h->mr >= 0) 00933 fprintf (o, "mr=%d\n", h->mr); 00934 if (h->rp) 00935 fprintf (o, "rp=1\n"); 00936 fclose (o); 00937 if (rename (fn, fn2)) 00938 unlink (fn); 00939 else 00940 ast_log (LOG_EVENT, "Received to %s\n", fn2); 00941 } 00942 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1519 of file app_sms.c.
References ast_module_user_hangup_all, and ast_unregister_application().
01520 { 01521 int res; 01522 01523 res = ast_unregister_application (app); 01524 01525 ast_module_user_hangup_all(); 01526 01527 return res; 01528 }
static unsigned char unpackaddress | ( | char * | o, | |
unsigned char * | i | |||
) | [static] |
unpack an address from i, return byte length, unpack to o
Definition at line 593 of file app_sms.c.
Referenced by sms_handleincoming().
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 }
static time_t unpackdate | ( | unsigned char * | i | ) | [static] |
unpack a date and return
Definition at line 456 of file app_sms.c.
References ast_mktime().
Referenced by sms_handleincoming().
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 }
static int unpacksms | ( | unsigned char | dcs, | |
unsigned char * | i, | |||
unsigned char * | udh, | |||
int * | udhl, | |||
unsigned short * | ud, | |||
int * | udl, | |||
char | udhi | |||
) | [static] |
general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length
Definition at line 579 of file app_sms.c.
References is7bit, is8bit, unpacksms16(), unpacksms7(), and unpacksms8().
Referenced by sms_handleincoming().
00580 { 00581 int l = *i++; 00582 if (is7bit (dcs)) { 00583 unpacksms7 (i, l, udh, udhl, ud, udl, udhi); 00584 l = (l * 7 + 7) / 8; /* adjust length to return */ 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 }
static void unpacksms16 | ( | unsigned char * | i, | |
unsigned char | l, | |||
unsigned char * | udh, | |||
int * | udhl, | |||
unsigned short * | ud, | |||
int * | udl, | |||
char | udhi | |||
) | [static] |
unpacks bytes (16 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set
Definition at line 552 of file app_sms.c.
Referenced by unpacksms().
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 }
static void unpacksms7 | ( | unsigned char * | i, | |
unsigned char | l, | |||
unsigned char * | udh, | |||
int * | udhl, | |||
unsigned short * | ud, | |||
int * | udl, | |||
char | udhi | |||
) | [static] |
unpacks bytes (7 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set
Definition at line 476 of file app_sms.c.
Referenced by unpacksms().
00477 { 00478 unsigned char b = 0, p = 0; 00479 unsigned short *o = ud; 00480 *udhl = 0; 00481 if (udhi && l) { /* header */ 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 /* adjust for fill, septets */ 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 }
static void unpacksms8 | ( | unsigned char * | i, | |
unsigned char | l, | |||
unsigned char * | udh, | |||
int * | udhl, | |||
unsigned short * | ud, | |||
int * | udl, | |||
char | udhi | |||
) | [static] |
unpacks bytes (8 bit encoding) at i, len l septets, and places in udh and ud setting udhl and udl. udh not used if udhi not set
Definition at line 527 of file app_sms.c.
Referenced by unpacksms().
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++; /* not to UTF-8 as explicitely 8 bit coding in DCS */ 00546 *udl = (o - ud); 00547 }
static long utf8decode | ( | unsigned char ** | pp | ) | [static] |
reads next UCS character from null terminated UTF-8 string and advanced pointer
Definition at line 220 of file app_sms.c.
Referenced by sms_readfile().
00221 { 00222 unsigned char *p = *pp; 00223 if (!*p) 00224 return 0; /* null termination of string */ 00225 (*pp)++; 00226 if (*p < 0xC0) 00227 return *p; /* ascii or continuation character */ 00228 if (*p < 0xE0) { 00229 if (*p < 0xC2 || (p[1] & 0xC0) != 0x80) 00230 return *p; /* not valid UTF-8 */ 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; /* not valid UTF-8 */ 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; /* not valid UTF-8 */ 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; /* not valid UTF-8 */ 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; /* not valid UTF-8 */ 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; /* not sensible */ 00261 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "SMS/PSTN handler" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static] |
const struct ast_module_info* ast_module_info = &__mod_info [static] |
const unsigned short defaultalphabet[] [static] |
volatile unsigned char message_ref [static] |
volatile unsigned int seq [static] |
Definition at line 59 of file app_sms.c.
Referenced by ast_udptl_write(), handle_link_data(), handle_remote_data(), and udptl_build_packet().
struct ast_generator smsgen [static] |
Initial value:
{ alloc:sms_alloc, release:sms_release, generate:sms_generate, }
char* synopsis = "Communicates with SMS service centres and SMS capable analogue phones" [static] |
signed short wave[] [static] |