#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().