108 #define SMASI_DEFAULT_PORT 21500 109 #define SMASI_DEFAULT_PRIORITY 0 110 #define MAX_PENDING_SUBMITS 10 111 #define SMASI_THROTTLING_SLEEP_TIME 15 112 #define SMASI_ENQUIRE_LINK_INTERVAL 30.0 125 #define SMASI_OVERRIDE_SOURCE_TON 1 126 #define SMASI_OVERRIDE_SOURCE_NPI -1 127 #define SMASI_OVERRIDE_DEST_TON -1 128 #define SMASI_OVERRIDE_DEST_NPI -1 194 if (smasi == NULL)
return;
244 else if (
check ==
'\n') escaped =
cr;
245 else if (
check ==
'\r') escaped =
lf;
247 if (escaped != NULL) {
282 if (msb ==
'0') msb = 0;
283 else if (msb >=
'1' && msb <=
'9') msb -=
'1' + 1;
284 else msb -=
'a' + 10;
286 if (lsb ==
'0') lsb = 0;
287 else if (lsb >=
'1' && lsb <=
'9') lsb -=
'1' + 1;
288 else lsb -=
'a' + 10;
290 byte = msb << 4 | lsb;
312 int msb = (encode & 0xf0) >> 4;
313 int lsb = (encode & 0x0f) >> 0;
315 if (msb == 0) msb =
'0';
316 else if (msb < 10) msb =
'1' + msb - 1;
317 else msb =
'a' + msb - 10;
319 if (lsb == 0) lsb =
'0';
320 else if (lsb < 10) lsb =
'1' + lsb - 1;
321 else lsb =
'a' + lsb - 10;
353 if (msb != -1 && lsb != -1) {
363 error(0,
"Malformed binary encoded data.");
380 if (
override != -1) {
381 debug(
"bb.sms.smasi", 0,
"SMASI: Manually forced ton or npi to `%d'",
475 pdu->
u.SubmitReq.OriginatorType =
478 pdu->
u.SubmitReq.Sequence =
524 pdu->
u.SubmitReq.UserDataHeader =
527 pdu->
u.SubmitReq.BodyEncoding =
530 if (pdu->
u.SubmitReq.MsEncoding)
533 pdu->
u.SubmitReq.MsEncoding =
568 if (pdu->
u.DeliverReq.ProtocolId)
570 pdu->
u.DeliverReq.ProtocolId, 0, 10) == -1)
574 if (pdu->
u.DeliverReq.MsEncoding) {
588 if (pdu->
u.DeliverReq.UserDataHeader)
598 if (pdu->
u.DeliverReq.UserDataHeader &&
599 octstr_len(pdu->
u.DeliverReq.UserDataHeader) > 0) {
609 if (pdu->
u.DeliverReq.Class &&
611 pdu->
u.DeliverReq.Class, 0, 10) == -1)
615 if (pdu->
u.DeliverReq.ProtocolId &&
617 pdu->
u.DeliverReq.ProtocolId, 0, 10) == -1)
698 error(0,
"SMASI[%s]: PDU unpacking failed.",
700 debug(
"bb.sms.smasi", 0,
"SMASI[%s]: Failed PDU follows.",
730 time(&
msg->sms.time);
735 if (pdu->
u.DeliverReq.Sequence)
736 resp->
u.DeliverConf.Sequence =
739 if (pdu->
u.DeliverReq.MsgReference)
740 resp->
u.DeliverConf.MsgReference =
745 if (pdu->
u.SubmitConf.Sequence) {
747 pdu->
u.SubmitConf.Sequence);
753 warning(0,
"SMASI[%s]: SMSC sent SubmitConf for unknown message.",
756 debug(
"bb.sms.smasi",0,
757 "SMSC[%s]: SMSC confirmed msg seq <%s> ref <%s>",
764 --(*pending_submits);
769 if (pdu->
u.SubmitRej.Sequence) {
771 pdu->
u.SubmitRej.Sequence);
776 error(0,
"SMASI[%s]: SMSC returned error code %s for " 782 warning(0,
"SMASI[%s]: SMSC sent SubmitRej for unknown message.",
788 --(*pending_submits);
793 *pending_submits = 0;
800 info(0,
"SMASI[%s]: connection to SMSC established.",
806 error(0,
"SMASI[%s]: SMSC rejected login with reason <%s>",
810 error(0,
"SMASI[%s]: SMSC rejected login without reason",
816 info(0,
"SMASI[%s]: SMSC confirmed logoff.",
822 warning(0,
"SMASI[%s]: Unknown PDU type <%s>, ignored.",
848 error(0,
"SMASI[%s]: Couldn't connect to server.",
869 long *pending_submits)
873 if (*pending_submits == -1)
return;
884 if (
msg == NULL)
break;
889 if (pdu->
u.SubmitReq.Sequence)
900 ++(*pending_submits);
913 long pending_submits;
916 int logoff_already_sent = 0;
919 long last_enquire_sent;
931 error(0,
"SMASI[%s]: Could not connect to SMSC center " \
932 "(retrying in %ld seconds).",
941 pending_submits = -1;
949 error(0,
"SMASI[%s]: I/O error or other error. Re-connecting.",
955 if (smasi->
quitting && !logoff_already_sent) {
957 logoff_already_sent = 1;
964 while ((ret =
read_pdu(smasi, conn, &pdu)) == 1) {
969 handle_pdu(smasi, conn, pdu, &pending_submits);
986 error(0,
"SMASI[%s]: I/O error or other error. Re-connecting.",
1036 SMASI *smasi = NULL;
1038 debug(
"bb.sms.smasi", 0,
"Shutting down SMSCConn %s (%s)",
1049 debug(
"bb.sms.smasi", 0,
"SMSCConn %s shut down.",
1079 if (smasi->
host == NULL) {
1080 error(0,
"SMASI: Configuration file doesn't specify host");
1084 error(0,
"SMASI: Configuration file doesn't specify username.");
1088 error(0,
"SMASI: Configuration file doesn't specify password.");
1122 if (smasi->
conn->
id == NULL)
1131 SMASI *smasi = NULL;
1146 panic(0,
"SMASI SMSC module configuration invalid.");
1156 error(0,
"SMASI[%s]: Couldn't start SMASI thread.",
Dict * dict_create(long size_hint, void(*destroy_value)(void *))
static int send_pdu(Connection *conn, Octstr *id, SMASI_PDU *pdu)
void smasi_pdu_dump(SMASI_PDU *pdu)
void msg_dump(Msg *msg, int level)
void error(int err, const char *fmt,...)
void info(int err, const char *fmt,...)
Msg * msg_duplicate(Msg *msg)
void bb_smscconn_connected(SMSCConn *conn)
static void decode_binary_data(Octstr *data)
#define SMASI_OVERRIDE_SOURCE_TON
#define SMASI_OVERRIDE_SOURCE_NPI
gw_assert(wtls_machine->packet_to_send !=NULL)
void dict_put(Dict *dict, Octstr *key, void *value)
void counter_destroy(Counter *counter)
#define SMASI_DEFAULT_PRIORITY
void bb_smscconn_killed(void)
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)
static SMASI_PDU * msg_to_pdu(SMASI *smasi, Msg *msg)
long gwlist_len(List *list)
time_t throttling_err_time
void octstr_append_char(Octstr *ostr, int ch)
#define SMASI_OVERRIDE_DEST_TON
static int shutdown_cb(SMSCConn *conn, int finish_sending)
#define cfg_get(grp, varname)
long enquire_link_interval
static void check(void *arg)
void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
int conn_eof(Connection *conn)
static void escape_data(Octstr *data)
SMASI_PDU * smasi_pdu_create(unsigned long type)
static void encode_binary_data(Octstr *data)
#define octstr_get_cstr(ostr)
unsigned long counter_increase(Counter *counter)
#define GSM_ADDR_TON_INTERNATIONAL
void log_thread_to(int idx)
Octstr * smasi_pdu_pack(SMASI_PDU *pdu)
static void send_enquire_link(SMASI *smasi, Connection *conn, long *last_sent)
int smsc_smasi_create(SMSCConn *conn, CfgGroup *config)
smscconn_killed_t why_killed
static void unescape_data(Octstr *data)
void msg_destroy_item(void *msg)
Octstr * octstr_imm(const char *cstr)
int conn_write(Connection *conn, Octstr *data)
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
void * dict_remove(Dict *dict, Octstr *key)
Counter * counter_create(void)
void * gwlist_extract_first(List *list)
static Octstr * get_originator_type(SMASI *smasi, Octstr *originator)
static SMASI * smasi_create(SMSCConn *conn)
SMASI_PDU * smasi_pdu_unpack(Octstr *data_without_len)
void octstr_delete(Octstr *ostr1, long pos, long len)
static Octstr * get_source_addr_npi(SMASI *smasi, Msg *msg)
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
void conn_destroy(Connection *conn)
static void send_messages(SMASI *smasi, Connection *conn, long *pending_submits)
#define octstr_duplicate(ostr)
#define octstr_dump(ostr, level,...)
Octstr * smasi_pdu_read(Connection *conn)
static void smasi_destroy(SMASI *smasi)
Connection * conn_open_tcp_with_port(Octstr *host, int port, int our_port, Octstr *our_host)
#define SMASI_THROTTLING_SLEEP_TIME
void warning(int err, const char *fmt,...)
static Octstr * get_ton_npi_value(int override, int message)
Octstr * octstr_format(const char *fmt,...)
void octstr_destroy(Octstr *ostr)
#define gwthread_create(func, arg)
#define octstr_create(cstr)
void gwthread_sleep(double seconds)
#define SMS_PARAM_UNDEFINED
#define MAX_PENDING_SUBMITS
static int init_configuration(SMASI *smasi, CfgGroup *config)
#define SMASI_ENQUIRE_LINK_INTERVAL
long date_universal_now(void)
static Octstr * get_source_addr_ton(SMASI *smasi, Msg *msg)
long octstr_len(const Octstr *ostr)
void dict_destroy(Dict *dict)
static void send_logoff(SMASI *smasi, Connection *conn)
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
int conn_wait(Connection *conn, double seconds)
#define GSM_ADDR_NPI_E164
int(* shutdown)(SMSCConn *conn, int finish_sending)
static int send_msg_cb(SMSCConn *conn, Msg *msg)
static Msg * pdu_to_msg(SMASI_PDU *pdu)
void debug(const char *place, int err, const char *fmt,...)
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
#define SMASI_DEFAULT_PORT
void gwthread_wakeup(long thread)
int octstr_hex_to_binary(Octstr *ostr)
int octstr_str_compare(const Octstr *ostr, const char *str)
static void dump_pdu(const char *msg, Octstr *id, SMASI_PDU *pdu)
long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
static Octstr * get_dest_addr_npi(SMASI *smasi, Msg *msg)
long(* queued)(SMSCConn *conn)
int(* send_msg)(SMSCConn *conn, Msg *msg)
static Octstr * get_dest_addr_ton(SMASI *smasi, Msg *msg)
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
int conn_error(Connection *conn)
#define SMASI_OVERRIDE_DEST_NPI
static int read_pdu(SMASI *smasi, Connection *conn, SMASI_PDU **pdu)
#define GSM_ADDR_TON_ALPHANUMERIC
static void smasi_thread(void *arg)
void gwlist_add_producer(List *list)
int octstr_get_char(const Octstr *ostr, long pos)
static XMLRPCDocument * msg
static void handle_pdu(SMASI *smasi, Connection *conn, SMASI_PDU *pdu, long *pending_submits)
void smasi_pdu_destroy(SMASI_PDU *pdu)
static long queued_cb(SMSCConn *conn)
Counter * message_id_counter
static Connection * open_connection(SMASI *smasi)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)