116 #define RESPONSE_TIMEOUT (10 * 1000000) 117 #define RESULT_SUCCESS 0 138 return isdigit(c) || c ==
'+' || c ==
'-';
175 for (i = 0;
operations[i].name != NULL; i++) {
249 #define BOGUS_SEQUENCE 0 303 static char s[4][4] = {
304 { 0x01, 0x0b, 0x00, 0x00 },
305 { 0x01, 0x00, 0x00, 0x00 },
306 { 0x00, 0x04, 0x00, 0x00 },
307 { 0x00, 0x09, 0x00, 0x00 }
316 for (i = 0; i < 4; i++) {
317 if (memcmp(s[i], known_bytes, 4) == 0)
322 error(0,
"OISD[%s]: wrong packet",
346 warning(0,
"OISD[%s]: SMSC sent us %s request",
361 for (j = i = 0; j < len; ++i) {
363 for (k = 0; k < 8; ++k) {
364 bits[j++] = (char) (ch & 0x01);
379 for (i = 6; i >= 0; --i) {
399 for (i = 0; i < len; ++i) {
418 for (i = 0; i < len; i++) {
443 unsigned char header[10];
450 header[0] =
opref & 0xff;
451 header[1] = (
opref >> 8) & 0xff;
452 header[2] = (
opref >> 16) & 0xff;
453 header[3] = (
opref >> 24) & 0xff;
507 int udhlen7, udhlen8;
508 int msglen7, msglen8;
517 if (
msg->sms.sender == NULL)
521 warning(0,
"OISD[%s]: non-digits in destination phone number '%s', discarded",
528 warning(0,
"OISD[%s]: non-digits in originating phone number '%s', discarded",
581 setvalidity = (
msg->sms.validity - time(NULL)) / 60;
588 if (setvalidity > 635040)
590 else if (setvalidity >= 50400 && setvalidity <= 635040)
591 setvalidity = (setvalidity - 1) / 7 / 24 / 60 + 192 + 1;
592 else if (setvalidity > 43200 && setvalidity < 50400)
594 else if (setvalidity >= 2880 && setvalidity <= 43200)
595 setvalidity = (setvalidity - 1) / 24 / 60 + 166 + 1;
596 else if (setvalidity > 1440 && setvalidity < 2880)
598 else if (setvalidity >= 750 && setvalidity <= 1440)
599 setvalidity = (setvalidity - 720 - 1) / 30 + 143 + 1;
600 else if (setvalidity > 720 && setvalidity < 750)
602 else if (setvalidity >= 5 && setvalidity <= 720)
603 setvalidity = (setvalidity - 1) / 5 - 1 + 1;
604 else if (setvalidity < 5)
614 if (setvalidity >= 0 && setvalidity <= 143)
615 debug(
"bb.smsc.oisd", 0,
"OISD[%s]: Validity-Period: %d minutes",
617 else if (setvalidity >= 144 && setvalidity <= 167)
618 debug(
"bb.smsc.oisd", 0,
"OISD[%s]: Validity-Period: %3.1f hours",
620 else if (setvalidity >= 168 && setvalidity <= 196)
621 debug(
"bb.smsc.oisd", 0,
"OISD[%s]: Validity-Period: %d days",
624 debug(
"bb.smsc.oisd", 0,
"OISD[%s]: Validity-Period: %d weeks",
642 warning(0,
"OISD[%s]: dlr request make no sense while no-dlr set to true",
663 debug(
"bb.sms.oisd", 0,
"OISD[%s]: sending UTF-8=%s",
722 warning(0,
"OISD[%s]: SMSC is not responding",
728 error(0,
"OISD[%s]: oisd_get_packet: read failed",
737 debug(
"bb.sms.oisd", 0,
"OISD[%s]: received",
766 debug(
"bb.sms.oisd", 0,
"OISD[%s]: sending response",
784 int msglen7, msglen8;
827 debug(
"bb.sms.oisd", 0,
"OISD[%s]: Invalid DCS",
837 msg->sms.rpi = add_info & 0x01;
839 debug(
"bb.sms.oisd", 0,
840 "OISD[%s]: received DCS=%02X, add_info=%d, msglen7=%d, msglen8=%d, rpi=%ld",
842 DCS, add_info, msglen7, msglen8,
msg->sms.rpi);
847 11+dest_len+5+origin_len+5,
849 debug(
"bb.sms.oisd", 0,
"OISD[%s]: received raw8=%s ",
852 if (add_info & 0x02) {
853 warning(0,
"OISD[%s]: 7-bit UDH ?",
857 debug(
"bb.sms.oisd", 0,
"OISD[%s]: received UTF-8=%s",
863 if (add_info & 0x02) {
865 11+dest_len+5+origin_len+5)+1;
868 11+dest_len+5+origin_len+5+udh_len,
872 11+dest_len+5+origin_len+5,
877 11+dest_len+5+origin_len+5,
887 info(0,
"OISD[%s]: Got SMS without receiver, discarding.",
893 info(0,
"OISD[%s]: Got SMS without sender, discarding.",
954 warning(0,
"OISD[%s]: oisd_request: socket not open.",
965 debug(
"bb.sms.oisd", 0,
"OISD[%s]: sending %s request",
992 warning(0,
"OISD[%s]: response had unexpected sequence number; ignoring.",
1001 warning(0,
"OISD[%s]: %s request got a %s",
1032 warning(0,
"OISD[%s]: Retransmitting (take %d)",
1037 warning(0,
"OISD[%s]: Giving up.",
1050 if (close(pdata->
socket) < 0)
1051 warning(errno,
"OISD[%s]: error closing socket",
1069 if (pdata->
socket >= 0) {
1070 warning(0,
"OISD[%s]: login: socket was already open; closing",
1079 if (pdata->
socket != -1) {
1080 info(0,
"OISD[%s] logged in.",
1084 error(0,
"OISD[%s] login failed.",
1122 warning(0,
"OISD[%s]: Sending delivery request failed.\n",
1141 warning(0,
"OISD[%s]: discarded %d received messages",
1160 debug(
"bb.sms.oisd", 0,
"OISD[%s]: sending message",
1184 else if (ret == -2) {
1229 warning(errno,
"OISD[%s]: oisd_receive_msg: read_available failed",
1238 warning(0,
"OISD[%s]: oisd_receive_msg: service center closed connection.",
1243 warning(0,
"OISD[%s]: oisd_receive_msg: read failed",
1255 debug(
"bb.sms.oisd", 0,
"OISD[%s]: received",
1262 error(0,
"OISD[%s]: oisd_receive_msg: unexpected response packet",
1281 Octstr *destination = NULL;
1282 Octstr *timestamp = NULL;
1332 else if (ret == 0) {
1349 double sleep = 0.0001;
1362 error(0,
"OISD[%s]: Couldn't connect to SMSC (retrying in %ld seconds).",
1383 debug(
"bb.sms.oisd", 0,
"OISD[%s]: new message received",
1434 debug(
"bb.sms", 0,
"Shutting down SMSCConn OISD %s (%s)",
1436 finish_sending ?
"slow" :
"instant");
1444 if (finish_sending == 0) {
1464 debug(
"bb.sms", 0,
"SMSCConn OISD %s shut down.",
1478 debug(
"bb.sms", 0,
"SMSCConn OISD %s, start called",
1486 debug(
"bb.sms", 0,
"SMSCConn OISD %s, stop called",
1503 pdata = gw_malloc(
sizeof(
PrivData));
1533 if (pdata->
host == NULL) {
1534 error(0,
"OISD[%s]: Configuration file doesn't specify host",
1538 if (pdata->
port == 0) {
1539 error(0,
"OISD[%s]: Configuration file doesn't specify port",
1544 error(0,
"OISD[%s]: Configuration file doesn't specify my-number.",
1560 debug(
"bb.sms.oisd", 0,
"OISD[%s]: Keepalive set to %ld seconds",
1567 debug(
"bb.sms.oisd", 0,
"OISD[%s]: Validity-Period set to %ld",
1576 error(0,
"OISD[%s]: Couldn't start I/O thread.",
static struct packet * packet_extract(Octstr *in, SMSCConn *conn)
void error(int err, const char *fmt,...)
int smsc_oisd_create(SMSCConn *conn, CfgGroup *grp)
static char oisd_expand_gsm7_from_bits(const char *bits, int pos)
void info(int err, const char *fmt,...)
int octstr_write_to_socket(int socket, Octstr *ostr)
Msg * msg_duplicate(Msg *msg)
static Msg * oisd_accept_message(struct packet *request, SMSCConn *conn)
void bb_smscconn_connected(SMSCConn *conn)
static int oisd_receive_msg(SMSCConn *conn, Msg **msg)
gw_assert(wtls_machine->packet_to_send !=NULL)
static void io_thread(void *arg)
void gwlist_append(List *list, void *item)
int tcpip_connect_to_server(char *hostname, int port, const char *source_addr)
void bb_smscconn_killed(void)
static void oisd_stop_cb(SMSCConn *conn)
int octstr_check_range(Octstr *ostr, long pos, long len, octstr_func_t filter)
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
void gwlist_produce(List *list, void *item)
void gwthread_join(long thread)
long gwlist_len(List *list)
int octstr_append_from_socket(Octstr *ostr, int socket)
static void packet_parse_header(struct packet *packet)
static void packet_set_sequence(struct packet *packet, unsigned long opref)
void(* stop_conn)(SMSCConn *conn)
void octstr_append_char(Octstr *ostr, int ch)
void charset_utf8_to_gsm(Octstr *ostr)
static Msg * oisd_accept_delivery_report_message(struct packet *request, SMSCConn *conn)
#define cfg_get(grp, varname)
static int oisd_request(struct packet *request, SMSCConn *conn, Octstr **ts)
static void packet_check_can_receive(struct packet *packet, SMSCConn *conn)
static void oisd_shrink_gsm7(Octstr *str)
static int isphonedigit(int c)
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Msg * dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
void dlr_add(const Octstr *smsc, const Octstr *ts, Msg *msg, int use_dst)
#define octstr_get_cstr(ostr)
#define octstr_copy(ostr, from, len)
void(* start_conn)(SMSCConn *conn)
void log_thread_to(int idx)
static int oisd_add_msg_cb(SMSCConn *conn, Msg *sms)
static struct packet * packet_parse(Octstr *packet_data)
smscconn_killed_t why_killed
static void oisd_start_cb(SMSCConn *conn)
static void oisd_close_socket(PrivData *pdata)
void msg_destroy_item(void *msg)
Octstr * octstr_imm(const char *cstr)
void * gwlist_extract_first(List *list)
void octstr_delete(Octstr *ostr1, long pos, long len)
void gwlist_remove_producer(List *list)
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
static void packet_destroy(struct packet *packet)
#define octstr_duplicate(ostr)
#define octstr_dump(ostr, level,...)
static struct packet * packet_create(int operation, unsigned long opref)
void msg_destroy(Msg *msg)
static void oisd_destroy(PrivData *pdata)
void warning(int err, const char *fmt,...)
Octstr * octstr_format(const char *fmt,...)
void octstr_destroy(Octstr *ostr)
static int oisd_expand_gsm7_to_bits(char *bits, Octstr *raw7)
#define gwthread_create(func, arg)
#define octstr_create(cstr)
int fields_to_dcs(Msg *msg, int mode)
void gwthread_sleep(double seconds)
static void packet_set_data_size(struct packet *packet)
#define SMS_PARAM_UNDEFINED
static int oisd_submit_msg(SMSCConn *conn, Msg *msg)
static int operation_can_receive(int operation)
static Octstr * operation_name(int operation)
volatile sig_atomic_t is_stopped
static void packet_set_send_sequence(struct packet *packet, PrivData *pdata)
static int operation_can_send(int operation)
static long oisd_queued_cb(SMSCConn *conn)
static struct packet * packet_encode_message(Msg *msg, SMSCConn *conn)
static int oisd_send_delivery_request(SMSCConn *conn)
long octstr_len(const Octstr *ostr)
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
void * gwlist_consume(List *list)
int read_available(int fd, long wait_usec)
static void oisd_send_response(struct packet *request, PrivData *pdata)
int(* shutdown)(SMSCConn *conn, int finish_sending)
static const struct @26 operations[]
void debug(const char *place, int err, const char *fmt,...)
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
void gwthread_wakeup(long thread)
long(* queued)(SMSCConn *conn)
int(* send_msg)(SMSCConn *conn, Msg *msg)
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
int dcs_to_fields(Msg **msg, int dcs)
static struct packet * oisd_get_packet(PrivData *pdata, Octstr **ts)
static Octstr * oisd_expand_gsm7(Octstr *raw7)
void gwlist_add_producer(List *list)
static Msg * sms_receive(SMSCConn *conn)
static int response(List *push_headers, Octstr **username, Octstr **password)
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
int octstr_get_char(const Octstr *ostr, long pos)
static int parm_valid_address(Octstr *value)
void octstr_set_char(Octstr *ostr, long pos, int ch)
#define octstr_create_from_data(data, len)
static void oisd_handle_request(struct packet *request, SMSCConn *conn)
static int oisd_shutdown_cb(SMSCConn *conn, int finish_sending)
static int oisd_login(SMSCConn *conn)
#define DLR_IS_SUCCESS_OR_FAIL(dlr)
static XMLRPCDocument * msg
static int operation_find(int operation)
static void reply(HTTPClient *c, List *push_headers)
void charset_gsm_to_utf8(Octstr *ostr)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)