115 #include <sys/time.h> 116 #include <sys/types.h> 117 #include <sys/timeb.h> 118 #include <sys/socket.h> 119 #include <netinet/in.h> 120 #include <arpa/inet.h> 141 #define SAY(d,s) { if (d<=ois_debug_level) debug("bb.sms.ois",0,s); } 142 #define SAY2(d,s,t) { if (d<=ois_debug_level) debug("bb.sms.ois",0,s,t); } 143 #define SAY3(d,s,t,u) { if (d<=ois_debug_level) debug("bb.sms.ois",0,s,t,u); } 144 #define IOTRACE(x,s,l) SAY3(1,"%s [%s]",x,ois_debug_str(s,l)) 148 #define OIS_OPEN_WAITTIME (15) 149 #define OIS_MESSAGE_WAITTIME (30) 150 #define OIS_WAITTIME (999999) 151 #define OIS_NOWAIT (0) 152 #define MAXCOUNTER (10000) 160 #define OIS_FLAG_DEBUG (0x000f) 161 #define OIS_FLAG_ERROR (0x0100) 162 #define OIS_FLAG_NOBANNER (0x0200) 163 #define OIS_FLAG_MULTIPLE_CALL (0x0400) 164 #define OIS_FLAG_CLOSED (0x0800) 247 sprintf(smsc->
name,
"OIS:TCP/X.25-Translator:localhost:%d:TCP:%.512s:%d",
253 error(0,
"ois_open: could not open");
269 warning(0,
"ois_close: closing a not-ois connection...");
276 SAY(4,
"ois_close: ois_disconnect_all");
292 SAY(2,
"ois_reopen");
302 error(0,
"ois_reopen: wrong smsc type");
308 error(0,
"ois_reopen: could not open");
323 SAY(8,
"ois_pending_smsmessage");
326 if (ret == 0 && smsc->
socket != -1) {
334 warning(0,
"ois_pending_smsmessage: missing %d ack(s)...",
351 SAY(2,
"ois_submit_msg");
355 error(0,
"ois_submit_msg: can not handle message types other than smart_msg");
378 warning(0,
"ois_submit_msg: missing %d ack(s)...",
381 SAY(4,
"ois_submit_msg: ois_disconnect in error_close");
384 SAY(2,
"ois_submit_msg error");
401 SAY(2,
"ois_receive_msg");
428 SAY(2,
"ois_delete_queue");
450 SAY(2,
"ois_open_listener");
470 error(0,
"ois_open_listener: failed to open listening socket");
482 SAY(2,
"ois_open_sender");
483 debug(
"bb.sms.ois", 0,
"connecting to host %s port %d",
498 SAY2(2,
"ois_open_sender fd=%d", smsc->
socket);
514 debug(
"bb.sms.ois", 0,
"assuming that %s:%d is in the quiet mode",
520 if (strncmp(buffer,
"Trying", 6) == 0 &&
521 strstr(buffer,
"...Open\r\n") != NULL) {
531 SAY(4,
"ois_open_sender: ois_disconnect in error");
533 error(0,
"ois_open_sender: failed to connect [%s%s]",
541 struct sockaddr_in addr;
545 SAY(2,
"ois_open_receiver");
549 addrlen =
sizeof(addr);
551 (
struct sockaddr *)&addr, (
socklen_t *)&addrlen);
553 if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
558 error(errno,
"ois_open_receiver: accept failed");
564 SAY2(2,
"ois_open_receiver fd=%d", smsc->
socket);
566 debug(
"bb.sms.ois", 0,
"connection from host %s port %hu",
579 SAY(4,
"ois_disconnect_all: ois_disconnect");
582 SAY(4,
"ois_disconnect_all: ois_disconnect");
587 warning(errno,
"ois_disconnect_all: close failed...");
597 SAY2(2,
"ois_disconnect fd=%d", smsc->
socket);
600 if (close(smsc->
socket) == -1) {
601 warning(errno,
"ois_disconnect: close failed...");
613 SAY(8,
"ois_read_into_buffer");
617 debug(
"bb.sms.ois", 0,
"attempting to read from a closed socket");
629 if (ret > 0 || (ret == 0 && smsc->
buflen > 0)) {
630 SAY(2,
"ois_read_into_buffer got something");
631 }
else if (ret == 0) {
633 SAY(2,
"ois_read_into_buffer has something");
636 SAY(4,
"ois_read_into_buffer: ois_disconnect");
650 SAY(8,
"ois_check_input");
659 IOTRACE(
"received", buffer, ret);
664 warning(0,
"ois_check_input: submit sm result signals (%d)...", ret);
665 }
else if (ret < 0) {
666 error(0,
"ois_check_input: invalid submit sm result");
680 error(0,
"ois_check_input: invalid deliver sm invoke");
686 warning(0,
"ois_check_input: unexpected message [%s]...",
694 debug(
"bb.sms.ois", 0,
"closing an idle connection");
695 SAY(4,
"ois_check_input: ois_disconnect");
702 error(0,
"ois_check_input: malformatted message [%s]",
709 SAY(2,
"ois_check_input has something");
727 SAY(8,
"ois_check_incoming");
730 tv.tv_usec = wait_usec;
736 if (errno == EINTR || errno == EAGAIN) {
739 error(errno,
"ois_check_incoming: select failed");
743 }
else if (ret == 0) {
753 debug(
"bb.sms.ois", 0,
"letting an incoming call to wait until the old one disconnects");
769 SAY(2,
"ois_append_to_list");
778 for (tail = *head; tail->
next != NULL; tail = tail->
next) ;
790 SAY(3,
"ois_int_to_i4");
792 for (pos = 0; pos < 4; ++pos) {
793 raw[pos] = (char)(nbr % 0x100);
801 SAY(3,
"ois_increment_counter");
817 SAY(2,
"ois_submit_sm_invoke");
827 count = (len-1) / 121;
831 sprintf(buffer,
"%c%c%04d%.121s%c",
837 IOTRACE(
"sending", buffer, strlen(buffer));
845 for (i = 1; i <= count; ++i) {
846 sprintf(buffer,
"%c%c%04d%.121s%c",
848 (
char)(0x60|(count-i)),
852 IOTRACE(
"sending", buffer, strlen(buffer));
859 SAY(2,
"ois_submit_sm_invoke ok");
863 SAY(2,
"ois_submit_sm_invoke error");
874 SAY(3,
"ois_encode_submit_sm_invoke");
898 SAY(3,
"ois_append_msisdn");
908 SAY(3,
"ois_append_sme_reference_number");
918 SAY(3,
"ois_append_priority");
926 SAY(3,
"ois_append_originating_address");
937 SAY(3,
"ois_append_validity_period");
946 SAY(3,
"ois_append_data_coding_scheme");
958 SAY(3,
"ois_append_status_report_request");
960 raw[0] = (char) 0x00;
966 SAY(3,
"ois_append_protocol_id");
974 SAY(3,
"ois_append_submission_options");
977 raw[0] = (char) 0x00;
979 raw[0] |= (char) 0x02;
982 raw[0] |= (char) 0x10;
990 int udhlen7, udhlen8;
991 int msglen7, msglen8;
994 SAY(3,
"ois_append_sm_text");
1009 len = udhlen8 + msglen8;
1013 raw[0] = (char) (len);
1014 raw[1] = (char) (udhlen7 + msglen7);
1018 IOTRACE(
"encoding", &raw[2], len);
1029 SAY(2,
"ois_submit_sm_result");
1049 SAY(3,
"ois_decode_submit_sm_result");
1051 buflen = strlen(str) - 1;
1052 if (buflen < 7 || str[0] !=
's' || str[1] != 0x50 || str[buflen] !=
EOL) {
1079 SAY(2,
"ois_deliver_sm_invoke");
1108 SAY(3,
"ois_decode_deliver_sm_invoke");
1118 for (pos = 0, i = 6; i < len; ++i) {
1119 if (str[i] !=
EOL) {
1120 body[pos++] = str[i];
1126 memset(raw,
'\0',
sizeof(raw));
1142 error(0,
"ois_decode_deliver_sm_invoke: message parsing error (%d!=%d)",
1159 SAY(3,
"ois_check_deliver_sm_invoke");
1163 buflen = strlen(str) - 1;
1164 if (buflen < 7 || str[0] !=
'M' || (str[1] & 0x50) != 0x50
1165 || str[buflen] !=
EOL) {
1169 count = str[1] & 0x0f;
1170 while (--count >= 0)
1174 sprintf(buffer,
"%c%c%c%.4s",
1179 if (strstr(str, buffer) == NULL) {
1195 SAY(3,
"ois_adjust_destination_address");
1197 len = raw[0] & 0xff;
1207 SAY(3,
"ois_ignore_smsc_reference_number");
1209 value = raw[3] & 0xff;
1211 value |= raw[2] & 0xff;
1213 value |= raw[1] & 0xff;
1215 value |= raw[0] & 0xff;
1224 SAY(3,
"ois_adjust_originating_address");
1226 len = raw[0] & 0xff;
1234 SAY(3,
"ois_adjust_data_coding_scheme");
1239 msg->sms.coding = (raw[0] & 0xff) + 1;
1246 SAY(3,
"ois_ignore_protocol_id");
1253 SAY(3,
"ois_adjust_additional_information");
1257 msg->sms.mclass = raw[0] & 0xff;
1264 int msglen7, msglen8;
1267 SAY(3,
"ois_adjust_sm_text");
1271 msglen7 = raw[0] & 0xff;
1272 msglen8 = raw[1] & 0xff;
1276 switch ((
msg->sms.coding - 1) & 0xff) {
1280 if (
msg->sms.mclass & 0x02) {
1290 memcpy(buffer, &raw[2], msglen8);
1292 if (
msg->sms.mclass & 0x02) {
1302 if (
msg->sms.mclass & 0x02) {
1330 SAY(3,
"ois_ignore_time");
1332 strncpy(str, raw, 14); str[14] =
'\0';
1345 SAY(2,
"ois_deliver_sm_result");
1353 sprintf(buffer,
"%c%c%.4s%.121s%c",
1360 IOTRACE(
"sending", buffer, strlen(buffer));
1377 SAY(3,
"ois_encode_deliver_sm_result");
1381 raw[0] = (char) result;
1392 SAY2(3,
"ois_expand_gsm7 len=%d", len);
1398 for (i = 0; i < len; ++i) {
1411 SAY(3,
"ois_expand_gsm7_to_bits");
1415 for (j = i = 0; j < len; ++i) {
1417 for (k = 0; k < 8; ++k) {
1418 bits[j++] = (char) (ch & 0x01);
1431 SAY2(8,
"ois_expand_gsm7_from_bits pos=%d", pos);
1435 for (i = 6; i >= 0; --i) {
1450 SAY2(3,
"ois_convert_to_ia5 len=%d", len);
1452 for (j = i = 0; i < len; ++i) {
1454 if (ch == 0x5c || ch == 0x5e || ch == 0x60 || ch == 0x7e) {
1455 str[j++] = (char) 0x5c;
1456 str[j++] = (char) ch;
1457 }
else if (0x20 <= ch && ch < 0x7f) {
1458 str[j++] = (char) ch;
1459 }
else if (0x00 <= ch && ch < 0x20) {
1460 str[j++] = (char) 0x5e;
1461 str[j++] = (char) ch + 0x40;
1462 }
else if (0xa0 <= ch && ch < 0xff) {
1463 str[j++] = (char) 0x60;
1464 str[j++] = (char) ch - 0x80;
1465 }
else if (0x80 <= ch && ch < 0xa0) {
1466 str[j++] = (char) 0x7e;
1467 str[j++] = (char) ch - 0x40;
1468 }
else if (ch == 0x7f) {
1469 str[j++] = (char) 0x5e;
1470 str[j++] = (char) 0x7e;
1472 str[j++] = (char) 0x7e;
1473 str[j++] = (char) 0x7e;
1489 SAY(3,
"ois_convert_from_ia5");
1491 for (j = i = 0; ; ++i) {
1493 if (ch < 0x20 || 0x7f <= ch) {
1495 }
else if (ch == 0x5c) {
1496 ch = str[++i] & 0xff;
1497 if (ch == 0x5c || ch == 0x5e || ch == 0x60 || ch == 0x7e) {
1498 raw[j++] = (char) ch;
1502 }
else if (ch == 0x5e) {
1503 ch = str[++i] & 0xff;
1504 if (0x40 <= ch && ch < 0x60) {
1505 raw[j++] = (char) ch - 0x40;
1506 }
else if (ch == 0x7e) {
1507 raw[j++] = (char) 0x7f;
1511 }
else if (ch == 0x60) {
1512 ch = str[++i] & 0xff;
1513 if (0x20 <= ch && ch < 0x7f) {
1514 raw[j++] = (char) ch + 0x80;
1518 }
else if (ch == 0x7e) {
1519 ch = str[++i] & 0xff;
1520 if (0x40 <= ch && ch < 0x60) {
1521 raw[j++] = (char) ch + 0x40;
1522 }
else if (ch == 0x7e) {
1523 raw[j++] = (char) 0xff;
1528 raw[j++] = (char) ch;
1541 static const char gsm_to_iso88591[] = {
1542 '@', 0xa3,
'$', 0xa5,0xe8,0xe9,0xf9,0xec,
1543 0xf2,0xc7,
'\n',0xd8,0xf8,
'\r',0xc5,0xe5,
1544 'D',
' ',
'F',
'G',
'L',
'W',
'P',
'Y',
1545 'Y',
'S',
'X',
' ', 0xc6,0xe6,
'b', 0xc9,
1546 ' ',
'!',
'"',
'#', 0xa4,
'%',
'&',
'\'',
1547 '(',
')',
'*',
'+',
',',
'-',
'.',
'/',
1548 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
1549 '8',
'9',
':',
';',
'<',
'=',
'>',
'?',
1550 0xa1,
'A',
'B',
'C',
'D',
'E',
'F',
'G',
1551 'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
1552 'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
1553 'X',
'Y',
'Z', 0xc4,0xd6,0xd1,0xdc,0xa7,
1554 0xbf,
'a',
'b',
'c',
'd',
'e',
'f',
'g',
1555 'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
1556 'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
1557 'x',
'y',
'z', 0xe4,0xf6,0xf1,0xfc,0xe0
1562 SAY2(3,
"ois_convert_to_iso88591 len=%d", len);
1564 for (i = 0; i < len; ++i) {
1565 raw[i] = gsm_to_iso88591[raw[i] & 0x7f];
1582 SAY2(8,
"ois_extract_msg_from_buffer buflen=%ld", (
long)smsc->
buflen);
1590 if (strchr(
"SRDATECQLMPOVsrdatecqlmpov", smsc->
buffer[0]) == NULL
1591 || (smsc->
buffer[1] & 0xf0) != 0x50) {
1598 count = smsc->
buffer[1] & 0x0f;
1599 for (len = 0; (size_t) len < smsc->buflen; ++len) {
1617 memcpy(str, smsc->
buffer, len);
1624 for (len = 0; (size_t) len < smsc->buflen && smsc->
buffer[len] !=
EOL;
1628 memcpy(str, smsc->
buffer, len);
1645 SAY2(3,
"ois_extract_line_from_buffer buflen=%ld", (
long)smsc->
buflen);
1649 for (len = 0; (size_t) len < smsc->buflen && smsc->
buffer[len] !=
'\n';
1652 if ((
size_t) len >= smsc->
buflen) {
1660 memcpy(str, smsc->
buffer, len);
1676 SAY(8,
"ois_swap_buffering");
1711 static const char hex[] =
"0123456789abcdef";
1712 static char str[4*(
BUFLEN+1)+1];
1718 for (i = 0; i < len; ++i) {
1720 if (0x20 <= ch && ch < 0x7f && ch != 0x5c) {
1721 str[pos++] = (char) ch;
1725 str[pos++] = hex[ch/16];
1726 str[pos++] = hex[ch%16];
int ois_pending_smsmessage(SMSCenter *smsc)
struct ois_listentry ois_listentry
void error(int err, const char *fmt,...)
static int ois_ignore_smsc_reference_number(const char *raw)
static int ois_adjust_sm_text(Msg *msg, const char *raw)
int socket_set_blocking(int fd, int blocking)
static void ois_swap_buffering(SMSCenter *smsc)
static int ois_check_input(SMSCenter *smsc, long wait_usec)
static int ois_adjust_additional_information(Msg *msg, const char *raw)
static int ois_open_sender(SMSCenter *smsc)
static char ois_expand_gsm7_from_bits(const char *bits, int pos)
struct ois_listentry * next
int ois_receive_msg(SMSCenter *smsc, Msg **msg)
int ois_submit_msg(SMSCenter *smsc, const Msg *msg)
int tcpip_connect_to_server(char *hostname, int port, const char *source_addr)
static int ois_encode_deliver_sm_result(char *str, int result)
static int ois_append_data_coding_scheme(char *raw, const Msg *msg)
static int ois_ignore_time(const char *raw)
static int ois_decode_submit_sm_result(int *code, const char *str)
static int ois_extract_line_from_buffer(char *str, SMSCenter *smsc)
static int ois_convert_to_ia5(char *str, const char *raw, int len)
void charset_utf8_to_gsm(Octstr *ostr)
int smscenter_read_into_buffer(SMSCenter *smsc)
static int ois_expand_gsm7_to_bits(char *bits, const char *raw7, int len)
static int ois_append_priority(char *raw)
static int ois_check_incoming(SMSCenter *smsc, long wait_usec)
#define octstr_get_cstr(ostr)
static const char * ois_debug_str(const char *raw, int len)
int ois_reopen(SMSCenter *smsc)
#define OIS_OPEN_WAITTIME
int write_to_socket(int socket, char *str)
static int ois_decode_deliver_sm_invoke(Msg *msg, const char *str)
static int ois_submit_sm_result(SMSCenter *smsc, const char *buffer)
static int ois_convert_to_iso88591(char *raw, int len)
static void ois_append_to_list(ois_listentry **head, Msg *msg)
static int ois_append_originating_address(char *raw)
int ois_close(SMSCenter *smsc)
static int ois_convert_from_ia5(char *raw, const char *str)
static int ois_ignore_protocol_id(const char *raw)
static int ois_encode_submit_sm_invoke(char *str, const Msg *msg)
static int ois_append_validity_period(char *raw)
static int ois_append_sme_reference_number(char *raw)
SMSCenter * ois_open(int receiveport, const char *hostname, int port, int debug_level)
static int ois_extract_msg_from_buffer(char *str, SMSCenter *smsc)
void smscenter_remove_from_buffer(SMSCenter *smsc, size_t n)
static int ois_deliver_sm_invoke(SMSCenter *smsc, const char *buffer)
static int ois_append_sm_text(char *raw, const Msg *msg)
static void ois_disconnect(SMSCenter *smsc)
Octstr * gw_netaddr_to_octstr(int af, void *src)
void msg_destroy(Msg *msg)
SMSCenter * smscenter_construct(void)
static int ois_append_msisdn(char *raw, const Msg *msg)
int make_server_socket(int port, const char *interface_name)
void warning(int err, const char *fmt,...)
void smscenter_destruct(SMSCenter *smsc)
void octstr_destroy(Octstr *ostr)
static int ois_read_into_buffer(SMSCenter *smsc, long wait_usec)
#define octstr_create(cstr)
static int ois_open_listener(SMSCenter *smsc)
static int ois_int_to_i4(char *raw, int nbr)
static int ois_check_deliver_sm_invoke(const char *str)
static void ois_disconnect_all(SMSCenter *smsc)
static int ois_increment_counter(void)
long octstr_len(const Octstr *ostr)
int read_available(int fd, long wait_usec)
void debug(const char *place, int err, const char *fmt,...)
static int ois_adjust_destination_address(Msg *msg, const char *raw)
static int ois_submit_sm_invoke(SMSCenter *smsc, const Msg *msg)
void ois_delete_queue(SMSCenter *smsc)
static int ois_append_protocol_id(char *raw)
static int ois_append_status_report_request(char *raw)
static int ois_append_submission_options(char *raw, const Msg *msg)
static int ois_deliver_sm_result(SMSCenter *smsc, int result, const char *str)
static int ois_adjust_data_coding_scheme(Msg *msg, const char *raw)
static int ois_open_receiver(SMSCenter *smsc)
#define OIS_MESSAGE_WAITTIME
#define OIS_FLAG_NOBANNER
static int ois_adjust_originating_address(Msg *msg, const char *raw)
static int ois_expand_gsm7(char *raw8, const char *raw7, int len)
#define octstr_create_from_data(data, len)
static XMLRPCDocument * msg
#define OIS_FLAG_MULTIPLE_CALL