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