#include "asterisk.h"
#include <dirent.h>
#include <ctype.h>
#include <sys/stat.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
Go to the source code of this file.
Data Structures | |
struct | sms_s |
Defines | |
#define | __OUT_FMT AST_FORMAT_SLINEAR |
#define | DIR_RX 1 |
#define | DIR_TX 2 |
#define | DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1) |
#define | is16bit(dcs) ( ((dcs) & 0xC0) ? 0 : (((dcs) & 0xc) == 8) ) |
#define | is7bit(dcs) ( ((dcs) & 0xC0) ? (!((dcs)&4) ) : (((dcs) & 0xc) == 0) ) |
#define | is8bit(dcs) ( ((dcs) & 0xC0) ? ( ((dcs)&4) ) : (((dcs) & 0xc) == 4) ) |
#define | MAX_DEBUG_LEN 300 |
#define | MAXSAMPLES (800) |
#define | OSYNC_BITS 80 |
#define | SMSLEN 160 |
#define | SMSLEN_8 140 |
Typedefs | |
typedef signed short | output_t |
typedef sms_s | sms_t |
Enumerations | |
enum | { OPTION_BE_SMSC = (1 << 0), OPTION_ANSWER = (1 << 1), OPTION_TWO = (1 << 2), OPTION_PAUSE = (1 << 3), OPTION_SRR = (1 << 4), OPTION_DCS = (1 << 5) } |
enum | { OPTION_ARG_PAUSE = 0, OPTION_ARG_ARRAY_SIZE } |
enum | message_types { DLL_SMS_MASK = 0x7f, DLL1_SMS_DATA = 0x11, DLL1_SMS_ERROR = 0x12, DLL1_SMS_EST = 0x13, DLL1_SMS_REL = 0x14, DLL1_SMS_ACK = 0x15, DLL1_SMS_NACK = 0x16, DLL1_SMS_COMPLETE = 0x80, DLL1_SMS_MORE = 0x00, DLL2_SMS_EST = 0x7f, DLL2_SMS_INFO_MO = 0x10, DLL2_SMS_INFO_MT = 0x11, DLL2_SMS_INFO_STA = 0x12, DLL2_SMS_NACK = 0x13, DLL2_SMS_ACK0 = 0x14, DLL2_SMS_ACK1 = 0x15, DLL2_SMS_ENQ = 0x16, DLL2_SMS_REL = 0x17, DLL2_SMS_COMPLETE = 0x00, DLL2_SMS_MORE = 0x80 } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static void | adddata_proto2 (sms_t *h, unsigned char msg, char *data, int size) |
static char * | isodate (time_t t, char *buf, int len) |
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. 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 void | putdummydata_proto2 (sms_t *h) |
static struct dirent * | readdirqueue (DIR *d, char *queue) |
read dir skipping dot files... | |
static void * | sms_alloc (struct ast_channel *chan, void *sms_t_ptr) |
static void | sms_compose1 (sms_t *h, int more) |
compose a message for protocol 1 | |
static void | sms_compose2 (sms_t *h, int more) |
static void | sms_debug (int dir, sms_t *h) |
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 int | sms_handleincoming_proto2 (sms_t *h) |
sms_handleincoming_proto2: handle the incoming message | |
static char * | sms_hexdump (unsigned char buf[], int size, char *s) |
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_messagerx2 (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 struct timeval | 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 NUL terminated UTF-8 string and advance pointer. | |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .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 |
enum { ... } | sms_flags |
enum { ... } | sms_opt_args |
static struct ast_app_option | sms_options [128] = { [ 's' ] = { .flag = OPTION_BE_SMSC }, [ 'a' ] = { .flag = OPTION_ANSWER }, [ 't' ] = { .flag = OPTION_TWO }, [ 'r' ] = { .flag = OPTION_SRR }, [ 'o' ] = { .flag = OPTION_DCS }, [ 'p' ] = { .flag = OPTION_PAUSE , .arg_index = OPTION_ARG_PAUSE + 1 }, } |
static struct ast_generator | smsgen |
static char * | synopsis = "Communicates with SMS service centres and SMS capable analogue phones" |
static signed short | wave [] |
static const output_t * | wave_out = wave |
Filippo Grassilli (Hyppo) - protocol 2 support Not fully tested, under development
Definition in file app_sms.c.
#define __OUT_FMT AST_FORMAT_SLINEAR |
#define DIR_RX 1 |
#define DIR_TX 2 |
#define DLL2_ACK | ( | h | ) | ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1) |
Referenced by sms_messagerx2().
#define is16bit | ( | dcs | ) | ( ((dcs) & 0xC0) ? 0 : (((dcs) & 0xc) == 8) ) |
#define is7bit | ( | dcs | ) | ( ((dcs) & 0xC0) ? (!((dcs)&4) ) : (((dcs) & 0xc) == 0) ) |
#define is8bit | ( | dcs | ) | ( ((dcs) & 0xC0) ? ( ((dcs)&4) ) : (((dcs) & 0xc) == 4) ) |
#define MAX_DEBUG_LEN 300 |
Definition at line 1146 of file app_sms.c.
Referenced by sms_handleincoming_proto2(), and sms_hexdump().
#define MAXSAMPLES (800) |
Referenced by sms_generate().
#define SMSLEN 160 |
max SMS length
Definition at line 187 of file app_sms.c.
Referenced by packsms7(), and sms_readfile().
#define SMSLEN_8 140 |
max SMS length for 8-bit char
Definition at line 188 of file app_sms.c.
Referenced by packsms16(), and packsms8().
anonymous enum |
Definition at line 1718 of file app_sms.c.
01718 { 01719 OPTION_BE_SMSC = (1 << 0), /* act as sms center */ 01720 OPTION_ANSWER = (1 << 1), /* answer on incoming calls */ 01721 OPTION_TWO = (1 << 2), /* Use Protocol Two */ 01722 OPTION_PAUSE = (1 << 3), /* pause before sending data, in ms */ 01723 OPTION_SRR = (1 << 4), /* set srr */ 01724 OPTION_DCS = (1 << 5), /* set dcs */ 01725 } sms_flags;
anonymous enum |
Definition at line 1727 of file app_sms.c.
01727 { 01728 OPTION_ARG_PAUSE = 0, 01729 OPTION_ARG_ARRAY_SIZE 01730 } sms_opt_args;
enum message_types |
The SMS spec ETSI ES 201 912 defines two protocols with different message types. Also note that the high bit is used to indicate whether the message is complete or not, but in two opposite ways: for Protocol 1, 0x80 means that the message is complete; for Protocol 2, 0x00 means that the message is complete;
Definition at line 133 of file app_sms.c.
00133 { 00134 DLL_SMS_MASK = 0x7f, /* mask for the valid bits */ 00135 00136 /* Protocol 1 values */ 00137 DLL1_SMS_DATA = 0x11, /* data packet */ 00138 DLL1_SMS_ERROR = 0x12, 00139 DLL1_SMS_EST = 0x13, /* start the connection */ 00140 DLL1_SMS_REL = 0x14, /* end the connection */ 00141 DLL1_SMS_ACK = 0x15, 00142 DLL1_SMS_NACK = 0x16, 00143 00144 DLL1_SMS_COMPLETE = 0x80, /* packet is complete */ 00145 DLL1_SMS_MORE = 0x00, /* more data to follow */ 00146 00147 /* Protocol 2 values */ 00148 DLL2_SMS_EST = 0x7f, /* magic number. No message body */ 00149 DLL2_SMS_INFO_MO = 0x10, 00150 DLL2_SMS_INFO_MT = 0x11, 00151 DLL2_SMS_INFO_STA = 0x12, 00152 DLL2_SMS_NACK = 0x13, 00153 DLL2_SMS_ACK0 = 0x14, /* ack even-numbered frame */ 00154 DLL2_SMS_ACK1 = 0x15, /* ack odd-numbered frame */ 00155 DLL2_SMS_ENQ = 0x16, 00156 DLL2_SMS_REL = 0x17, /* end the connection */ 00157 00158 DLL2_SMS_COMPLETE = 0x00, /* packet is complete */ 00159 DLL2_SMS_MORE = 0x80, /* more data to follow */ 00160 };
static void adddata_proto2 | ( | sms_t * | h, | |
unsigned char | msg, | |||
char * | data, | |||
int | size | |||
) | [static] |
Add data to a protocol 2 message. Use the length field (h->omsg[1]) as a pointer to the next free position.
Definition at line 1090 of file app_sms.c.
References sms_s::omsg.
Referenced by putdummydata_proto2(), and sms_compose2().
01091 { 01092 int x = h->omsg[1]+2; /* Get current position */ 01093 if (x == 2) 01094 x += 2; /* First: skip Payload length (set later) */ 01095 h->omsg[x++] = msg; /* Message code */ 01096 h->omsg[x++] = (unsigned char)size; /* Data size Low */ 01097 h->omsg[x++] = 0; /* Data size Hi */ 01098 for (; size > 0 ; size--) 01099 h->omsg[x++] = *data++; 01100 h->omsg[1] = x - 2; /* Frame size */ 01101 h->omsg[2] = x - 4; /* Payload length (Lo) */ 01102 h->omsg[3] = 0; /* Payload length (Hi) */ 01103 }
static char* isodate | ( | time_t | t, | |
char * | buf, | |||
int | len | |||
) | [static] |
static, return a date/time in ISO format
Definition at line 271 of file app_sms.c.
References ast_localtime(), and ast_strftime().
Referenced by sms_log(), and sms_writefile().
00272 { 00273 struct ast_tm tm; 00274 struct timeval tv = { t, 0 }; 00275 ast_localtime(&tv, &tm, NULL); 00276 ast_strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); 00277 return buf; 00278 }
static int load_module | ( | void | ) | [static] |
Definition at line 1925 of file app_sms.c.
References ast_config_AST_LOG_DIR, AST_LIN2A, ast_register_application, and sms_exec().
01926 { 01927 #ifdef OUTALAW 01928 int p; 01929 for (p = 0; p < 80; p++) 01930 wavea[p] = AST_LIN2A (wave[p]); 01931 #endif 01932 snprintf(log_file, sizeof(log_file), "%s/sms", ast_config_AST_LOG_DIR); 01933 return ast_register_application(app, sms_exec, synopsis, descrip); 01934 }
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 688 of file app_sms.c.
Referenced by sms_compose1().
00689 { 00690 unsigned char p = 2; 00691 o[0] = 0; /* number of bytes */ 00692 if (*i == '+') { /* record as bit 0 in byte 1 */ 00693 i++; 00694 o[1] = 0x91; 00695 } else 00696 o[1] = 0x81; 00697 for ( ; *i ; i++) { 00698 if (!isdigit(*i)) /* ignore non-digits */ 00699 continue; 00700 if (o[0] & 1) 00701 o[p++] |= ((*i & 0xF) << 4); 00702 else 00703 o[p] = (*i & 0xF); 00704 o[0]++; 00705 } 00706 if (o[0] & 1) 00707 o[p++] |= 0xF0; /* pad */ 00708 return p; 00709 }
static void packdate | ( | unsigned char * | o, | |
time_t | w | |||
) | [static] |
pack a date and return
Definition at line 506 of file app_sms.c.
References ast_localtime(), ast_tm::tm_gmtoff, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, and ast_tm::tm_year.
Referenced by sms_compose1().
00507 { 00508 struct ast_tm t; 00509 struct timeval tv = { w, 0 }; 00510 int z; 00511 00512 ast_localtime(&tv, &t, NULL); 00513 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__) 00514 z = -t.tm_gmtoff / 60 / 15; 00515 #else 00516 z = timezone / 60 / 15; 00517 #endif 00518 *o++ = ((t.tm_year % 10) << 4) + (t.tm_year % 100) / 10; 00519 *o++ = (((t.tm_mon + 1) % 10) << 4) + (t.tm_mon + 1) / 10; 00520 *o++ = ((t.tm_mday % 10) << 4) + t.tm_mday / 10; 00521 *o++ = ((t.tm_hour % 10) << 4) + t.tm_hour / 10; 00522 *o++ = ((t.tm_min % 10) << 4) + t.tm_min / 10; 00523 *o++ = ((t.tm_sec % 10) << 4) + t.tm_sec / 10; 00524 if (z < 0) 00525 *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08; 00526 else 00527 *o++ = ((z % 10) << 4) + z / 10; 00528 }
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 473 of file app_sms.c.
References is7bit, is8bit, packsms16(), packsms7(), and packsms8().
Referenced by sms_compose1().
00474 { 00475 unsigned char *p = base; 00476 if (udl == 0) 00477 *p++ = 0; /* no user data */ 00478 else { 00479 00480 int l = 0; 00481 if (is7bit(dcs)) { /* 7 bit */ 00482 l = packsms7(p + 1, udhl, udh, udl, ud); 00483 if (l < 0) 00484 l = 0; 00485 *p++ = l; 00486 p += (l * 7 + 7) / 8; 00487 } else if (is8bit(dcs)) { /* 8 bit */ 00488 l = packsms8(p + 1, udhl, udh, udl, ud); 00489 if (l < 0) 00490 l = 0; 00491 *p++ = l; 00492 p += l; 00493 } else { /* UCS-2 */ 00494 l = packsms16(p + 1, udhl, udh, udl, ud); 00495 if (l < 0) 00496 l = 0; 00497 *p++ = l; 00498 p += l; 00499 } 00500 } 00501 return p - base; 00502 }
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 442 of file app_sms.c.
References dummy(), and SMSLEN_8.
Referenced by packsms(), and sms_readfile().
00443 { 00444 unsigned char p = 0; 00445 unsigned char dummy[SMSLEN_8]; 00446 00447 if (o == NULL) 00448 o = dummy; 00449 /* header - no encoding */ 00450 if (udhl) { 00451 o[p++] = udhl; 00452 while (udhl--) { 00453 o[p++] = *udh++; 00454 if (p >= SMSLEN_8) 00455 return p; 00456 } 00457 } 00458 while (udl--) { 00459 long u; 00460 u = *ud++; 00461 o[p++] = (u >> 8); 00462 if (p >= SMSLEN_8) 00463 return p - 1; /* could not fit last character */ 00464 o[p++] = u; 00465 if (p >= SMSLEN_8) 00466 return p; 00467 } 00468 return p; 00469 }
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 330 of file app_sms.c.
References dummy(), and SMSLEN.
Referenced by packsms(), and sms_readfile().
00331 { 00332 unsigned char p = 0; /* output pointer (bytes) */ 00333 unsigned char b = 0; /* bit position */ 00334 unsigned char n = 0; /* output character count */ 00335 unsigned char dummy[SMSLEN]; 00336 00337 if (o == NULL) /* output to a dummy buffer if o not set */ 00338 o = dummy; 00339 00340 if (udhl) { /* header */ 00341 o[p++] = udhl; 00342 b = 1; 00343 n = 1; 00344 while (udhl--) { 00345 o[p++] = *udh++; 00346 b += 8; 00347 while (b >= 7) { 00348 b -= 7; 00349 n++; 00350 } 00351 if (n >= SMSLEN) 00352 return n; 00353 } 00354 if (b) { 00355 b = 7 - b; 00356 if (++n >= SMSLEN) 00357 return n; 00358 }; /* filling to septet boundary */ 00359 } 00360 o[p] = 0; 00361 /* message */ 00362 while (udl--) { 00363 long u; 00364 unsigned char v; 00365 u = *ud++; 00366 /* XXX 0 is invalid ? */ 00367 /* look up in defaultalphabet[]. If found, v is the 7-bit code */ 00368 for (v = 0; v < 128 && defaultalphabet[v] != u; v++); 00369 if (v == 128 /* not found */ && u && n + 1 < SMSLEN) { 00370 /* if not found, look in the escapes table (we need 2 bytes) */ 00371 for (v = 0; v < 128 && escapes[v] != u; v++); 00372 if (v < 128) { /* escaped sequence, esc + v */ 00373 /* store the low (8-b) bits in o[p], the remaining bits in o[p+1] */ 00374 o[p] |= (27 << b); /* the low bits go into o[p] */ 00375 b += 7; 00376 if (b >= 8) { 00377 b -= 8; 00378 p++; 00379 o[p] = (27 >> (7 - b)); 00380 } 00381 n++; 00382 } 00383 } 00384 if (v == 128) 00385 return -1; /* invalid character */ 00386 /* store, same as above */ 00387 o[p] |= (v << b); 00388 b += 7; 00389 if (b >= 8) { 00390 b -= 8; 00391 p++; 00392 o[p] = (v >> (7 - b)); 00393 } 00394 if (++n >= SMSLEN) 00395 return n; 00396 } 00397 return n; 00398 }
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. 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 406 of file app_sms.c.
References dummy(), and SMSLEN_8.
Referenced by packsms(), and sms_readfile().
00407 { 00408 unsigned char p = 0; 00409 unsigned char dummy[SMSLEN_8]; 00410 00411 if (o == NULL) 00412 o = dummy; 00413 /* header - no encoding */ 00414 if (udhl) { 00415 o[p++] = udhl; 00416 while (udhl--) { 00417 o[p++] = *udh++; 00418 if (p >= SMSLEN_8) 00419 return p; 00420 } 00421 } 00422 while (udl--) { 00423 long u; 00424 u = *ud++; 00425 if (u < 0 || u > 0xFF) 00426 return -1; /* not valid */ 00427 o[p++] = u; 00428 if (p >= SMSLEN_8) 00429 return p; 00430 } 00431 return p; 00432 }
static void putdummydata_proto2 | ( | sms_t * | h | ) | [static] |
Definition at line 1105 of file app_sms.c.
References adddata_proto2(), sms_s::udl, and sms_s::udtxt.
Referenced by sms_compose2().
01106 { 01107 adddata_proto2(h, 0x10, "\0", 1); /* Media Identifier > SMS */ 01108 adddata_proto2(h, 0x11, "\0\0\0\0\0\0", 6); /* Firmware version */ 01109 adddata_proto2(h, 0x12, "\2\0\4", 3); /* SMS provider ID */ 01110 adddata_proto2(h, 0x13, h->udtxt, h->udl); /* Body */ 01111 }
static struct dirent* readdirqueue | ( | DIR * | d, | |
char * | queue | |||
) | [static] |
read dir skipping dot files...
Definition at line 1006 of file app_sms.c.
References f.
Referenced by sms_nextoutgoing().
01007 { 01008 struct dirent *f; 01009 do { 01010 f = readdir(d); 01011 } while (f && (*f->d_name == '.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] != '.')); 01012 return f; 01013 }
static void* sms_alloc | ( | struct ast_channel * | chan, | |
void * | sms_t_ptr | |||
) | [static] |
static void sms_compose1 | ( | sms_t * | h, | |
int | more | |||
) | [static] |
compose a message for protocol 1
Definition at line 1292 of file app_sms.c.
References sms_s::da, sms_s::dcs, sms_s::mr, sms_s::oa, sms_s::omsg, packaddress(), packdate(), packsms(), sms_s::pid, sms_s::rp, sms_s::scts, 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_nextoutgoing().
01293 { 01294 unsigned int p = 2; /* next byte to write. Skip type and len */ 01295 01296 h->omsg[0] = 0x91; /* SMS_DATA */ 01297 if (h->smsc) { /* deliver */ 01298 h->omsg[p++] = (more ? 4 : 0) + ((h->udhl > 0) ? 0x40 : 0); 01299 p += packaddress(h->omsg + p, h->oa); 01300 h->omsg[p++] = h->pid; 01301 h->omsg[p++] = h->dcs; 01302 packdate(h->omsg + p, h->scts.tv_sec); 01303 p += 7; 01304 p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud); 01305 } else { /* submit */ 01306 h->omsg[p++] = 01307 0x01 + (more ? 4 : 0) + (h->srr ? 0x20 : 0) + (h->rp ? 0x80 : 0) + (h->vp ? 0x10 : 0) + (h->udhi ? 0x40 : 0); 01308 if (h->mr < 0) 01309 h->mr = message_ref++; 01310 h->omsg[p++] = h->mr; 01311 p += packaddress(h->omsg + p, h->da); 01312 h->omsg[p++] = h->pid; 01313 h->omsg[p++] = h->dcs; 01314 if (h->vp) { /* relative VP */ 01315 if (h->vp < 720) 01316 h->omsg[p++] = (h->vp + 4) / 5 - 1; 01317 else if (h->vp < 1440) 01318 h->omsg[p++] = (h->vp - 720 + 29) / 30 + 143; 01319 else if (h->vp < 43200) 01320 h->omsg[p++] = (h->vp + 1439) / 1440 + 166; 01321 else if (h->vp < 635040) 01322 h->omsg[p++] = (h->vp + 10079) / 10080 + 192; 01323 else 01324 h->omsg[p++] = 255; /* max */ 01325 } 01326 p += packsms(h->dcs, h->omsg + p, h->udhl, h->udh, h->udl, h->ud); 01327 } 01328 h->omsg[1] = p - 2; 01329 }
static void sms_compose2 | ( | sms_t * | h, | |
int | more | |||
) | [static] |
Definition at line 1113 of file app_sms.c.
References adddata_proto2(), ast_localtime(), sms_s::da, sms_s::oa, sms_s::omsg, putdummydata_proto2(), sms_s::scts, sms_s::smsc, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, and ast_tm::tm_mon.
Referenced by sms_nextoutgoing().
01114 { 01115 struct ast_tm tm; 01116 struct timeval tv = h->scts; 01117 char stm[9]; 01118 01119 h->omsg[0] = 0x00; /* set later... */ 01120 h->omsg[1] = 0; 01121 putdummydata_proto2(h); 01122 if (h->smsc) { /* deliver */ 01123 h->omsg[0] = 0x11; /* SMS_DELIVERY */ 01124 /* Required: 10 11 12 13 14 15 17 (seems they must be ordered!) */ 01125 ast_localtime(&tv, &tm, NULL); 01126 sprintf(stm, "%02d%02d%02d%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min); /* Date mmddHHMM */ 01127 adddata_proto2(h, 0x14, stm, 8); /* Date */ 01128 if (*h->oa == 0) 01129 strcpy(h->oa, "00000000"); 01130 adddata_proto2(h, 0x15, h->oa, strlen(h->oa)); /* Originator */ 01131 adddata_proto2(h, 0x17, "\1", 1); /* Calling Terminal ID */ 01132 } else { /* submit */ 01133 h->omsg[0] = 0x10; /* SMS_SUBMIT */ 01134 /* Required: 10 11 12 13 17 18 1B 1C (seems they must be ordered!) */ 01135 adddata_proto2(h, 0x17, "\1", 1); /* Calling Terminal ID */ 01136 if (*h->da == 0) 01137 strcpy(h->da, "00000000"); 01138 adddata_proto2(h, 0x18, h->da, strlen(h->da)); /* Originator */ 01139 adddata_proto2(h, 0x1B, "\1", 1); /* Called Terminal ID */ 01140 adddata_proto2(h, 0x1C, "\0\0\0", 3); /* Notification */ 01141 } 01142 }
static void sms_debug | ( | int | dir, | |
sms_t * | h | |||
) | [static] |
Definition at line 1372 of file app_sms.c.
References ast_verb, DIR_RX, sms_s::ibytep, sms_s::imsg, msg, and sms_s::omsg.
Referenced by sms_messagerx(), and sms_messagetx().
01373 { 01374 char txt[259 * 3 + 1]; 01375 char *p = txt; /* always long enough */ 01376 unsigned char *msg = (dir == DIR_RX) ? h->imsg : h->omsg; 01377 int n = (dir == DIR_RX) ? h->ibytep : msg[1] + 2; 01378 int q = 0; 01379 while (q < n && q < 30) { 01380 sprintf(p, " %02X", msg[q++]); 01381 p += 3; 01382 } 01383 if (q < n) 01384 sprintf(p, "..."); 01385 ast_verb(3, "SMS %s%s\n", dir == DIR_RX ? "RX" : "TX", txt); 01386 }
static int sms_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 1741 of file app_sms.c.
References AST_APP_ARG, ast_app_parse_options(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verb, chan, ast_channel::cid, ast_callerid::cid_num, sms_s::cli, sms_s::dcs, sms_s::ipc0, sms_s::ipc1, LOG_ERROR, sms_s::opause_0, OPTION_ARG_ARRAY_SIZE, OPTION_ARG_PAUSE, OPTION_BE_SMSC, OPTION_DCS, OPTION_SRR, OPTION_TWO, parse(), sms_s::pid, sms_s::protocol, sms_s::queue, S_OR, sms_flags, sms_options, sms_s::smsc, and sms_s::srr.
Referenced by load_module().
01742 { 01743 int res = -1; 01744 sms_t h = { 0 }; 01745 /* argument parsing support */ 01746 struct ast_flags sms_flags; 01747 char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, }; 01748 char *p; 01749 AST_DECLARE_APP_ARGS(sms_args, 01750 AST_APP_ARG(queue); 01751 AST_APP_ARG(options); 01752 AST_APP_ARG(addr); 01753 AST_APP_ARG(body); 01754 ); 01755 01756 if (!data) { 01757 ast_log(LOG_ERROR, "Requires queue name at least\n"); 01758 return -1; 01759 } 01760 01761 parse = ast_strdupa(data); /* create a local copy */ 01762 AST_STANDARD_APP_ARGS(sms_args, parse); 01763 if (sms_args.argc > 1) 01764 ast_app_parse_options(sms_options, &sms_flags, sms_opts, sms_args.options); 01765 01766 ast_verb(1, "sms argc %d queue <%s> opts <%s> addr <%s> body <%s>\n", 01767 sms_args.argc, S_OR(sms_args.queue, ""), 01768 S_OR(sms_args.options, ""), 01769 S_OR(sms_args.addr, ""), 01770 S_OR(sms_args.body, "") ); 01771 01772 h.ipc0 = h.ipc1 = 20; /* phase for cosine */ 01773 h.dcs = 0xF1; /* default */ 01774 01775 if (chan->cid.cid_num) 01776 ast_copy_string(h.cli, chan->cid.cid_num, sizeof(h.cli)); 01777 01778 if (ast_strlen_zero(sms_args.queue)) { 01779 ast_log(LOG_ERROR, "Requires queue name\n"); 01780 goto done; 01781 } 01782 if (strlen(sms_args.queue) >= sizeof(h.queue)) { 01783 ast_log(LOG_ERROR, "Queue name too long\n"); 01784 goto done; 01785 } 01786 ast_copy_string(h.queue, sms_args.queue, sizeof(h.queue)); 01787 01788 for (p = h.queue; *p; p++) 01789 if (!isalnum(*p)) 01790 *p = '-'; /* make very safe for filenames */ 01791 01792 h.smsc = ast_test_flag(&sms_flags, OPTION_BE_SMSC); 01793 h.protocol = ast_test_flag(&sms_flags, OPTION_TWO) ? 2 : 1; 01794 if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE])) 01795 h.opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]); 01796 if (h.opause_0 < 25 || h.opause_0 > 2000) 01797 h.opause_0 = 300; /* default 300ms */ 01798 ast_verb(1, "initial delay %dms\n", h.opause_0); 01799 01800 01801 /* the following apply if there is an arg3/4 and apply to the created message file */ 01802 if (ast_test_flag(&sms_flags, OPTION_SRR)) 01803 h.srr = 1; 01804 if (ast_test_flag(&sms_flags, OPTION_DCS)) 01805 h.dcs = 1; 01806 #if 0 01807 case '1': 01808 case '2': 01809 case '3': 01810 case '4': 01811 case '5': 01812 case '6': 01813 case '7': /* set the pid for saved local message */ 01814 h.pid = 0x40 + (*d & 0xF); 01815 break; 01816 } 01817 #endif 01818 if (sms_args.argc > 2) { 01819 unsigned char *up; 01820 01821 /* submitting a message, not taking call. */ 01822 /* deprecated, use smsq instead */ 01823 h.scts = ast_tvnow(); 01824 if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >= sizeof(h.oa)) { 01825 ast_log(LOG_ERROR, "Address too long %s\n", sms_args.addr); 01826 goto done; 01827 } 01828 if (h.smsc) 01829 ast_copy_string(h.oa, sms_args.addr, sizeof(h.oa)); 01830 else { 01831 ast_copy_string(h.da, sms_args.addr, sizeof(h.da)); 01832 ast_copy_string(h.oa, h.cli, sizeof(h.oa)); 01833 } 01834 h.udl = 0; 01835 if (ast_strlen_zero(sms_args.body)) { 01836 ast_log(LOG_ERROR, "Missing body for %s\n", sms_args.addr); 01837 goto done; 01838 } 01839 up = (unsigned char *)sms_args.body; 01840 while (*up && h.udl < SMSLEN) 01841 h.ud[h.udl++] = utf8decode(&up); 01842 if (is7bit(h.dcs) && packsms7(0, h.udhl, h.udh, h.udl, h.ud) < 0) { 01843 ast_log(LOG_WARNING, "Invalid 7 bit GSM data\n"); 01844 goto done; 01845 } 01846 if (is8bit(h.dcs) && packsms8(0, h.udhl, h.udh, h.udl, h.ud) < 0) { 01847 ast_log(LOG_WARNING, "Invalid 8 bit data\n"); 01848 goto done; 01849 } 01850 if (is16bit(h.dcs) && packsms16(0, h.udhl, h.udh, h.udl, h.ud) < 0) { 01851 ast_log(LOG_WARNING, "Invalid 16 bit data\n"); 01852 goto done; 01853 } 01854 h.rx = 0; /* sent message */ 01855 h.mr = -1; 01856 sms_writefile(&h); 01857 res = h.err; 01858 goto done; 01859 } 01860 01861 if (ast_test_flag(&sms_flags, OPTION_ANSWER)) { 01862 h.framenumber = 1; /* Proto 2 */ 01863 /* set up SMS_EST initial message */ 01864 if (h.protocol == 2) { 01865 h.omsg[0] = DLL2_SMS_EST; 01866 h.omsg[1] = 0; 01867 } else { 01868 h.omsg[0] = DLL1_SMS_EST | DLL1_SMS_COMPLETE; 01869 h.omsg[1] = 0; 01870 } 01871 sms_messagetx(&h); 01872 } 01873 01874 if (chan->_state != AST_STATE_UP) 01875 ast_answer(chan); 01876 01877 res = ast_set_write_format(chan, __OUT_FMT); 01878 if (res >= 0) 01879 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 01880 if (res < 0) { 01881 ast_log(LOG_ERROR, "Unable to set to linear mode, giving up\n"); 01882 goto done; 01883 } 01884 01885 if ( (res = ast_activate_generator(chan, &smsgen, &h)) < 0) { 01886 ast_log(LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name); 01887 goto done; 01888 } 01889 01890 /* Do our thing here */ 01891 for (;;) { 01892 struct ast_frame *f; 01893 int i = ast_waitfor(chan, -1); 01894 if (i < 0) { 01895 ast_log(LOG_NOTICE, "waitfor failed\n"); 01896 break; 01897 } 01898 if (h.hangup) { 01899 ast_log(LOG_NOTICE, "channel hangup\n"); 01900 break; 01901 } 01902 f = ast_read(chan); 01903 if (!f) { 01904 ast_log(LOG_NOTICE, "ast_read failed\n"); 01905 break; 01906 } 01907 if (f->frametype == AST_FRAME_VOICE) { 01908 sms_process(&h, f->samples, f->data); 01909 } 01910 01911 ast_frfree(f); 01912 } 01913 res = h.err; /* XXX */ 01914 01915 sms_log(&h, '?'); /* log incomplete message */ 01916 done: 01917 return (res); 01918 }
static int sms_generate | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
outgoing data are produced by this generator function, that reads from the descriptor whether it has data to send and which ones.
Definition at line 1483 of file app_sms.c.
References __OUT_FMT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), DLL2_SMS_EST, f, LOG_WARNING, MAXSAMPLES, sms_s::obyte, sms_s::obyten, sms_s::obytep, sms_s::omsg, sms_s::opause, sms_s::ophase, sms_s::ophasep, sms_s::oseizure, sms_s::osync, and sms_s::protocol.
01484 { 01485 struct ast_frame f = { 0 }; 01486 #define MAXSAMPLES (800) 01487 output_t *buf; 01488 sms_t *h = data; 01489 int i; 01490 01491 if (samples > MAXSAMPLES) { 01492 ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", 01493 MAXSAMPLES, samples); 01494 samples = MAXSAMPLES; 01495 } 01496 len = samples * sizeof(*buf) + AST_FRIENDLY_OFFSET; 01497 buf = alloca(len); 01498 01499 f.frametype = AST_FRAME_VOICE; 01500 f.subclass = __OUT_FMT; 01501 f.datalen = samples * sizeof(*buf); 01502 f.offset = AST_FRIENDLY_OFFSET; 01503 f.mallocd = 0; 01504 f.data = buf; 01505 f.samples = samples; 01506 f.src = "app_sms"; 01507 /* create a buffer containing the digital sms pattern */ 01508 for (i = 0; i < samples; i++) { 01509 buf[i] = wave_out[0]; /* default is silence */ 01510 01511 if (h->opause) 01512 h->opause--; 01513 else if (h->obyten || h->osync) { /* sending data */ 01514 buf[i] = wave_out[h->ophase]; 01515 h->ophase += (h->obyte & 1) ? 13 : 21; /* compute next phase */ 01516 if (h->ophase >= 80) 01517 h->ophase -= 80; 01518 if ((h->ophasep += 12) >= 80) { /* time to send the next bit */ 01519 h->ophasep -= 80; 01520 if (h->oseizure > 0) { /* sending channel seizure (proto 2) */ 01521 h->oseizure--; 01522 h->obyte ^= 1; /* toggle low bit */ 01523 } else if (h->osync) { 01524 h->obyte = 1; /* send mark as sync bit */ 01525 h->osync--; /* sending sync bits */ 01526 if (h->osync == 0 && h->protocol == 2 && h->omsg[0] == DLL2_SMS_EST) { 01527 h->obytep = h->obyten = 0; /* we are done */ 01528 } 01529 } else { 01530 h->obitp++; 01531 if (h->obitp == 1) 01532 h->obyte = 0; /* start bit; */ 01533 else if (h->obitp == 2) 01534 h->obyte = h->omsg[h->obytep]; 01535 else if (h->obitp == 10) { 01536 h->obyte = 1; /* stop bit */ 01537 h->obitp = 0; 01538 h->obytep++; 01539 if (h->obytep == h->obyten) { 01540 h->obytep = h->obyten = 0; /* sent */ 01541 h->osync = 10; /* trailing marks */ 01542 } 01543 } else 01544 h->obyte >>= 1; 01545 } 01546 } 01547 } 01548 } 01549 if (ast_write(chan, &f) < 0) { 01550 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno)); 01551 return -1; 01552 } 01553 return 0; 01554 #undef MAXSAMPLES 01555 }
static unsigned char sms_handleincoming | ( | sms_t * | h | ) | [static] |
handle the incoming message
Definition at line 1016 of file app_sms.c.
References ast_copy_string(), ast_log(), ast_tvnow(), 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().
01017 { 01018 unsigned char p = 3; 01019 if (h->smsc) { /* SMSC */ 01020 if ((h->imsg[2] & 3) == 1) { /* SMS-SUBMIT */ 01021 h->udhl = h->udl = 0; 01022 h->vp = 0; 01023 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0); 01024 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0); 01025 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0); 01026 ast_copy_string(h->oa, h->cli, sizeof(h->oa)); 01027 h->scts = ast_tvnow(); 01028 h->mr = h->imsg[p++]; 01029 p += unpackaddress(h->da, h->imsg + p); 01030 h->pid = h->imsg[p++]; 01031 h->dcs = h->imsg[p++]; 01032 if ((h->imsg[2] & 0x18) == 0x10) { /* relative VP */ 01033 if (h->imsg[p] < 144) 01034 h->vp = (h->imsg[p] + 1) * 5; 01035 else if (h->imsg[p] < 168) 01036 h->vp = 720 + (h->imsg[p] - 143) * 30; 01037 else if (h->imsg[p] < 197) 01038 h->vp = (h->imsg[p] - 166) * 1440; 01039 else 01040 h->vp = (h->imsg[p] - 192) * 10080; 01041 p++; 01042 } else if (h->imsg[2] & 0x18) 01043 p += 7; /* ignore enhanced / absolute VP */ 01044 p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi); 01045 h->rx = 1; /* received message */ 01046 sms_writefile(h); /* write the file */ 01047 if (p != h->imsg[1] + 2) { 01048 ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2); 01049 return 0xFF; /* duh! */ 01050 } 01051 } else { 01052 ast_log(LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]); 01053 return 0xFF; 01054 } 01055 } else { /* client */ 01056 if (!(h->imsg[2] & 3)) { /* SMS-DELIVER */ 01057 *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0; 01058 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0); 01059 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0); 01060 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0); 01061 h->mr = -1; 01062 p += unpackaddress(h->oa, h->imsg + p); 01063 h->pid = h->imsg[p++]; 01064 h->dcs = h->imsg[p++]; 01065 h->scts = unpackdate(h->imsg + p); 01066 p += 7; 01067 p += unpacksms(h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi); 01068 h->rx = 1; /* received message */ 01069 sms_writefile(h); /* write the file */ 01070 if (p != h->imsg[1] + 2) { 01071 ast_log(LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2); 01072 return 0xFF; /* duh! */ 01073 } 01074 } else { 01075 ast_log(LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]); 01076 return 0xFF; 01077 } 01078 } 01079 return 0; /* no error */ 01080 }
static int sms_handleincoming_proto2 | ( | sms_t * | h | ) | [static] |
sms_handleincoming_proto2: handle the incoming message
Definition at line 1159 of file app_sms.c.
References ast_copy_string(), ast_localtime(), ast_mktime(), ast_tvnow(), ast_verb, sms_s::da, f, sms_s::imsg, MAX_DEBUG_LEN, msg, sms_s::oa, sms_s::rx, sms_s::scts, sms_hexdump(), sms_writefile(), ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, sms_s::ud, and sms_s::udl.
Referenced by sms_messagerx2().
01160 { 01161 int f, i, sz = 0; 01162 int msg, msgsz; 01163 struct ast_tm tm; 01164 struct timeval tv = { 0, 0 }; 01165 char debug_buf[MAX_DEBUG_LEN * 3 + 1]; 01166 01167 sz = h->imsg[1] + 2; 01168 /* ast_verb(3, "SMS-P2 Frame: %s\n", sms_hexdump(h->imsg, sz, debug_buf)); */ 01169 01170 /* Parse message body (called payload) */ 01171 tv = h->scts = ast_tvnow(); 01172 for (f = 4; f < sz; ) { 01173 msg = h->imsg[f++]; 01174 msgsz = h->imsg[f++]; 01175 msgsz += (h->imsg[f++] * 256); 01176 switch (msg) { 01177 case 0x13: /* Body */ 01178 ast_verb(3, "SMS-P2 Body#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]); 01179 if (msgsz >= sizeof(h->imsg)) 01180 msgsz = sizeof(h->imsg) - 1; 01181 for (i = 0; i < msgsz; i++) 01182 h->ud[i] = h->imsg[f + i]; 01183 h->udl = msgsz; 01184 break; 01185 case 0x14: /* Date SCTS */ 01186 tv = h->scts = ast_tvnow(); 01187 ast_localtime(&tv, &tm, NULL); 01188 tm.tm_mon = ( (h->imsg[f] * 10) + h->imsg[f + 1] ) - 1; 01189 tm.tm_mday = ( (h->imsg[f + 2] * 10) + h->imsg[f + 3] ); 01190 tm.tm_hour = ( (h->imsg[f + 4] * 10) + h->imsg[f + 5] ); 01191 tm.tm_min = ( (h->imsg[f + 6] * 10) + h->imsg[f + 7] ); 01192 tm.tm_sec = 0; 01193 h->scts = ast_mktime(&tm, NULL); 01194 ast_verb(3, "SMS-P2 Date#%02X=%02d/%02d %02d:%02d\n", msg, tm.tm_mday, tm.tm_mon + 1, tm.tm_hour, tm.tm_min); 01195 break; 01196 case 0x15: /* Calling line (from SMSC) */ 01197 if (msgsz >= 20) 01198 msgsz = 20 - 1; 01199 ast_verb(3, "SMS-P2 Origin#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]); 01200 ast_copy_string(h->oa, (char *)(&h->imsg[f]), msgsz + 1); 01201 break; 01202 case 0x18: /* Destination(from TE/phone) */ 01203 if (msgsz >= 20) 01204 msgsz = 20 - 1; 01205 ast_verb(3, "SMS-P2 Destination#%02X=[%.*s]\n", msg, msgsz, &h->imsg[f]); 01206 ast_copy_string(h->da, (char *)(&h->imsg[f]), msgsz + 1); 01207 break; 01208 case 0x1C: /* Notify */ 01209 ast_verb(3, "SMS-P2 Notify#%02X=%s\n", msg, sms_hexdump(&h->imsg[f], 3, debug_buf)); 01210 break; 01211 default: 01212 ast_verb(3, "SMS-P2 Par#%02X [%d]: %s\n", msg, msgsz, sms_hexdump(&h->imsg[f], msgsz, debug_buf)); 01213 break; 01214 } 01215 f+=msgsz; /* Skip to next */ 01216 } 01217 h->rx = 1; /* received message */ 01218 sms_writefile(h); /* write the file */ 01219 return 0; /* no error */ 01220 }
static char* sms_hexdump | ( | unsigned char | buf[], | |
int | size, | |||
char * | s | |||
) | [static] |
Definition at line 1147 of file app_sms.c.
References f, and MAX_DEBUG_LEN.
Referenced by sms_handleincoming_proto2().
01148 { 01149 char *p; 01150 int f; 01151 01152 for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3) 01153 sprintf(p, "%02X ", (unsigned char)buf[f]); 01154 return(s); 01155 }
static void sms_log | ( | sms_t * | h, | |
char | status | |||
) | [static] |
Log the output, and remove file.
Definition at line 712 of file app_sms.c.
References AST_FILE_MODE, buf, sms_s::da, isodate(), sms_s::mr, sms_s::oa, sms_s::queue, sms_s::rx, S_OR, sms_s::smsc, sms_s::ud, and sms_s::udl.
Referenced by sms_messagerx(), and sms_messagerx2().
00713 { 00714 int o; 00715 00716 if (*h->oa == '\0' && *h->da == '\0') 00717 return; 00718 o = open(log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE); 00719 if (o >= 0) { 00720 char line[1000], mrs[3] = "", *p; 00721 char buf[30]; 00722 unsigned char n; 00723 00724 if (h->mr >= 0) 00725 snprintf(mrs, sizeof(mrs), "%02X", h->mr); 00726 snprintf(line, sizeof(line), "%s %c%c%c%s %s %s %s ", 00727 isodate(time(NULL), buf, sizeof(buf)), 00728 status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue, 00729 S_OR(h->oa, "-"), S_OR(h->da, "-") ); 00730 p = line + strlen(line); 00731 for (n = 0; n < h->udl; n++) { 00732 if (h->ud[n] == '\\') { 00733 *p++ = '\\'; 00734 *p++ = '\\'; 00735 } else if (h->ud[n] == '\n') { 00736 *p++ = '\\'; 00737 *p++ = 'n'; 00738 } else if (h->ud[n] == '\r') { 00739 *p++ = '\\'; 00740 *p++ = 'r'; 00741 } else if (h->ud[n] < 32 || h->ud[n] == 127) 00742 *p++ = 191; 00743 else 00744 *p++ = h->ud[n]; 00745 } 00746 *p++ = '\n'; 00747 *p = 0; 00748 if (write(o, line, strlen(line)) < 0) { 00749 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00750 } 00751 close(o); 00752 } 00753 *h->oa = *h->da = h->udl = 0; 00754 }
static void sms_messagerx | ( | sms_t * | h | ) | [static] |
Definition at line 1389 of file app_sms.c.
References DIR_RX, sms_s::err, sms_s::hangup, sms_s::imsg, sms_s::omsg, sms_s::protocol, sms_debug(), sms_handleincoming(), sms_log(), sms_messagerx2(), sms_messagetx(), and sms_nextoutgoing().
01390 { 01391 int cause; 01392 01393 sms_debug (DIR_RX, h); 01394 if (h->protocol == 2) { 01395 sms_messagerx2(h); 01396 return; 01397 } 01398 /* parse incoming message for Protocol 1 */ 01399 switch (h->imsg[0]) { 01400 case 0x91: /* SMS_DATA */ 01401 cause = sms_handleincoming (h); 01402 if (!cause) { 01403 sms_log(h, 'Y'); 01404 h->omsg[0] = 0x95; /* SMS_ACK */ 01405 h->omsg[1] = 0x02; 01406 h->omsg[2] = 0x00; /* deliver report */ 01407 h->omsg[3] = 0x00; /* no parameters */ 01408 } else { /* NACK */ 01409 sms_log(h, 'N'); 01410 h->omsg[0] = 0x96; /* SMS_NACK */ 01411 h->omsg[1] = 3; 01412 h->omsg[2] = 0; /* delivery report */ 01413 h->omsg[3] = cause; /* cause */ 01414 h->omsg[4] = 0; /* no parameters */ 01415 } 01416 sms_messagetx(h); 01417 break; 01418 01419 case 0x92: /* SMS_ERROR */ 01420 h->err = 1; 01421 sms_messagetx(h); /* send whatever we sent again */ 01422 break; 01423 case 0x93: /* SMS_EST */ 01424 sms_nextoutgoing (h); 01425 break; 01426 case 0x94: /* SMS_REL */ 01427 h->hangup = 1; /* hangup */ 01428 break; 01429 case 0x95: /* SMS_ACK */ 01430 sms_log(h, 'Y'); 01431 sms_nextoutgoing (h); 01432 break; 01433 case 0x96: /* SMS_NACK */ 01434 h->err = 1; 01435 sms_log(h, 'N'); 01436 sms_nextoutgoing (h); 01437 break; 01438 default: /* Unknown */ 01439 h->omsg[0] = 0x92; /* SMS_ERROR */ 01440 h->omsg[1] = 1; 01441 h->omsg[2] = 3; /* unknown message type; */ 01442 sms_messagetx(h); 01443 break; 01444 } 01445 }
static void sms_messagerx2 | ( | sms_t * | h | ) | [static] |
Definition at line 1236 of file app_sms.c.
References ast_log(), DLL2_ACK, DLL2_SMS_ACK0, DLL2_SMS_ACK1, DLL2_SMS_EST, DLL2_SMS_INFO_MO, DLL2_SMS_INFO_MT, DLL2_SMS_NACK, DLL2_SMS_REL, DLL_SMS_MASK, sms_s::imsg, LOG_NOTICE, sms_handleincoming_proto2(), sms_log(), sms_messagetx(), and sms_nextoutgoing().
Referenced by sms_messagerx().
01237 { 01238 int p = h->imsg[0] & DLL_SMS_MASK ; /* mask the high bit */ 01239 int cause; 01240 01241 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1) 01242 switch (p) { 01243 case DLL2_SMS_EST: /* Protocol 2: Connection ready (fake): send message */ 01244 sms_nextoutgoing (h); 01245 /* smssend(h,"11 29 27 00 10 01 00 00 11 06 00 00 00 00 00 00 00 12 03 00 02 00 04 13 01 00 41 14 08 00 30 39 31 35 30 02 30 02 15 02 00 39 30 "); */ 01246 break; 01247 01248 case DLL2_SMS_INFO_MO: /* transport SMS_SUBMIT */ 01249 case DLL2_SMS_INFO_MT: /* transport SMS_DELIVERY */ 01250 cause = sms_handleincoming_proto2(h); 01251 if (!cause) /* ACK */ 01252 sms_log(h, 'Y'); 01253 h->omsg[0] = DLL2_ACK(h); 01254 h->omsg[1] = 0x06; /* msg len */ 01255 h->omsg[2] = 0x04; /* payload len */ 01256 h->omsg[3] = 0x00; /* payload len */ 01257 h->omsg[4] = 0x1f; /* Response type */ 01258 h->omsg[5] = 0x01; /* parameter len */ 01259 h->omsg[6] = 0x00; /* parameter len */ 01260 h->omsg[7] = cause; /* CONFIRM or error */ 01261 sms_messagetx(h); 01262 break; 01263 01264 case DLL2_SMS_NACK: /* Protocol 2: SMS_NAK */ 01265 h->omsg[0] = DLL2_SMS_REL; /* SMS_REL */ 01266 h->omsg[1] = 0x00; /* msg len */ 01267 sms_messagetx(h); 01268 break; 01269 01270 case DLL2_SMS_ACK0: 01271 case DLL2_SMS_ACK1: 01272 /* SMS_ACK also transport SMS_SUBMIT or SMS_DELIVERY */ 01273 if ( (h->omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) { 01274 /* a response to our Release, just hangup */ 01275 h->hangup = 1; /* hangup */ 01276 } else { 01277 /* XXX depending on what we are.. */ 01278 ast_log(LOG_NOTICE, "SMS_SUBMIT or SMS_DELIVERY"); 01279 sms_nextoutgoing (h); 01280 } 01281 break; 01282 01283 case DLL2_SMS_REL: /* Protocol 2: SMS_REL (hangup req) */ 01284 h->omsg[0] = DLL2_ACK(h); 01285 h->omsg[1] = 0; 01286 sms_messagetx(h); 01287 break; 01288 } 01289 }
static void sms_messagetx | ( | sms_t * | h | ) | [static] |
Definition at line 1447 of file app_sms.c.
References DIR_TX, sms_s::framenumber, len(), sms_s::obitp, sms_s::obyte, sms_s::obytep, sms_s::omsg, sms_s::opause, sms_s::opause_0, sms_s::oseizure, sms_s::protocol, and sms_debug().
Referenced by sms_messagerx(), sms_messagerx2(), sms_nextoutgoing(), and sms_process().
01448 { 01449 unsigned char c = 0, p; 01450 int len = h->omsg[1] + 2; /* total message length excluding checksum */ 01451 01452 for (p = 0; p < len; p++) /* compute checksum */ 01453 c += h->omsg[p]; 01454 h->omsg[len] = 0 - c; /* actually, (256 - (c & 0fxx)) & 0xff) */ 01455 sms_debug(DIR_TX, h); 01456 h->framenumber++; /* Proto 2 */ 01457 h->obyte = 1; /* send mark ('1') at the beginning */ 01458 h->opause = 200; 01459 /* Change the initial message delay. BT requires 300ms, 01460 * but for others this might be way too much and the phone 01461 * could time out. XXX make it configurable. 01462 */ 01463 if (h->omsg[0] == 0x93) 01464 h->opause = 8 * h->opause_0; /* initial message delay */ 01465 h->obytep = 0; 01466 h->obitp = 0; 01467 if (h->protocol == 2) { 01468 h->oseizure = 300; /* Proto 2: 300bits (or more ?) */ 01469 h->obyte = 0; /* Seizure starts with space (0) */ 01470 h->opause = 400; 01471 } else { 01472 h->oseizure = 0; /* Proto 1: No seizure */ 01473 } 01474 /* Note - setting osync triggers the generator */ 01475 h->osync = OSYNC_BITS; /* 80 sync bits */ 01476 h->obyten = len + 1; /* bytes to send (including checksum) */ 01477 }
static void sms_nextoutgoing | ( | sms_t * | h | ) | [static] |
find and fill in next message, or send a REL if none waiting
Definition at line 1332 of file app_sms.c.
References ast_config_AST_SPOOL_DIR, ast_mkdir(), sms_s::da, sms_s::oa, sms_s::omsg, sms_s::protocol, sms_s::queue, readdirqueue(), sms_s::rx, sms_compose1(), sms_compose2(), sms_messagetx(), sms_readfile(), and sms_s::smsc.
Referenced by sms_messagerx(), and sms_messagerx2().
01333 { 01334 char fn[100 + NAME_MAX] = ""; 01335 DIR *d; 01336 char more = 0; 01337 01338 *h->da = *h->oa = '\0'; /* clear destinations */ 01339 h->rx = 0; /* outgoing message */ 01340 snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? "mttx" : "motx"); 01341 ast_mkdir(fn, 0777); /* ensure it exists */ 01342 d = opendir(fn); 01343 if (d) { 01344 struct dirent *f = readdirqueue(d, h->queue); 01345 if (f) { 01346 snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/%s", f->d_name); 01347 sms_readfile(h, fn); 01348 if (readdirqueue(d, h->queue)) 01349 more = 1; /* more to send */ 01350 } 01351 closedir(d); 01352 } 01353 if (*h->da || *h->oa) { /* message to send */ 01354 if (h->protocol == 2) 01355 sms_compose2(h, more); 01356 else 01357 sms_compose1(h, more); 01358 } else { /* no message */ 01359 if (h->protocol == 2) { 01360 h->omsg[0] = 0x17; /* SMS_REL */ 01361 h->omsg[1] = 0; 01362 } else { 01363 h->omsg[0] = 0x94; /* SMS_REL */ 01364 h->omsg[1] = 0; 01365 } 01366 } 01367 sms_messagetx(h); 01368 }
static void sms_process | ( | sms_t * | h, | |
int | samples, | |||
signed short * | data | |||
) | [static] |
Process an incoming frame, trying to detect the carrier and decode the message. The two frequencies are 1300 and 2100 Hz. The decoder detects the amplitude of the signal over the last few samples, filtering the absolute values with a lowpass filter. If the magnitude (h->imag) is large enough, multiply the signal by the two carriers, and compute the amplitudes m0 and m1. Record the current sample as '0' or '1' depending on which one is greater. The last 3 bits are stored in h->ibith, with the count of '1' bits in h->ibitt. XXX the rest is to be determined.
Definition at line 1588 of file app_sms.c.
References ast_log(), sms_s::err, sms_s::hangup, sms_s::idle, sms_s::ierr, sms_s::imag, LOG_NOTICE, m1, sms_s::obyten, sms_s::omsg, sms_s::osync, and sms_messagetx().
01589 { 01590 int bit; 01591 01592 /* 01593 * Ignore incoming audio while a packet is being transmitted, 01594 * the protocol is half-duplex. 01595 * Unfortunately this means that if the outbound and incoming 01596 * transmission overlap (which is an error condition anyways), 01597 * we may miss some data and this makes debugging harder. 01598 */ 01599 if (h->obyten || h->osync) 01600 return; 01601 for ( ; samples-- ; data++) { 01602 unsigned long long m0, m1; 01603 if (abs(*data) > h->imag) 01604 h->imag = abs(*data); 01605 else 01606 h->imag = h->imag * 7 / 8; 01607 if (h->imag <= 500) { /* below [arbitrary] threahold: lost carrier */ 01608 if (h->idle++ == 80000) { /* nothing happening */ 01609 ast_log(LOG_NOTICE, "No data, hanging up\n"); 01610 h->hangup = 1; 01611 h->err = 1; 01612 } 01613 if (h->ierr) { /* error */ 01614 ast_log(LOG_NOTICE, "Error %d, hanging up\n", h->ierr); 01615 /* Protocol 1 */ 01616 h->err = 1; 01617 h->omsg[0] = 0x92; /* error */ 01618 h->omsg[1] = 1; 01619 h->omsg[2] = h->ierr; 01620 sms_messagetx(h); /* send error */ 01621 } 01622 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0; 01623 continue; 01624 } 01625 h->idle = 0; 01626 01627 /* multiply signal by the two carriers. */ 01628 h->ims0 = (h->ims0 * 6 + *data * wave[h->ips0]) / 7; 01629 h->imc0 = (h->imc0 * 6 + *data * wave[h->ipc0]) / 7; 01630 h->ims1 = (h->ims1 * 6 + *data * wave[h->ips1]) / 7; 01631 h->imc1 = (h->imc1 * 6 + *data * wave[h->ipc1]) / 7; 01632 /* compute the amplitudes */ 01633 m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0; 01634 m1 = h->ims1 * h->ims1 + h->imc1 * h->imc1; 01635 01636 /* advance the sin/cos pointers */ 01637 if ((h->ips0 += 21) >= 80) 01638 h->ips0 -= 80; 01639 if ((h->ipc0 += 21) >= 80) 01640 h->ipc0 -= 80; 01641 if ((h->ips1 += 13) >= 80) 01642 h->ips1 -= 80; 01643 if ((h->ipc1 += 13) >= 80) 01644 h->ipc1 -= 80; 01645 01646 /* set new bit to 1 or 0 depending on which value is stronger */ 01647 h->ibith <<= 1; 01648 if (m1 > m0) 01649 h->ibith |= 1; 01650 if (h->ibith & 8) 01651 h->ibitt--; 01652 if (h->ibith & 1) 01653 h->ibitt++; 01654 bit = ((h->ibitt > 1) ? 1 : 0); 01655 if (bit != h->ibitl) 01656 h->ibitc = 1; 01657 else 01658 h->ibitc++; 01659 h->ibitl = bit; 01660 if (!h->ibitn && h->ibitc == 4 && !bit) { 01661 h->ibitn = 1; 01662 h->iphasep = 0; 01663 } 01664 if (bit && h->ibitc == 200) { /* sync, restart message */ 01665 /* Protocol 2: empty connnection ready (I am master) */ 01666 if (h->framenumber < 0 && h->ibytec >= 160 && !memcmp(h->imsg, "UUUUUUUUUUUUUUUUUUUU", 20)) { 01667 h->framenumber = 1; 01668 ast_verb(3, "SMS protocol 2 detected\n"); 01669 h->protocol = 2; 01670 h->imsg[0] = 0xff; /* special message (fake) */ 01671 h->imsg[1] = h->imsg[2] = 0x00; 01672 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0; 01673 sms_messagerx(h); 01674 } 01675 h->ierr = h->ibitn = h->ibytep = h->ibytec = 0; 01676 } 01677 if (h->ibitn) { 01678 h->iphasep += 12; 01679 if (h->iphasep >= 80) { /* next bit */ 01680 h->iphasep -= 80; 01681 if (h->ibitn++ == 9) { /* end of byte */ 01682 if (!bit) { /* bad stop bit */ 01683 ast_log(LOG_NOTICE, "bad stop bit"); 01684 h->ierr = 0xFF; /* unknown error */ 01685 } else { 01686 if (h->ibytep < sizeof(h->imsg)) { 01687 h->imsg[h->ibytep] = h->ibytev; 01688 h->ibytec += h->ibytev; 01689 h->ibytep++; 01690 } else if (h->ibytep == sizeof(h->imsg)) { 01691 ast_log(LOG_NOTICE, "msg too large"); 01692 h->ierr = 2; /* bad message length */ 01693 } 01694 if (h->ibytep > 1 && h->ibytep == 3 + h->imsg[1] && !h->ierr) { 01695 if (!h->ibytec) 01696 sms_messagerx(h); 01697 else { 01698 ast_log(LOG_NOTICE, "bad checksum"); 01699 h->ierr = 1; /* bad checksum */ 01700 } 01701 } 01702 } 01703 h->ibitn = 0; 01704 } 01705 h->ibytev = (h->ibytev >> 1) + (bit ? 0x80 : 0); 01706 } 01707 } 01708 } 01709 }
static void sms_readfile | ( | sms_t * | h, | |
char * | fn | |||
) | [static] |
parse and delete a file
Definition at line 757 of file app_sms.c.
References ast_log(), ast_mktime(), ast_tvnow(), 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, pp, sms_s::rp, sms_s::rx, S, s, sms_s::scts, SMSLEN, sms_s::srr, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, sms_s::ud, sms_s::udh, sms_s::udhi, sms_s::udhl, sms_s::udl, sms_s::udtxt, utf8decode(), and sms_s::vp.
Referenced by sms_nextoutgoing().
00758 { 00759 char line[1000]; 00760 FILE *s; 00761 char dcsset = 0; /* if DSC set */ 00762 ast_log(LOG_EVENT, "Sending %s\n", fn); 00763 h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0; 00764 h->mr = -1; 00765 h->dcs = 0xF1; /* normal messages class 1 */ 00766 h->scts = ast_tvnow(); 00767 s = fopen(fn, "r"); 00768 if (s) { 00769 if (unlink(fn)) { /* concurrent access, we lost */ 00770 fclose(s); 00771 return; 00772 } 00773 while (fgets (line, sizeof(line), s)) { /* process line in file */ 00774 char *p; 00775 void *pp = &p; 00776 for (p = line; *p && *p != '\n' && *p != '\r'; p++); 00777 *p = 0; /* strip eoln */ 00778 p = line; 00779 if (!*p || *p == ';') 00780 continue; /* blank line or comment, ignore */ 00781 while (isalnum(*p)) { 00782 *p = tolower (*p); 00783 p++; 00784 } 00785 while (isspace (*p)) 00786 *p++ = 0; 00787 if (*p == '=') { 00788 *p++ = 0; 00789 if (!strcmp(line, "ud")) { /* parse message (UTF-8) */ 00790 unsigned char o = 0; 00791 memcpy(h->udtxt, p, SMSLEN); /* for protocol 2 */ 00792 while (*p && o < SMSLEN) 00793 h->ud[o++] = utf8decode(pp); 00794 h->udl = o; 00795 if (*p) 00796 ast_log(LOG_WARNING, "UD too long in %s\n", fn); 00797 } else { 00798 while (isspace (*p)) 00799 p++; 00800 if (!strcmp(line, "oa") && strlen(p) < sizeof(h->oa)) 00801 numcpy (h->oa, p); 00802 else if (!strcmp(line, "da") && strlen(p) < sizeof(h->oa)) 00803 numcpy (h->da, p); 00804 else if (!strcmp(line, "pid")) 00805 h->pid = atoi(p); 00806 else if (!strcmp(line, "dcs")) { 00807 h->dcs = atoi(p); 00808 dcsset = 1; 00809 } else if (!strcmp(line, "mr")) 00810 h->mr = atoi(p); 00811 else if (!strcmp(line, "srr")) 00812 h->srr = (atoi(p) ? 1 : 0); 00813 else if (!strcmp(line, "vp")) 00814 h->vp = atoi(p); 00815 else if (!strcmp(line, "rp")) 00816 h->rp = (atoi(p) ? 1 : 0); 00817 else if (!strcmp(line, "scts")) { /* get date/time */ 00818 int Y, 00819 m, 00820 d, 00821 H, 00822 M, 00823 S; 00824 if (sscanf (p, "%d-%d-%dT%d:%d:%d", &Y, &m, &d, &H, &M, &S) == 6) { 00825 struct ast_tm t = { 0, }; 00826 t.tm_year = Y - 1900; 00827 t.tm_mon = m - 1; 00828 t.tm_mday = d; 00829 t.tm_hour = H; 00830 t.tm_min = M; 00831 t.tm_sec = S; 00832 t.tm_isdst = -1; 00833 h->scts = ast_mktime(&t, NULL); 00834 if (h->scts.tv_sec == 0) 00835 ast_log(LOG_WARNING, "Bad date/timein %s: %s", fn, p); 00836 } 00837 } else 00838 ast_log(LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p); 00839 } 00840 } else if (*p == '#') { /* raw hex format */ 00841 *p++ = 0; 00842 if (*p == '#') { 00843 p++; 00844 if (!strcmp(line, "ud")) { /* user data */ 00845 int o = 0; 00846 while (*p && o < SMSLEN) { 00847 if (isxdigit(*p) && isxdigit(p[1]) && isxdigit(p[2]) && isxdigit(p[3])) { 00848 h->ud[o++] = 00849 (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 12) + 00850 (((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) + 00851 (((isalpha(p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha(p[3]) ? 9 : 0) + (p[3] & 0xF)); 00852 p += 4; 00853 } else 00854 break; 00855 } 00856 h->udl = o; 00857 if (*p) 00858 ast_log(LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn); 00859 } else 00860 ast_log(LOG_WARNING, "Only ud can use ## format, %s\n", fn); 00861 } else if (!strcmp(line, "ud")) { /* user data */ 00862 int o = 0; 00863 while (*p && o < SMSLEN) { 00864 if (isxdigit(*p) && isxdigit(p[1])) { 00865 h->ud[o++] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)); 00866 p += 2; 00867 } else 00868 break; 00869 } 00870 h->udl = o; 00871 if (*p) 00872 ast_log(LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn); 00873 } else if (!strcmp(line, "udh")) { /* user data header */ 00874 unsigned char o = 0; 00875 h->udhi = 1; 00876 while (*p && o < SMSLEN) { 00877 if (isxdigit(*p) && isxdigit(p[1])) { 00878 h->udh[o] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)); 00879 o++; 00880 p += 2; 00881 } else 00882 break; 00883 } 00884 h->udhl = o; 00885 if (*p) 00886 ast_log(LOG_WARNING, "UDH too long / invalid hex in %s\n", fn); 00887 } else 00888 ast_log(LOG_WARNING, "Only ud and udh can use # format, %s\n", fn); 00889 } else 00890 ast_log(LOG_WARNING, "Cannot parse in %s: %s\n", fn, line); 00891 } 00892 fclose(s); 00893 if (!dcsset && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) { 00894 if (packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) { 00895 if (packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) 00896 ast_log(LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn); 00897 else { 00898 h->dcs = 0x08; /* default to 16 bit */ 00899 ast_log(LOG_WARNING, "Sending in 16 bit format(%s)\n", fn); 00900 } 00901 } else { 00902 h->dcs = 0xF5; /* default to 8 bit */ 00903 ast_log(LOG_WARNING, "Sending in 8 bit format(%s)\n", fn); 00904 } 00905 } 00906 if (is7bit(h->dcs) && packsms7(0, h->udhl, h->udh, h->udl, h->ud) < 0) 00907 ast_log(LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn); 00908 if (is8bit(h->dcs) && packsms8(0, h->udhl, h->udh, h->udl, h->ud) < 0) 00909 ast_log(LOG_WARNING, "Invalid 8 bit data %s\n", fn); 00910 if (is16bit(h->dcs) && packsms16(0, h->udhl, h->udh, h->udl, h->ud) < 0) 00911 ast_log(LOG_WARNING, "Invalid 16 bit data %s\n", fn); 00912 } 00913 }
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 916 of file app_sms.c.
References ast_config_AST_SPOOL_DIR, ast_copy_string(), ast_mkdir(), buf, 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(), and sms_handleincoming_proto2().
00917 { 00918 char fn[200] = "", fn2[200] = ""; 00919 char buf[30]; 00920 FILE *o; 00921 00922 snprintf(fn, sizeof(fn), "%s/sms/%s", ast_config_AST_SPOOL_DIR, h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx"); 00923 ast_mkdir(fn, 0777); /* ensure it exists */ 00924 ast_copy_string(fn2, fn, sizeof(fn2)); 00925 snprintf(fn2 + strlen(fn2), sizeof(fn2) - strlen(fn2), "/%s.%s-%d", h->queue, isodate(h->scts.tv_sec, buf, sizeof(buf)), seq++); 00926 snprintf(fn + strlen(fn), sizeof(fn) - strlen(fn), "/.%s", fn2 + strlen(fn) + 1); 00927 o = fopen(fn, "w"); 00928 if (o == NULL) 00929 return; 00930 00931 if (*h->oa) 00932 fprintf(o, "oa=%s\n", h->oa); 00933 if (*h->da) 00934 fprintf(o, "da=%s\n", h->da); 00935 if (h->udhi) { 00936 unsigned int p; 00937 fprintf(o, "udh#"); 00938 for (p = 0; p < h->udhl; p++) 00939 fprintf(o, "%02X", h->udh[p]); 00940 fprintf(o, "\n"); 00941 } 00942 if (h->udl) { 00943 unsigned int p; 00944 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++); 00945 if (p < h->udl) 00946 fputc(';', o); /* cannot use ud=, but include as a comment for human readable */ 00947 fprintf(o, "ud="); 00948 for (p = 0; p < h->udl; p++) { 00949 unsigned short v = h->ud[p]; 00950 if (v < 32) 00951 fputc(191, o); 00952 else if (v < 0x80) 00953 fputc(v, o); 00954 else if (v < 0x800) 00955 { 00956 fputc(0xC0 + (v >> 6), o); 00957 fputc(0x80 + (v & 0x3F), o); 00958 } else 00959 { 00960 fputc(0xE0 + (v >> 12), o); 00961 fputc(0x80 + ((v >> 6) & 0x3F), o); 00962 fputc(0x80 + (v & 0x3F), o); 00963 } 00964 } 00965 fprintf(o, "\n"); 00966 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++); 00967 if (p < h->udl) { 00968 for (p = 0; p < h->udl && h->ud[p] < 0x100; p++); 00969 if (p == h->udl) { /* can write in ucs-1 hex */ 00970 fprintf(o, "ud#"); 00971 for (p = 0; p < h->udl; p++) 00972 fprintf(o, "%02X", h->ud[p]); 00973 fprintf(o, "\n"); 00974 } else { /* write in UCS-2 */ 00975 fprintf(o, "ud##"); 00976 for (p = 0; p < h->udl; p++) 00977 fprintf(o, "%04X", h->ud[p]); 00978 fprintf(o, "\n"); 00979 } 00980 } 00981 } 00982 if (h->scts.tv_sec) { 00983 char buf[30]; 00984 fprintf(o, "scts=%s\n", isodate(h->scts.tv_sec, buf, sizeof(buf))); 00985 } 00986 if (h->pid) 00987 fprintf(o, "pid=%d\n", h->pid); 00988 if (h->dcs != 0xF1) 00989 fprintf(o, "dcs=%d\n", h->dcs); 00990 if (h->vp) 00991 fprintf(o, "vp=%d\n", h->vp); 00992 if (h->srr) 00993 fprintf(o, "srr=1\n"); 00994 if (h->mr >= 0) 00995 fprintf(o, "mr=%d\n", h->mr); 00996 if (h->rp) 00997 fprintf(o, "rp=1\n"); 00998 fclose(o); 00999 if (rename(fn, fn2)) 01000 unlink(fn); 01001 else 01002 ast_log(LOG_EVENT, "Received to %s\n", fn2); 01003 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1920 of file app_sms.c.
References ast_unregister_application().
01921 { 01922 return ast_unregister_application(app); 01923 }
static unsigned char unpackaddress | ( | char * | o, | |
unsigned char * | i | |||
) | [static] |
unpack an address from i, return byte length, unpack to o
Definition at line 671 of file app_sms.c.
Referenced by sms_handleincoming().
00672 { 00673 unsigned char l = i[0], 00674 p; 00675 if (i[1] == 0x91) 00676 *o++ = '+'; 00677 for (p = 0; p < l; p++) { 00678 if (p & 1) 00679 *o++ = (i[2 + p / 2] >> 4) + '0'; 00680 else 00681 *o++ = (i[2 + p / 2] & 0xF) + '0'; 00682 } 00683 *o = 0; 00684 return (l + 5) / 2; 00685 }
static struct timeval unpackdate | ( | unsigned char * | i | ) | [static] |
unpack a date and return
Definition at line 531 of file app_sms.c.
References ast_mktime().
Referenced by sms_handleincoming().
00532 { 00533 struct ast_tm t; 00534 00535 t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4); 00536 t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1; 00537 t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4); 00538 t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4); 00539 t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4); 00540 t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4); 00541 t.tm_isdst = 0; 00542 if (i[6] & 0x08) 00543 t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4)); 00544 else 00545 t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4)); 00546 00547 return ast_mktime(&t, NULL); 00548 }
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 657 of file app_sms.c.
References is7bit, is8bit, unpacksms16(), unpacksms7(), and unpacksms8().
Referenced by sms_handleincoming().
00658 { 00659 int l = *i++; 00660 if (is7bit(dcs)) { 00661 unpacksms7(i, l, udh, udhl, ud, udl, udhi); 00662 l = (l * 7 + 7) / 8; /* adjust length to return */ 00663 } else if (is8bit(dcs)) 00664 unpacksms8(i, l, udh, udhl, ud, udl, udhi); 00665 else 00666 unpacksms16(i, l, udh, udhl, ud, udl, udhi); 00667 return l + 1; 00668 }
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 630 of file app_sms.c.
Referenced by unpacksms().
00631 { 00632 unsigned short *o = ud; 00633 *udhl = 0; 00634 if (udhi) { 00635 int n = *i; 00636 *udhl = n; 00637 if (n) { 00638 i++; 00639 l--; 00640 while (l && n) { 00641 l--; 00642 n--; 00643 *udh++ = *i++; 00644 } 00645 } 00646 } 00647 while (l--) { 00648 int v = *i++; 00649 if (l--) 00650 v = (v << 8) + *i++; 00651 *o++ = v; 00652 } 00653 *udl = (o - ud); 00654 }
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 553 of file app_sms.c.
Referenced by unpacksms().
00554 { 00555 unsigned char b = 0, p = 0; 00556 unsigned short *o = ud; 00557 *udhl = 0; 00558 if (udhi && l) { /* header */ 00559 int h = i[p]; 00560 *udhl = h; 00561 if (h) { 00562 b = 1; 00563 p++; 00564 l--; 00565 while (h-- && l) { 00566 *udh++ = i[p++]; 00567 b += 8; 00568 while (b >= 7) { 00569 b -= 7; 00570 l--; 00571 if (!l) 00572 break; 00573 } 00574 } 00575 /* adjust for fill, septets */ 00576 if (b) { 00577 b = 7 - b; 00578 l--; 00579 } 00580 } 00581 } 00582 while (l--) { 00583 unsigned char v; 00584 if (b < 2) 00585 v = ((i[p] >> b) & 0x7F); /* everything in one byte */ 00586 else 00587 v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F); 00588 b += 7; 00589 if (b >= 8) { 00590 b -= 8; 00591 p++; 00592 } 00593 /* 0x00A0 is the encoding of ESC (27) in defaultalphabet */ 00594 if (o > ud && o[-1] == 0x00A0 && escapes[v]) 00595 o[-1] = escapes[v]; 00596 else 00597 *o++ = defaultalphabet[v]; 00598 } 00599 *udl = (o - ud); 00600 }
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 605 of file app_sms.c.
Referenced by unpacksms().
00606 { 00607 unsigned short *o = ud; 00608 *udhl = 0; 00609 if (udhi) { 00610 int n = *i; 00611 *udhl = n; 00612 if (n) { 00613 i++; 00614 l--; 00615 while (l && n) { 00616 l--; 00617 n--; 00618 *udh++ = *i++; 00619 } 00620 } 00621 } 00622 while (l--) 00623 *o++ = *i++; /* not to UTF-8 as explicitly 8 bit coding in DCS */ 00624 *udl = (o - ud); 00625 }
static long utf8decode | ( | unsigned char ** | pp | ) | [static] |
Reads next UCS character from NUL terminated UTF-8 string and advance pointer.
Definition at line 283 of file app_sms.c.
Referenced by sms_readfile().
00284 { 00285 unsigned char *p = *pp; 00286 if (!*p) 00287 return 0; /* null termination of string */ 00288 (*pp)++; 00289 if (*p < 0xC0) 00290 return *p; /* ascii or continuation character */ 00291 if (*p < 0xE0) { 00292 if (*p < 0xC2 || (p[1] & 0xC0) != 0x80) 00293 return *p; /* not valid UTF-8 */ 00294 (*pp)++; 00295 return ((*p & 0x1F) << 6) + (p[1] & 0x3F); 00296 } 00297 if (*p < 0xF0) { 00298 if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80) 00299 return *p; /* not valid UTF-8 */ 00300 (*pp) += 2; 00301 return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F); 00302 } 00303 if (*p < 0xF8) { 00304 if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80) 00305 return *p; /* not valid UTF-8 */ 00306 (*pp) += 3; 00307 return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F); 00308 } 00309 if (*p < 0xFC) { 00310 if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80 00311 || (p[4] & 0xC0) != 0x80) 00312 return *p; /* not valid UTF-8 */ 00313 (*pp) += 4; 00314 return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F); 00315 } 00316 if (*p < 0xFE) { 00317 if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80 00318 || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80) 00319 return *p; /* not valid UTF-8 */ 00320 (*pp) += 5; 00321 return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F); 00322 } 00323 return *p; /* not sensible */ 00324 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .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 65 of file app_sms.c.
Referenced by __manager_event(), append_event(), ast_udptl_write(), handle_link_data(), handle_remote_data(), parsing(), process_cisco_dtmf(), send_retransmit(), and udptl_build_packet().
enum { ... } sms_flags |
Referenced by sms_exec().
enum { ... } sms_opt_args |
struct ast_app_option sms_options[128] = { [ 's' ] = { .flag = OPTION_BE_SMSC }, [ 'a' ] = { .flag = OPTION_ANSWER }, [ 't' ] = { .flag = OPTION_TWO }, [ 'r' ] = { .flag = OPTION_SRR }, [ 'o' ] = { .flag = OPTION_DCS }, [ 'p' ] = { .flag = OPTION_PAUSE , .arg_index = OPTION_ARG_PAUSE + 1 }, } [static] |
struct ast_generator smsgen [static] |
Initial value:
{ .alloc = sms_alloc, .release = sms_release, .generate = sms_generate, }
signed short wave[] [static] |