119 static volatile unsigned char message_ref;
120 static volatile unsigned int seq;
122 static char log_file[255];
124 static char *app =
"SMS";
132 static const signed short wave[] = {
133 0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
134 5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
135 0, -392, -782, -1167,
136 -1545, -1913, -2270, -2612, -2939, -3247, -3536, -3802, -4045, -4263, -4455, -4619, -4755, -4862, -4938, -4985, -5000,
138 -4755, -4619, -4455, -4263, -4045, -3802, -3536, -3247, -2939, -2612, -2270, -1913, -1545, -1167, -782, -392
142 static unsigned char wavea[80];
143 typedef unsigned char output_t;
144 static const output_t *wave_out = wavea;
145 #define __OUT_FMT ast_format_alaw
147 typedef signed short output_t;
148 static const output_t *wave_out = wave;
149 #define __OUT_FMT ast_format_slin
152 #define OSYNC_BITS 80
165 DLL1_SMS_DATA = 0x11,
166 DLL1_SMS_ERROR = 0x12,
170 DLL1_SMS_NACK = 0x16,
172 DLL1_SMS_COMPLETE = 0x80,
173 DLL1_SMS_MORE = 0x00,
177 DLL2_SMS_INFO_MO = 0x10,
178 DLL2_SMS_INFO_MT = 0x11,
179 DLL2_SMS_INFO_STA = 0x12,
180 DLL2_SMS_NACK = 0x13,
181 DLL2_SMS_ACK0 = 0x14,
182 DLL2_SMS_ACK1 = 0x15,
186 DLL2_SMS_COMPLETE = 0x00,
187 DLL2_SMS_MORE = 0x80,
191 static const unsigned short defaultalphabet[] = {
192 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
193 0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
194 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
195 0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
196 ' ',
'!',
'"',
'#', 164,
'%',
'&', 39,
'(',
')',
'*',
'+',
',',
'-',
'.',
'/',
197 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
':',
';',
'<',
'=',
'>',
'?',
198 161,
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
199 'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z', 196, 214, 209, 220, 167,
200 191,
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
201 'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z', 228, 246, 241, 252, 224,
204 static const unsigned short escapes[] = {
205 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x000C, 0, 0, 0, 0, 0,
206 0, 0, 0, 0, 0x005E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207 0, 0, 0, 0, 0, 0, 0, 0, 0x007B, 0x007D, 0, 0, 0, 0, 0, 0x005C,
208 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x005B, 0x007E, 0x005D, 0,
209 0x007C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
210 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
211 0, 0, 0, 0, 0, 0x20AC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
212 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
251 signed long long ims0,
281 #define is7bit(dcs) ( ((dcs) & 0xC0) ? (!((dcs) & 4) ) : (((dcs) & 0xc) == 0) )
282 #define is8bit(dcs) ( ((dcs) & 0xC0) ? ( ((dcs) & 4) ) : (((dcs) & 0xc) == 4) )
283 #define is16bit(dcs) ( ((dcs) & 0xC0) ? 0 : (((dcs) & 0xc) == 8) )
285 static void sms_messagetx(
sms_t *h);
303 static char *
isodate(time_t t,
char *buf,
int len)
306 struct timeval local = { t, 0 };
317 unsigned char *p = *pp;
326 if (*p < 0xC2 || (p[1] & 0xC0) != 0x80) {
330 return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
333 if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80) {
337 return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
340 if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80) {
344 return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
347 if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
348 || (p[4] & 0xC0) != 0x80) {
352 return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
355 if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
356 || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80) {
360 return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
369 static int packsms7(
unsigned char *o,
int udhl,
unsigned char *udh,
int udl,
unsigned short *ud)
374 unsigned char dummy[
SMSLEN];
408 for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
409 if (v == 128 && u && n + 1 <
SMSLEN) {
411 for (v = 0; v < 128 && escapes[v] != u; v++);
419 o[p] = (27 >> (7 - b));
432 o[p] = (v >> (7 - b));
446 static int packsms8(
unsigned char *o,
int udhl,
unsigned char *udh,
int udl,
unsigned short *ud)
466 if (u < 0 || u > 0xFF) {
485 static int packsms16(
unsigned char *o,
int udhl,
unsigned char *udh,
int udl,
unsigned short *ud)
520 static int packsms(
unsigned char dcs,
unsigned char *base,
unsigned int udhl,
unsigned char *udh,
int udl,
unsigned short *ud)
522 unsigned char *p = base;
529 if ((l =
packsms7(p + 1, udhl, udh, udl, ud)) < 0) {
533 p += (l * 7 + 7) / 8;
534 }
else if (is8bit(dcs)) {
535 if ((l =
packsms8(p + 1, udhl, udh, udl, ud)) < 0) {
541 if ((l =
packsms16(p + 1, udhl, udh, udl, ud)) < 0) {
556 struct timeval topack = { w, 0 };
560 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
563 z = timezone / 60 / 15;
566 *o++ = (((t.
tm_mon + 1) % 10) << 4) + (t.
tm_mon + 1) / 10;
572 *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
574 *o++ = ((z % 10) << 4) + z / 10;
583 t.
tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
584 t.
tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
585 t.
tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
586 t.
tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
587 t.
tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
588 t.
tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
591 t.
tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
593 t.
tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
602 static void unpacksms7(
unsigned char *i,
unsigned char l,
unsigned char *udh,
int *udhl,
unsigned short *ud,
int *udl,
char udhi)
604 unsigned char b = 0, p = 0;
605 unsigned short *o = ud;
635 v = ((i[p] >> b) & 0x7F);
637 v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
645 if (o > ud && o[-1] == 0x00A0 && escapes[v]) {
648 *o++ = defaultalphabet[v];
658 static void unpacksms8(
unsigned char *i,
unsigned char l,
unsigned char *udh,
int *udhl,
unsigned short *ud,
int *udl,
char udhi)
660 unsigned short *o = ud;
684 static void unpacksms16(
unsigned char *i,
unsigned char l,
unsigned char *udh,
int *udhl,
unsigned short *ud,
int *udl,
char udhi)
686 unsigned short *o = ud;
712 static int unpacksms(
unsigned char dcs,
unsigned char *i,
unsigned char *udh,
int *udhl,
unsigned short *ud,
int *udl,
char udhi)
718 }
else if (is8bit(dcs)) {
730 unsigned char l = i[0], p;
734 for (p = 0; p < l; p++) {
736 *o++ = (i[2 + p / 2] >> 4) +
'0';
738 *o++ = (i[2 + p / 2] & 0xF) +
'0';
761 o[p++] |= ((*i & 0xF) << 4);
778 if (*h->
oa ==
'\0' && *h->
da ==
'\0') {
781 o = open(log_file, O_CREAT | O_APPEND | O_WRONLY, AST_FILE_MODE);
783 char line[1000], mrs[3] =
"", *p;
788 snprintf(mrs,
sizeof(mrs),
"%02hhX", (
unsigned char)h->
mr);
790 snprintf(line,
sizeof(line),
"%s %c%c%c%s %s %s %s ",
791 isodate(time(NULL), buf,
sizeof(buf)),
792 status, h->
rx ?
'I' :
'O', h->
smsc ?
'S' :
'M', mrs, h->
queue,
794 p = line + strlen(line);
797 p += snprintf(p, 1000 - strlen(line),
"udl=%d", h->
udl);
799 for (n = 0; n < h->
udl; n++) {
800 if (h->
ud[n] ==
'\\') {
803 }
else if (h->
ud[n] ==
'\n') {
806 }
else if (h->
ud[n] ==
'\r') {
809 }
else if (h->
ud[n] < 32 || h->
ud[n] == 127) {
818 if (write(o, line, strlen(line)) < 0) {
819 ast_log(LOG_WARNING,
"write() failed: %s\n", strerror(errno));
832 ast_log(LOG_NOTICE,
"Sending %s\n", fn);
843 while (fgets (line,
sizeof(line), s)) {
846 for (p = line; *p && *p !=
'\n' && *p !=
'\r'; p++);
849 if (!*p || *p ==
';') {
852 while (isalnum(*p)) {
856 while (isspace (*p)) {
861 if (!strcmp(line,
"ud")) {
864 while (*p && o <
SMSLEN) {
869 ast_log(LOG_WARNING,
"UD too long in %s\n", fn);
872 while (isspace (*p)) {
875 if (!strcmp(line,
"oa") && strlen(p) <
sizeof(h->
oa)) {
877 }
else if (!strcmp(line,
"da") && strlen(p) <
sizeof(h->
oa)) {
879 }
else if (!strcmp(line,
"pid")) {
881 }
else if (!strcmp(line,
"dcs")) {
884 }
else if (!strcmp(line,
"mr")) {
886 }
else if (!strcmp(line,
"srr")) {
887 h->
srr = (atoi(p) ? 1 : 0);
888 }
else if (!strcmp(line,
"vp")) {
890 }
else if (!strcmp(line,
"rp")) {
891 h->
rp = (atoi(p) ? 1 : 0);
892 }
else if (!strcmp(line,
"scts")) {
893 int Y, m, d, H, M, S;
895 if (sscanf(p,
"%4d-%2d-%2dT%2d:%2d:%2d", &Y, &m, &d, &H, &M, &S) == 6) {
905 if (h->
scts.tv_sec == 0) {
906 ast_log(LOG_WARNING,
"Bad date/timein %s: %s", fn, p);
910 ast_log(LOG_WARNING,
"Cannot parse in %s: %s=%si\n", fn, line, p);
913 }
else if (*p ==
'#') {
917 if (!strcmp(line,
"ud")) {
919 while (*p && o <
SMSLEN) {
920 if (isxdigit(*p) && isxdigit(p[1]) && isxdigit(p[2]) && isxdigit(p[3])) {
922 (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 12) +
923 (((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
924 (((isalpha(p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha(p[3]) ? 9 : 0) + (p[3] & 0xF));
931 ast_log(LOG_WARNING,
"UD too long / invalid UCS-2 hex in %s\n", fn);
933 ast_log(LOG_WARNING,
"Only ud can use ## format, %s\n", fn);
934 }
else if (!strcmp(line,
"ud")) {
936 while (*p && o <
SMSLEN) {
937 if (isxdigit(*p) && isxdigit(p[1])) {
938 h->
ud[o++] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
946 ast_log(LOG_WARNING,
"UD too long / invalid UCS-1 hex in %s\n", fn);
948 }
else if (!strcmp(line,
"udh")) {
951 while (*p && o <
SMSLEN) {
952 if (isxdigit(*p) && isxdigit(p[1])) {
953 h->
udh[o] = (((isalpha(*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha(p[1]) ? 9 : 0) + (p[1] & 0xF));
962 ast_log(LOG_WARNING,
"UDH too long / invalid hex in %s\n", fn);
965 ast_log(LOG_WARNING,
"Only ud and udh can use # format, %s\n", fn);
968 ast_log(LOG_WARNING,
"Cannot parse in %s: %s\n", fn, line);
975 ast_log(LOG_WARNING,
"Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
978 ast_log(LOG_WARNING,
"Sending in 16 bit format(%s)\n", fn);
982 ast_log(LOG_WARNING,
"Sending in 8 bit format(%s)\n", fn);
986 ast_log(LOG_WARNING,
"Invalid 7 bit GSM data %s\n", fn);
989 ast_log(LOG_WARNING,
"Invalid 8 bit data %s\n", fn);
992 ast_log(LOG_WARNING,
"Invalid 16 bit data %s\n", fn);
1000 char fn[200] =
"", fn2[200] =
"";
1007 snprintf(fn,
sizeof(fn),
"%s/sms/%s", ast_config_AST_SPOOL_DIR, h->
smsc ? h->
rx ?
"morx" :
"mttx" : h->
rx ?
"mtrx" :
"motx");
1010 snprintf(fn2 + strlen(fn2),
sizeof(fn2) - strlen(fn2),
"/%s.%s-%u", h->
queue,
isodate(h->
scts.tv_sec, buf,
sizeof(buf)), seq++);
1011 snprintf(fn + strlen(fn),
sizeof(fn) - strlen(fn),
"/.%s", fn2 + strlen(fn) + 1);
1012 if ((o = fopen(fn,
"w")) == NULL) {
1017 fprintf(o,
"oa=%s\n", h->
oa);
1020 fprintf(o,
"da=%s\n", h->
da);
1025 for (p = 0; p < h->
udhl; p++) {
1026 fprintf(o,
"%02hhX", (
unsigned char)h->
udh[p]);
1032 for (p = 0; p < h->
udl && h->
ud[p] >=
' '; p++);
1037 for (p = 0; p < h->
udl; p++) {
1038 unsigned short v = h->
ud[p];
1041 }
else if (v < 0x80) {
1043 }
else if (v < 0x800) {
1044 fputc(0xC0 + (v >> 6), o);
1045 fputc(0x80 + (v & 0x3F), o);
1047 fputc(0xE0 + (v >> 12), o);
1048 fputc(0x80 + ((v >> 6) & 0x3F), o);
1049 fputc(0x80 + (v & 0x3F), o);
1053 for (p = 0; p < h->
udl && h->
ud[p] >=
' '; p++);
1055 for (p = 0; p < h->
udl && h->
ud[p] < 0x100; p++);
1058 for (p = 0; p < h->
udl; p++) {
1059 fprintf(o,
"%02hhX", (
unsigned char)h->
ud[p]);
1064 for (p = 0; p < h->
udl; p++) {
1065 fprintf(o,
"%04X", (
unsigned)h->
ud[p]);
1071 if (h->
scts.tv_sec) {
1073 fprintf(o,
"scts=%s\n",
isodate(h->
scts.tv_sec, datebuf,
sizeof(datebuf)));
1076 fprintf(o,
"pid=%d\n", h->
pid);
1078 if (h->
dcs != 0xF1) {
1079 fprintf(o,
"dcs=%d\n", h->
dcs);
1082 fprintf(o,
"vp=%u\n", h->
vp);
1085 fprintf(o,
"srr=1\n");
1088 fprintf(o,
"mr=%d\n", h->
mr);
1091 fprintf(o,
"rp=1\n");
1094 if (rename(fn, fn2)) {
1097 ast_log(LOG_NOTICE,
"Received to %s\n", fn2);
1107 }
while (f && (*f->d_name ==
'.' || strncmp(f->d_name, queue, strlen(queue)) || f->d_name[strlen(queue)] !=
'.'));
1114 unsigned char p = 3;
1116 if ((h->
imsg[2] & 3) == 1) {
1119 h->
srr = ((h->
imsg[2] & 0x20) ? 1 : 0);
1120 h->
udhi = ((h->
imsg[2] & 0x40) ? 1 : 0);
1121 h->
rp = ((h->
imsg[2] & 0x80) ? 1 : 0);
1128 if ((h->
imsg[2] & 0x18) == 0x10) {
1129 if (h->
imsg[p] < 144) {
1130 h->
vp = (h->
imsg[p] + 1) * 5;
1131 }
else if (h->
imsg[p] < 168) {
1132 h->
vp = 720 + (h->
imsg[p] - 143) * 30;
1133 }
else if (h->
imsg[p] < 197) {
1134 h->
vp = (h->
imsg[p] - 166) * 1440;
1136 h->
vp = (h->
imsg[p] - 192) * 10080;
1139 }
else if (h->
imsg[2] & 0x18) {
1145 if (p != h->
imsg[1] + 2) {
1146 ast_log(LOG_WARNING,
"Mismatch receive unpacking %d/%d\n", p, h->
imsg[1] + 2);
1150 ast_log(LOG_WARNING,
"Unknown message type %02hhX\n", h->
imsg[2]);
1154 if (!(h->
imsg[2] & 3)) {
1156 h->
srr = ((h->
imsg[2] & 0x20) ? 1 : 0);
1157 h->
udhi = ((h->
imsg[2] & 0x40) ? 1 : 0);
1158 h->
rp = ((h->
imsg[2] & 0x80) ? 1 : 0);
1168 if (p != h->
imsg[1] + 2) {
1169 ast_log(LOG_WARNING,
"Mismatch receive unpacking %d/%d\n", p, h->
imsg[1] + 2);
1173 ast_log(LOG_WARNING,
"Unknown message type %02hhX\n", h->
imsg[2]);
1181 #define NAME_MAX 1024
1190 int x = h->
omsg[1] + 2;
1195 h->
omsg[x++] = (
unsigned char)size;
1197 for (; size > 0 ; size--) {
1198 h->
omsg[x++] = *data++;
1205 static void putdummydata_proto2(
sms_t *h)
1213 static void sms_compose2(
sms_t *h,
int more)
1216 struct timeval now = h->
scts;
1221 putdummydata_proto2(h);
1226 sprintf(stm,
"%02d%02d%02d%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);
1229 strcpy(h->
oa,
"00000000");
1238 strcpy(h->
da,
"00000000");
1246 static void putdummydata_proto2(
sms_t *h);
1248 #define MAX_DEBUG_LEN 300
1249 static char *sms_hexdump(
unsigned char buf[],
int size,
char *s )
1254 for (p = s, f = 0; f < size && f < MAX_DEBUG_LEN; f++, p += 3) {
1255 sprintf(p,
"%02hhX ", (
unsigned char)buf[f]);
1267 struct timeval now = { 0, 0 };
1268 char debug_buf[MAX_DEBUG_LEN * 3 + 1];
1270 sz = h->
imsg[1] + 2;
1275 for (f = 4; f < sz; ) {
1277 msgsz = h->
imsg[f++];
1278 msgsz += (h->
imsg[f++] * 256);
1281 ast_verb(3,
"SMS-P2 Body#%02X=[%.*s]\n", (
unsigned)msg, msgsz, &h->
imsg[f]);
1282 if (msgsz >=
sizeof(h->
ud)) {
1283 msgsz =
sizeof(h->
ud) - 1;
1285 for (i = 0; i < msgsz; i++) {
1286 h->
ud[i] = h->
imsg[f + i];
1305 ast_verb(3,
"SMS-P2 Origin#%02X=[%.*s]\n", (
unsigned)msg, msgsz, &h->
imsg[f]);
1312 ast_verb(3,
"SMS-P2 Destination#%02X=[%.*s]\n", (
unsigned)msg, msgsz, &h->
imsg[f]);
1316 ast_verb(3,
"SMS-P2 Notify#%02X=%s\n", (
unsigned)msg, sms_hexdump(&h->
imsg[f], 3, debug_buf));
1319 ast_verb(3,
"SMS-P2 Par#%02X [%d]: %s\n", (
unsigned)msg, msgsz, sms_hexdump(&h->
imsg[f], msgsz, debug_buf));
1330 static void smssend(
sms_t *h,
char *c)
1333 for (f = 0; f < strlen(c); f++) {
1334 sscanf(&c[f*3],
"%x", &x);
1343 static void sms_messagerx2(
sms_t * h)
1345 int p = h->
imsg[0] & DLL_SMS_MASK ;
1348 #define DLL2_ACK(h) ((h->framenumber & 1) ? DLL2_SMS_ACK1: DLL2_SMS_ACK1)
1355 case DLL2_SMS_INFO_MO:
1356 case DLL2_SMS_INFO_MT:
1361 h->
omsg[0] = DLL2_ACK(h);
1373 h->
omsg[0] = DLL2_SMS_REL;
1381 if ( (h->
omsg[0] & DLL_SMS_MASK) == DLL2_SMS_REL) {
1386 ast_log(LOG_NOTICE,
"SMS_SUBMIT or SMS_DELIVERY\n");
1392 h->
omsg[0] = DLL2_ACK(h);
1406 h->
omsg[p++] = (more ? 4 : 0) + ((h->
udhl > 0) ? 0x40 : 0);
1415 0x01 + (more ? 4 : 0) + (h->
srr ? 0x20 : 0) + (h->
rp ? 0x80 : 0) + (h->
vp ? 0x10 : 0) + (h->
udhi ? 0x40 : 0);
1417 h->
mr = message_ref++;
1425 h->
omsg[p++] = (h->
vp + 4) / 5 - 1;
1426 }
else if (h->
vp < 1440) {
1427 h->
omsg[p++] = (h->
vp - 720 + 29) / 30 + 143;
1428 }
else if (h->
vp < 43200) {
1429 h->
omsg[p++] = (h->
vp + 1439) / 1440 + 166;
1430 }
else if (h->
vp < 635040) {
1431 h->
omsg[p++] = (h->
vp + 10079) / 10080 + 192;
1444 char fn[100 + NAME_MAX] =
"";
1448 *h->
da = *h->
oa =
'\0';
1450 snprintf(fn,
sizeof(fn),
"%s/sms/%s", ast_config_AST_SPOOL_DIR, h->
smsc ?
"mttx" :
"motx");
1456 snprintf(fn + strlen(fn),
sizeof(fn) - strlen(fn),
"/%s", f->d_name);
1464 if (*h->
da || *h->
oa) {
1466 sms_compose2(h, more);
1485 static void sms_debug (
int dir,
sms_t *h)
1487 char txt[259 * 3 + 1];
1489 unsigned char *msg = (dir == DIR_RX) ? h->
imsg : h->
omsg;
1490 int n = (dir == DIR_RX) ? h->
ibytep : msg[1] + 2;
1492 while (q < n && q < 30) {
1493 sprintf(p,
" %02hhX", msg[q++]);
1499 ast_verb(3,
"SMS %s%s\n", dir == DIR_RX ?
"RX" :
"TX", txt);
1503 static void sms_messagerx(
sms_t * h)
1507 sms_debug (DIR_RX, h);
1513 switch (h->
imsg[0]) {
1561 static void sms_messagetx(
sms_t * h)
1563 unsigned char c = 0, p;
1564 int len = h->
omsg[1] + 2;
1566 for (p = 0; p < len; p++) {
1569 h->
omsg[len] = 0 - c;
1570 sms_debug(DIR_TX, h);
1577 if (h->
omsg[0] == 0x7F) {
1589 if (h->
omsg[0] == 0x93) {
1596 h->
osync = OSYNC_BITS;
1607 #define MAXSAMPLES (800)
1612 if (samples > MAXSAMPLES) {
1613 ast_log(LOG_WARNING,
"Only doing %d samples (%d requested)\n",
1614 MAXSAMPLES, samples);
1615 samples = MAXSAMPLES;
1622 f.
datalen = samples *
sizeof(*buf);
1629 for (i = 0; i <
samples; i++) {
1630 buf[i] = wave_out[0];
1635 buf[i] = wave_out[h->
ophase];
1639 if ((h->
ophasep += 12) >= 80) {
1644 }
else if (h->
osync) {
1652 if (h->
obitp == 1) {
1654 }
else if (h->
obitp == 2) {
1656 }
else if (h->
obitp == 10) {
1674 ast_log(LOG_WARNING,
"Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
1696 .release = sms_release,
1726 for ( ; samples-- ; data++) {
1727 unsigned long long m0, m1;
1728 if (abs(*data) > h->
imag) {
1729 h->
imag = abs(*data);
1733 if (h->
imag <= 500) {
1734 if (h->idle++ == 80000) {
1735 ast_log(LOG_NOTICE,
"No data, hanging up\n");
1740 ast_log(LOG_NOTICE,
"Error %d, hanging up\n", h->
ierr);
1754 h->ims0 = (h->ims0 * 6 + *data * wave[h->
ips0]) / 7;
1755 h->imc0 = (h->imc0 * 6 + *data * wave[h->
ipc0]) / 7;
1756 h->ims1 = (h->ims1 * 6 + *data * wave[h->
ips1]) / 7;
1759 m0 = h->ims0 * h->ims0 + h->imc0 * h->imc0;
1760 m1 = h->ims1 * h->ims1 + h->
imc1 * h->
imc1;
1763 if ((h->
ips0 += 21) >= 80) {
1766 if ((h->
ipc0 += 21) >= 80) {
1769 if ((h->
ips1 += 13) >= 80) {
1772 if ((h->
ipc1 += 13) >= 80) {
1787 bit = ((h->
ibitt > 1) ? 1 : 0);
1788 if (bit != h->
ibitl) {
1798 if (bit && h->
ibitc == 200) {
1802 ast_verb(3,
"SMS protocol 2 detected\n");
1815 if (h->
ibitn++ == 9) {
1820 ast_log(LOG_NOTICE,
"Bad stop bit\n");
1829 ast_log(LOG_NOTICE,
"msg too large\n");
1836 ast_log(LOG_NOTICE,
"bad checksum\n");
1857 OPTION_BE_SMSC = (1 << 0),
1858 OPTION_ANSWER = (1 << 1),
1859 OPTION_TWO = (1 << 2),
1860 OPTION_PAUSE = (1 << 3),
1861 OPTION_SRR = (1 << 4),
1862 OPTION_DCS = (1 << 5),
1863 OPTIONS_NO_LOG = (1 << 6),
1867 OPTION_ARG_PAUSE = 0,
1868 OPTION_ARG_ARRAY_SIZE
1881 static int sms_exec(
struct ast_channel *chan,
const char *data)
1887 char *parse, *sms_opts[OPTION_ARG_ARRAY_SIZE] = { 0, };
1897 ast_log(LOG_ERROR,
"Requires queue name at least\n");
1903 if (sms_args.argc > 1) {
1907 ast_verb(1,
"sms argc %u queue <%s> opts <%s> addr <%s> body <%s>\n",
1908 sms_args.argc,
S_OR(sms_args.queue,
""),
1909 S_OR(sms_args.options,
""),
1910 S_OR(sms_args.addr,
""),
1911 S_OR(sms_args.body,
"") );
1917 S_COR(ast_channel_caller(chan)->
id.
number.valid, ast_channel_caller(chan)->
id.
number.str,
""),
1920 if (ast_strlen_zero(sms_args.queue)) {
1921 ast_log(LOG_ERROR,
"Requires queue name\n");
1924 if (strlen(sms_args.queue) >=
sizeof(h.
queue)) {
1925 ast_log(LOG_ERROR,
"Queue name too long\n");
1930 for (p = h.
queue; *p; p++) {
1936 h.
smsc = ast_test_flag(&flags, OPTION_BE_SMSC);
1937 h.
protocol = ast_test_flag(&flags, OPTION_TWO) ? 2 : 1;
1938 h.
nolog = ast_test_flag(&flags, OPTIONS_NO_LOG) ? 1 : 0;
1939 if (!ast_strlen_zero(sms_opts[OPTION_ARG_PAUSE])) {
1940 h.
opause_0 = atoi(sms_opts[OPTION_ARG_PAUSE]);
1945 ast_verb(1,
"initial delay %dms\n", h.
opause_0);
1949 if (ast_test_flag(&flags, OPTION_SRR)) {
1952 if (ast_test_flag(&flags, OPTION_DCS)) {
1963 h.
pid = 0x40 + (*d & 0xF);
1967 if (sms_args.argc > 2) {
1973 if (ast_strlen_zero(sms_args.addr) || strlen(sms_args.addr) >=
sizeof(h.
oa)) {
1974 ast_log(LOG_ERROR,
"Address too long %s\n", sms_args.addr);
1984 if (ast_strlen_zero(sms_args.body)) {
1985 ast_log(LOG_ERROR,
"Missing body for %s\n", sms_args.addr);
1988 up = (
unsigned char *)sms_args.body;
1993 ast_log(LOG_WARNING,
"Invalid 7 bit GSM data\n");
1997 ast_log(LOG_WARNING,
"Invalid 8 bit data\n");
2001 ast_log(LOG_WARNING,
"Invalid 16 bit data\n");
2015 if (ast_test_flag(&flags, OPTION_ANSWER)) {
2019 h.
omsg[0] = DLL2_SMS_EST;
2022 h.
omsg[0] = DLL1_SMS_EST | DLL1_SMS_COMPLETE;
2033 ast_log(LOG_ERROR,
"Unable to set to linear mode, giving up\n");
2038 ast_log(LOG_ERROR,
"Failed to activate generator on '%s'\n", ast_channel_name(chan));
2047 ast_log(LOG_NOTICE,
"waitfor failed\n");
2051 ast_log(LOG_NOTICE,
"channel hangup\n");
2056 ast_log(LOG_NOTICE,
"ast_read failed\n");
2078 static int unload_module(
void)
2083 static int load_module(
void)
2087 for (p = 0; p < 80; p++) {
2088 wavea[p] = AST_LIN2A(wave[p]);
2091 snprintf(log_file,
sizeof(log_file),
"%s/sms", ast_config_AST_LOG_DIR);
A-Law to Signed linear conversion.
Main Channel structure associated with a channel.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
static long utf8decode(unsigned char **pp)
Reads next UCS character from NUL terminated UTF-8 string and advance pointer.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
static void packdate(unsigned char *o, time_t w)
pack a date and return
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
static unsigned char packaddress(unsigned char *o, char *i)
store an address at o, and return number of bytes used
static int sms_handleincoming_proto2(sms_t *h)
sms_handleincoming_proto2: handle the incoming message
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
static void sms_compose1(sms_t *h, int more)
compose a message for protocol 1
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
ast_channel_state
ast_channel states
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
static unsigned char unpackaddress(char *o, unsigned char *i)
unpack an address from i, return byte length, unpack to o
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_unregister_application(const char *app)
Unregister an application.
struct ast_frame_subclass subclass
static void sms_readfile(sms_t *h, char *fn)
parse and delete a file
static void sms_process(sms_t *h, int samples, signed short *data)
static int sms_generate(struct ast_channel *chan, void *data, int len, int samples)
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
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...
static struct dirent * readdirqueue(DIR *d, char *queue)
read dir skipping dot files...
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
#define ast_strdupa(s)
duplicate a string in memory from the stack
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 ...
static char * isodate(time_t t, char *buf, int len)
static, return a date/time in ISO format
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
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...
static void * sms_alloc(struct ast_channel *chan, void *sms_t_ptr)
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
static void sms_writefile(sms_t *h)
white a received text message to a file
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Core PBX routines and definitions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
unsigned short ud[SMSLEN]
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...
union ast_frame::@224 data
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 void sms_log(sms_t *h, char status)
Log the output, and remove file.
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
static void adddata_proto2(sms_t *h, unsigned char msg, char *data, int size)
Structure used to handle boolean flags.
void ast_deactivate_generator(struct ast_channel *chan)
static struct timeval unpackdate(unsigned char *i)
unpack a date and return
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 ...
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int ast_answer(struct ast_channel *chan)
Answer a channel.
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 ...
Data structure associated with a single frame of data.
enum ast_frame_type frametype
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...
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
struct ast_format * format
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static void numcpy(char *d, char *s)
copy number, skipping non digits apart from leading +
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
static void sms_nextoutgoing(sms_t *h)
find and fill in next message, or send a REL if none waiting
#define AST_APP_ARG(name)
Define an application argument.
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
static unsigned char sms_handleincoming(sms_t *h)
handle the incoming message
unsigned char udh[SMSLEN]