opensmppbox patch with MSSQL support (opensmppbox part)
Aarno Syvanen <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi List, there is paths adding MSSQL support for delivery reports Aarno
box.diff
(application/octet-stream, 47.7 KB)
--- gw/opensmppbox.c 2012-02-08 11:55:45.000000000 +0100
+++ /Users/aarno/opensmppbox/gw/opensmppbox.c 2012-02-16 11:42:32.000000000 +0100
@@ -76,7 +76,6 @@
#include "gw/smsc/smpp_pdu.h"
#include "gw/sms.h"
-#include "gw/dlr.h"
#include "gw/heartbeat.h"
#include "gw/meta_data.h"
@@ -84,6 +83,9 @@
#undef GW_VERSION
#include "../sb-config.h"
+#include "box-dlr.h"
+#include "gw/dlr.h"
+
#ifdef HAVE_PAM_SECURITY
#include <security/pam_appl.h>
#elif defined HAVE_PAM_PAM
@@ -118,17 +120,24 @@
static Octstr *smppbox_id;
static Octstr *our_system_id;
-static Octstr *route_to_smsc;
+static Octstr *route_to_smsc = NULL;
static time_t smpp_timeout;
static int systemidisboxcid;
static int enablepam;
static Octstr *pamacl;
+static int usesmppboxid;
+static Dict *client_by_smsc;
+static Dict *client_by_receiver;
+static Dict *client_by_smsc_receiver;
#define TIMEOUT_SECONDS 300
-typedef enum { SMPP_LOGIN_NOTLOGGEDIN, SMPP_LOGIN_TRANSMITTER, SMPP_LOGIN_RECEIVER, SMPP_LOGIN_TRANSCEIVER } smpp_login;
+typedef enum { SMPP_LOGIN_NOTLOGGEDIN, SMPP_LOGIN_TRANSMITTER, SMPP_LOGIN_RECEIVER,
+ SMPP_LOGIN_TRANSCEIVER } smpp_login;
+
+enum {USE_UUID = 0, USE_SMPP_ID = 1};
typedef struct _boxc {
Connection *smpp_connection;
@@ -149,8 +158,9 @@
Dict *sent;
Semaphore *pending;
volatile sig_atomic_t alive;
- Octstr *boxc_id; /* identifies the connected opensmppbox instance */
- Octstr *sms_service;
+ Octstr *boxc_id; /* identifies connected client */
+ Octstr *our_id; /* Idenfies us to our bearerbox */
+ Octstr *sms_service; //
Octstr *route_to_smsc;
Dict *msg_acks;
Dict *deliver_acks;
@@ -173,11 +183,105 @@
} Boxc;
+typedef struct _bbboxc {
+ Connection *bearerbox_connection;
+ volatile sig_atomic_t alive;
+ Dict *msg_acks;
+ Dict *deliver_acks;
+ int mo_recode;
+} BBBoxc;
+
+static BBBoxc *bbbox;
+
+
+static void msg_list_destroy(List *l)
+{
+ long i, len;
+ Msg *item;
+
+ i = 0;
+ len = gwlist_len(l);
+ while (i < len) {
+ item = gwlist_get(l, i);
+ msg_destroy(item); item = NULL;
+ ++i;
+ }
+}
+
+static void msg_list_destroy_item(void *item)
+{
+ msg_list_destroy(item);
+}
+
+static void box_dump_salient(Boxc *boxc)
+{
+ if (!boxc) {
+ debug("opensmppbox", 0, "client pointer points to NULL");
+ return;
+ }
+
+ debug("opensmppbox", 0, "client dump starts");
+ if (boxc->client_ip)
+ debug("opensmppbox", 0, "client ip address was <%s>", octstr_get_cstr(boxc->client_ip));
+ if (boxc->our_id)
+ debug("opensmppbox", 0, "our id to bearerbox was <%s>", octstr_get_cstr(boxc->our_id));
+ if (boxc->boxc_id)
+ debug("opensmppbox", 0, "client id (username) was <%s>", octstr_get_cstr(boxc->boxc_id));
+ debug("opensmppbox", 0, "client dump ends");
+}
+
+static void box_list_dump_salient(List *boxes)
+{
+ long i, len;
+ Boxc *box;
+
+ i = 0;
+ len = gwlist_len(boxes);
+ while (i < len) {
+ box = gwlist_get(boxes, i);
+ box_dump_salient(box);
+ ++i;
+ }
+}
+
+void box_id_dict_dump(Dict *box_id_by_msg_id)
+{
+ long i, count;
+ List *ids;
+ Octstr *key;
+ Octstr *box_id;
+
+ gwlib_assert_init();
+
+ debug("opensmppbox", 0, "Dumping box_id dict:");
+ if (!box_id_by_msg_id) {
+ debug("opensmppbox", 0, "box id dict point NULL");
+ return;
+ }
+
+ ids = dict_keys(box_id_by_msg_id);
+ count = dict_key_count(box_id_by_msg_id);
+ for (i = 0; i < count; ++i) {
+ key = gwlist_get(ids, i);
+ box_id = dict_get(box_id_by_msg_id, key);
+ debug("opensmppbox", 0, "Msg id %ld was: ", i);
+ octstr_dump(key, 0);
+ debug("opensmppbox", 0, "Box id %ld was: ", i);
+ octstr_dump(box_id, 0);
+ }
+ debug("opensmppbox", 0, "End of dump.");
+}
+
void smpp_pdu_destroy_item(void *pdu)
{
smpp_pdu_destroy(pdu);
}
+static void shutdown_connection(Connection *conn)
+{
+ conn_destroy(conn);
+}
+
/*
* Use PAM (Pluggable Authentication Module) to check sendsms authentication.
*/
@@ -309,16 +414,18 @@
valid_login:
for (box = 0; box < gwlist_len(all_boxes); box++) {
thisbox = (Boxc *)gwlist_get(all_boxes, box);
- if (octstr_compare(system_type, thisbox->boxc_id) == 0 && (thisbox->login_type == SMPP_LOGIN_TRANSCEIVER || (thisbox->login_type == login_type))) {
- debug("bb.sms.smpp", 0, "opensmppbox[%s]: Multiple login: disconnect.",
- octstr_get_cstr(thisbox->boxc_id));
+ if (system_type && thisbox && thisbox->boxc_id && octstr_compare(system_type, thisbox->boxc_id) == 0 &&
+ (thisbox->login_type == SMPP_LOGIN_TRANSCEIVER || (thisbox->login_type == login_type))) {
+ debug("opensmppbox", 0, "opensmppbox[%s]: Multiple login: disconnect", octstr_get_cstr(thisbox->boxc_id));
thisbox->alive = 0;
#ifdef HAVE_SHUTDOWN_CONNECTION
+ if (!use_smppboxid)
shutdown_connection(thisbox->bearerbox_connection);
shutdown_connection(thisbox->smpp_connection);
#endif
}
}
+
return 1;
}
@@ -342,6 +449,12 @@
} while(0)
#endif
+static void dump_pdu_debug(char *msg, Octstr *id, SMPP_PDU *pdu)
+{
+ debug("opensmppbox", 0, "SMPP[%s]: %s", \
+ octstr_get_cstr(id), msg); \
+ smpp_pdu_dump(pdu);
+}
/*
* Converting SMPP timestamp to minutes relative
@@ -396,7 +509,7 @@
localdiff = difftime(gw_mktime(&local), gw_mktime(&tm));
valutc += localdiff;
- debug("sms.smpp",0, "diff between utc and localtime (%d)", localdiff);
+ debug("opensmppbox",0, "diff between utc and localtime (%d)", localdiff);
diff = diff*15*60;
switch(relation) {
case '+':
@@ -421,10 +534,10 @@
return -1;
}
tm = gw_gmtime(valutc);
- debug("sms.smpp",0,"Requested UTC timestamp: %02d-%02d-%02d %02d:%02d:%02d",
+ debug("opensmppbox",0,"Requested UTC timestamp: %02d-%02d-%02d %02d:%02d:%02d",
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
- debug("sms.smpp", 0, "requested timestamp in min. (%ld)", (valutc - utc)/60);
+ debug("opensmppbox", 0, "requested timestamp in min. (%ld)", (valutc - utc)/60);
return ceil ( difftime (valutc, utc) / 60 );
}
@@ -440,7 +553,7 @@
/* send to bearerbox */
-static int send_msg(Connection *conn, Boxc *boxconn, Msg *pmsg)
+static int send_msg(Connection *conn, Msg *pmsg)
{
/* Caution: implicit msg_destroy */
write_to_bearerbox_real(conn, pmsg);
@@ -456,7 +569,7 @@
for (pos = 0; pos < gwlist_len(all_boxes); pos++) {
box = (Boxc *)gwlist_get(all_boxes, pos);
- send_msg(box->bearerbox_connection, box, msg);
+ send_msg(box->bearerbox_connection, msg);
}
}
*/
@@ -474,40 +587,43 @@
* Do this even while no opensmppbox-id is given to unlock the sender thread in
* bearerbox.
*/
-static void identify_to_bearerbox(Boxc *conn)
+static void identify_to_bearerbox(Connection *conn, Octstr *our_id)
{
Msg *msg;
msg = msg_create(admin);
msg->admin.command = cmd_identify;
- msg->admin.boxc_id = octstr_duplicate(conn->boxc_id);
- send_msg(conn->bearerbox_connection, conn, msg);
+ msg->admin.boxc_id = octstr_duplicate(our_id);
+ send_msg(conn, msg);
}
/* read from bearerbox */
-static Msg *read_from_box(Connection *conn, Boxc *boxconn)
+/* ret is -1, when connection was broke, 0 when we had a message and 1 when we had a timeout*/
+static Msg *read_from_box(Connection *conn, int alive, int *ret)
{
Octstr *pack;
- Msg *msg;
+ Msg *msg = NULL;
pack = NULL;
- while (boxconn->alive) {
- switch (read_from_bearerbox_real(conn, &msg, 1.0)) {
+ while (alive) {
+ switch (read_from_bearerbox_real(conn, &msg, 0.1)) {
case -1:
/* connection to bearerbox lost */
+ *ret = -1;
return NULL;
- break;
case 0:
/* all is well */
+ *ret = 0;
return msg;
- break;
case 1:
/* timeout */
- break;
+ *ret = 1;
+ return NULL;
}
}
+ *ret = -1;
return msg;
}
@@ -626,7 +742,7 @@
/* generate 8 character ID, taken from msgid */
static Octstr *generate_smppid(Msg *msg)
{
- char uuidbuf[100];
+ char uuidbuf[UUID_STR_LEN + 1];
Octstr *result;
// gw_assert(msg->type == sms); // we segfault on this
@@ -673,7 +789,7 @@
if (*pdu == NULL) {
error(0, "opensmppbox[%s]: PDU unpacking failed.",
octstr_get_cstr(box->boxc_id));
- debug("bb.sms.smpp", 0, "opensmppbox[%s]: Failed PDU omitted.",
+ debug("opensmppbox", 0, "opensmppbox[%s]: Failed PDU omitted.",
octstr_get_cstr(box->boxc_id));
/* octstr_dump(os, 0); */
octstr_destroy(os);
@@ -684,6 +800,59 @@
return 1;
}
+static int msg_is_report_mo(Msg *msg)
+{
+ return msg->sms.sms_type == report_mo;
+}
+
+ /* To route to the original client, we restore the original
+ * box id (i.e., essentially the username).
+ * For report mo, we get id of the original message following way:
+ * a) in case of HTTP SMSC drl-url up to semicolon
+ * b) otherwise (AT & SMPP tested), the whole dlr_url
+ */
+static void restore_box_id(Msg *msg)
+{
+ if (msg_is_report_mo(msg)) {
+ Msg *dlr = NULL;
+ Octstr *boxid = NULL;
+ Octstr *msgid = NULL;
+ long semicolon = -1;
+
+ if (msg->sms.dlr_url)
+ semicolon = octstr_search(msg->sms.dlr_url, octstr_imm(";"), 0);
+
+ if (semicolon > -1)
+ msgid = octstr_copy(msg->sms.dlr_url, 0, semicolon);
+ else
+ msgid = octstr_duplicate(msg->sms.dlr_url);
+
+ if (msgid) {
+ dlr = dlr_find_by_id(msgid, USE_SMPP_ID);
+
+ if (dlr && dlr->sms.boxc_id) {
+ boxid = octstr_duplicate(dlr->sms.boxc_id);
+
+ if (boxid) {
+ octstr_destroy(msg->sms.boxc_id);
+ msg->sms.boxc_id = octstr_duplicate(boxid);
+ }
+
+ octstr_destroy(boxid); boxid = NULL;
+ msg_destroy(dlr); dlr = NULL;
+ }
+ octstr_destroy(msgid);
+ }
+ }
+ /* MOs are routed separately, using smsc_id */
+}
+
+static void change_box_id(Msg *msg)
+{
+ octstr_destroy(msg->sms.boxc_id);
+ msg->sms.boxc_id = octstr_duplicate(smppbox_id);
+}
+
static List *msg_to_pdu(Boxc *box, Msg *msg)
{
SMPP_PDU *pdu, *pdu2;
@@ -702,8 +871,7 @@
Octstr *header, *footer, *suffix, *split_chars;
Msg *msg2;
- pdu = smpp_pdu_create(deliver_sm,
- counter_increase(box->smpp_pdu_counter));
+ pdu = smpp_pdu_create(deliver_sm, counter_increase(box->smpp_pdu_counter));
pdu->u.deliver_sm.source_addr = octstr_duplicate(msg->sms.sender);
pdu->u.deliver_sm.destination_addr = octstr_duplicate(msg->sms.receiver);
@@ -717,7 +885,7 @@
if(box->source_addr_ton > -1 && box->source_addr_npi > -1) {
pdu->u.deliver_sm.source_addr_ton = box->source_addr_ton;
pdu->u.deliver_sm.source_addr_npi = box->source_addr_npi;
- debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced source addr ton = %ld, source add npi = %ld",
+ debug("opensmppbox", 0, "SMPP[%s]: Manually forced source addr ton = %ld, source add npi = %ld",
octstr_get_cstr(box->boxc_id), box->source_addr_ton,
box->source_addr_npi);
} else {
@@ -749,7 +917,7 @@
if (box->dest_addr_ton > -1 && box->dest_addr_npi > -1) {
pdu->u.deliver_sm.dest_addr_ton = box->dest_addr_ton;
pdu->u.deliver_sm.dest_addr_npi = box->dest_addr_npi;
- debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced dest addr ton = %ld, dest add npi = %ld",
+ debug("opensmppbox", 0, "SMPP[%s]: Manually forced dest addr ton = %ld, dest add npi = %ld",
octstr_get_cstr(box->boxc_id), box->dest_addr_ton,
box->dest_addr_npi);
} else {
@@ -770,7 +938,9 @@
if (octstr_len(pdu->u.deliver_sm.destination_addr) > 20 ||
octstr_len(pdu->u.deliver_sm.source_addr) > 20) {
smpp_pdu_destroy(pdu);
- gwlist_destroy(pdulist, NULL);
+
+ gwlist_destroy(pdulist, smpp_pdu_destroy_item);
+ warning(0, "opensmppbox: msg_to_pdu: address too long, not acceptable");
return NULL;
}
@@ -807,7 +977,7 @@
ESM_CLASS_SUBMIT_RPI;
/* Is this a delivery report? */
- if (msg->sms.sms_type == report_mo) {
+ if (msg_is_report_mo(msg)) {
pdu->u.deliver_sm.esm_class |= ESM_CLASS_DELIVER_SMSC_DELIVER_ACK;
dlrtype = msg->sms.dlr_mask;
parts = octstr_split(msg->sms.dlr_url, octstr_imm(";"));
@@ -816,9 +987,10 @@
if (dlr == NULL) {
/* we could not find a corresponding dlr; nothing to send */
smpp_pdu_destroy(pdu);
- gwlist_destroy(pdulist, NULL);
+ gwlist_destroy(pdulist, smpp_pdu_destroy_item);
octstr_destroy(msgid);
gwlist_destroy(parts, octstr_destroy_item);
+ warning(0, "opensmppbox: msg_to_pdu: no msg corresponding dlr, ignoring");
return NULL;
}
dlvrd = octstr_imm("000");
@@ -901,7 +1073,7 @@
if (box->version > 0x33) {
pdu2->u.deliver_sm.receipted_message_id = octstr_duplicate(msgid2);
pdu2->u.deliver_sm.message_state = dlr_state;
- dict_destroy(pdu2->u.deliver_sm.tlv);
+ dict_destroy(pdu->u.deliver_sm.tlv);
pdu2->u.deliver_sm.tlv = meta_data_get_values(msg->sms.meta_data, "smpp");
}
pdu2->u.deliver_sm.short_message = octstr_format("id:%S sub:001 dlvrd:%S submit date:%s done date:%s stat:%S err:%s text:%12s", msgid2, dlvrd, submit_date_c_str, done_date_c_str, dlr_status, err, text);
@@ -1028,7 +1200,7 @@
parts = NULL;
}
- debug("SMPP", 0, "message length %ld, sending %ld message%s",
+ debug("opensmppbox", 0, "message length %ld, sending %ld message%s",
octstr_len(msg->sms.msgdata), msg_count, msg_count == 1 ? "" : "s");
if (parts) {
@@ -1067,7 +1239,7 @@
}
else {
if (box->version > 0x33) {
- dict_destroy(pdu->u.deliver_sm.tlv);
+ dict_destroy(pdu->u.deliver_sm.tlv); pdu->u.deliver_sm.tlv = NULL;
pdu->u.deliver_sm.tlv = meta_data_get_values(msg->sms.meta_data, "smpp");
}
@@ -1162,7 +1333,7 @@
if (pdu->u.submit_sm.esm_class & ESM_CLASS_SUBMIT_UDH_INDICATOR) {
int udhl;
udhl = octstr_get_char(msg->sms.msgdata, 0) + 1;
- debug("bb.sms.smpp",0,"SMPP[%s]: UDH length read as %d",
+ debug("opensmppbox",0,"SMPP[%s]: UDH length read as %d",
octstr_get_cstr(box->boxc_id), udhl);
if (udhl > octstr_len(msg->sms.msgdata)) {
error(0, "SMPP[%s]: Mallformed UDH length indicator 0x%03x while message length "
@@ -1348,7 +1518,7 @@
if (pdu->u.data_sm.esm_class & ESM_CLASS_SUBMIT_UDH_INDICATOR) {
int udhl;
udhl = octstr_get_char(msg->sms.msgdata, 0) + 1;
- debug("bb.sms.smpp",0,"SMPP[%s]: UDH length read as %d",
+ debug("opensmppbox",0,"SMPP[%s]: UDH length read as %d",
octstr_get_cstr(box->boxc_id), udhl);
if (udhl > octstr_len(msg->sms.msgdata)) {
error(0, "SMPP[%s]: Mallformed UDH length indicator 0x%03x while message length "
@@ -1494,12 +1664,18 @@
static void handle_pdu(Connection *conn, Boxc *box, SMPP_PDU *pdu) {
SMPP_PDU *resp = NULL;
- Msg *msg, *msg2, *mack;
+ Msg *msg = NULL, *msg2 = NULL, *mack = NULL;
long reason;
- Octstr *msgid = NULL, *hold_service, *system_type;
+ Octstr *msgid = NULL, *hold_service = NULL, *system_type = NULL;
int msg_to_send = 1;
List *parts_list = NULL;
char id[UUID_STR_LEN + 1];
+ Connection *bearerbox_connection;
+
+ if (usesmppboxid)
+ bearerbox_connection = bbbox->bearerbox_connection;
+ else
+ bearerbox_connection = box->bearerbox_connection;
dump_pdu("Got PDU:", box->boxc_id, pdu);
switch (pdu->type) {
@@ -1516,6 +1692,7 @@
break;
}
switch (pdu->type) {
+ /* We set a substitute box id here, if smppbox id is used*/
case bind_transmitter:
system_type = pdu->u.bind_transmitter.system_type ? pdu->u.bind_transmitter.system_type : octstr_imm("");
if (check_login(box, pdu->u.bind_transmitter.system_id, pdu->u.bind_transmitter.password, system_type, SMPP_LOGIN_TRANSMITTER)) {
@@ -1524,11 +1701,12 @@
box->login_type = SMPP_LOGIN_TRANSMITTER;
box->boxc_id = systemidisboxcid ? octstr_duplicate(pdu->u.bind_transmitter.system_id) : octstr_duplicate(system_type);
box->sms_service = octstr_duplicate(pdu->u.bind_transmitter.system_id);
- identify_to_bearerbox(box);
+ if (!usesmppboxid)
+ identify_to_bearerbox(box->bearerbox_connection, box->boxc_id);
resp = smpp_pdu_create(bind_transmitter_resp, pdu->u.bind_transmitter.sequence_number);
resp->u.bind_transmitter_resp.system_id = octstr_duplicate(our_system_id);
- }
- else {
+ debug("opensmppbox", 0, "Client connected with id %s", octstr_get_cstr(box->boxc_id));
+ } else {
resp = smpp_pdu_create(bind_transmitter_resp, pdu->u.bind_transmitter_resp.sequence_number);
resp->u.bind_transmitter.command_status = 0x0d; /* invalid login */
}
@@ -1541,9 +1719,11 @@
box->login_type = SMPP_LOGIN_RECEIVER;
box->boxc_id = systemidisboxcid ? octstr_duplicate(pdu->u.bind_transmitter.system_id) : octstr_duplicate(system_type);
box->sms_service = octstr_duplicate(pdu->u.bind_receiver.system_id);
- identify_to_bearerbox(box);
+ if (!usesmppboxid)
+ identify_to_bearerbox(box->bearerbox_connection, box->boxc_id);
resp = smpp_pdu_create(bind_receiver_resp, pdu->u.bind_receiver.sequence_number);
resp->u.bind_receiver_resp.system_id = octstr_duplicate(our_system_id);
+ debug("opensmppbox", 0, "Client connected with id %s", octstr_get_cstr(box->boxc_id));
}
else {
resp = smpp_pdu_create(bind_receiver_resp, pdu->u.bind_receiver.sequence_number);
@@ -1558,9 +1738,11 @@
box->login_type = SMPP_LOGIN_TRANSCEIVER;
box->boxc_id = systemidisboxcid ? octstr_duplicate(pdu->u.bind_transmitter.system_id) : octstr_duplicate(system_type);
box->sms_service = octstr_duplicate(pdu->u.bind_transceiver.system_id);
- identify_to_bearerbox(box);
+ if (!usesmppboxid)
+ identify_to_bearerbox(box->bearerbox_connection, box->boxc_id);
resp = smpp_pdu_create(bind_transceiver_resp, pdu->u.bind_transceiver.sequence_number);
resp->u.bind_transceiver_resp.system_id = octstr_duplicate(our_system_id);
+ debug("opensmppbox", 0, "Client connected with id %s", octstr_get_cstr(box->boxc_id));
}
else {
resp = smpp_pdu_create(bind_transceiver_resp, pdu->u.bind_transceiver.sequence_number);
@@ -1587,7 +1769,6 @@
check_multipart(box, msg, &msg_to_send, &msg2, &parts_list);
msg->sms.smsc_id = box->route_to_smsc ? octstr_duplicate(box->route_to_smsc) : NULL;
msg->sms.boxc_id = octstr_duplicate(box->boxc_id);
- msg_dump(msg, 0);
resp = smpp_pdu_create(data_sm_resp, pdu->u.data_sm.sequence_number);
msgid = generate_smppid(msg);
msg->sms.dlr_url = octstr_duplicate(msgid);
@@ -1596,20 +1777,29 @@
if (DLR_IS_ENABLED(msg2->sms.dlr_mask)) {
hold_service = msg2->sms.service;
msg2->sms.service = octstr_format("%ld", msg2->sms.time);
+ octstr_destroy(msgid);
msgid = generate_smppid(msg2);
if (parts_list) {
msg2->sms.dlr_url = concat_msgids(msgid, parts_list);
}
- dlr_add(box->boxc_id, msgid, msg2);
+ msg_add(box->boxc_id, msgid, msg2);
+ if (usesmppboxid)
+ change_box_id(msg2);
octstr_destroy(msgid);
octstr_destroy(msg2->sms.service);
msg2->sms.service = hold_service;
}
uuid_unparse(msg2->sms.id, id);
msgid = octstr_create(id);
+ if (!usesmppboxid)
dict_put(box->msg_acks, msgid, resp);
+ else
+ dict_put(bbbox->msg_acks, msgid, resp);
resp = NULL;
- send_msg(box->bearerbox_connection, box, msg2);
+ if (usesmppboxid) {
+ send_msg(bearerbox_connection, msg2);
+ } else
+ send_msg(box->bearerbox_connection, msg2);
if (parts_list) {
/* destroy values */
gwlist_destroy(parts_list, msg_destroy_item);
@@ -1628,21 +1818,28 @@
check_multipart(box, msg, &msg_to_send, &msg2, &parts_list);
msg->sms.smsc_id = box->route_to_smsc ? octstr_duplicate(box->route_to_smsc) : NULL;
msg->sms.boxc_id = octstr_duplicate(box->boxc_id);
- msg_dump(msg, 0);
resp = smpp_pdu_create(submit_sm_resp, pdu->u.submit_sm.sequence_number);
msgid = generate_smppid(msg);
msg->sms.dlr_url = octstr_duplicate(msgid);
- resp->u.submit_sm_resp.message_id = msgid;
+ resp->u.submit_sm_resp.message_id = octstr_duplicate(msgid);
+ /* Note that we add msg to dlr tzble in all cases.
+ * In case of report_mo, need is obvious. In case
+ * of mo, it is needed to route resps. Report mo must be stored before
+ * we change box id.*/
+ if (usesmppboxid)
+ msg_add(msg->sms.boxc_id, msgid, msg);
if (msg_to_send) {
if (DLR_IS_ENABLED(msg2->sms.dlr_mask)) {
hold_service = msg2->sms.service;
msg2->sms.service = octstr_format("%ld", msg2->sms.time);
+ octstr_destroy(msgid);
msgid = generate_smppid(msg2);
if (parts_list) {
msg2->sms.dlr_url = concat_msgids(msgid, parts_list);
}
- dlr_add(box->boxc_id, msgid, msg2);
- octstr_destroy(msgid);
+ //dlr_add(box->boxc_id, msgid, msg2);
+ if (usesmppboxid)
+ change_box_id(msg2);
octstr_destroy(msg2->sms.service);
msg2->sms.service = hold_service;
}
@@ -1646,19 +1843,32 @@
octstr_destroy(msg2->sms.service);
msg2->sms.service = hold_service;
}
+
uuid_unparse(msg2->sms.id, id);
+ octstr_destroy(msgid);
msgid = octstr_create(id);
+
+ if (!usesmppboxid) {
dict_put(box->msg_acks, msgid, resp);
- octstr_destroy(msgid);
+ } else {
+ dict_put(bbbox->msg_acks, msgid, resp);
+ }
resp = NULL;
- send_msg(box->bearerbox_connection, box, msg2);
+
+ if (usesmppboxid) {
+ send_msg(bearerbox_connection, msg2);
+ } else
+ send_msg(box->bearerbox_connection, msg2);
if (parts_list) {
/* destroy values */
gwlist_destroy(parts_list, msg_destroy_item);
}
+ octstr_destroy(msgid); msgid = NULL;
}
}
break;
+ /* Note that deliver_sm_resp message_id filed is set to NULL. Instead, the sequwnce number
+ * is used for identification. */
case deliver_sm_resp:
msgid = octstr_format("%ld", pdu->u.deliver_sm_resp.sequence_number);
mack = dict_get(box->deliver_acks, msgid);
@@ -1668,10 +1878,15 @@
if (pdu->u.deliver_sm_resp.command_status != 0) {
msg->ack.nack = ack_failed;
}
- send_msg(box->bearerbox_connection, box, msg);
- dict_put(box->deliver_acks, msgid, NULL);
+ if (usesmppboxid) {
+ send_msg(bearerbox_connection, msg);
+ } else {
+ send_msg(box->bearerbox_connection, msg);
+ }
+ dict_put(box->deliver_acks, msgid, NULL); /* would destroy the message */
}
- octstr_destroy(msgid);
+
+ octstr_destroy(msgid); msgid = NULL;
break;
case unbind_resp:
box->logged_in = 0;
@@ -1688,12 +1903,13 @@
resp->u.generic_nack.command_status = SMPP_ESME_RINVCMDID;
break;
}
+/* An intentional fall-through*/
error:
smpp_pdu_destroy(pdu);
if (resp != NULL) {
send_pdu(conn, box->boxc_id, resp);
- smpp_pdu_destroy(resp);
}
+ smpp_pdu_destroy(resp);
}
/*
@@ -1712,11 +1928,18 @@
boxc->is_wap = 0;
boxc->load = 0;
boxc->smpp_connection = conn_wrap_fd(fd, ssl);
+ boxc->bearerbox_connection = NULL;
boxc->id = counter_increase(boxid);
boxc->client_ip = octstr_duplicate(ip);
boxc->alive = 1;
boxc->connect_time = time(NULL);
+ /* If smmpbox id is not used, box id would be set when doing SMPP bind */
+ if (usesmppboxid)
+ boxc->our_id = octstr_duplicate(smppbox_id);
+ else
+ boxc->our_id = NULL;
boxc->boxc_id = NULL;
+ boxc->sms_service = NULL;
boxc->routable = 0;
boxc->smpp_pdu_counter = counter_create();
boxc->alt_charset = NULL; /* todo: get from config */
@@ -1754,6 +1977,8 @@
conn_destroy(boxc->bearerbox_connection);
if (boxc->boxc_id)
octstr_destroy(boxc->boxc_id);
+ if (boxc->our_id)
+ octstr_destroy(boxc->our_id);
if (boxc->alt_charset)
octstr_destroy(boxc->alt_charset);
counter_destroy(boxc->smpp_pdu_counter);
@@ -1762,11 +1987,45 @@
}
if (boxc->client_ip)
octstr_destroy(boxc->client_ip);
+ if (boxc->sms_service)
+ octstr_destroy(boxc->sms_service);
+
dict_destroy(boxc->msg_acks);
dict_destroy(boxc->deliver_acks);
gw_free(boxc);
}
+static void boxc_destroy_item(void *item)
+{
+ boxc_destroy(item);
+}
+
+static BBBoxc *bbboxc_create(void)
+{
+ BBBoxc *boxc;
+
+ boxc = gw_malloc(sizeof(BBBoxc));
+ boxc->bearerbox_connection = connect_to_bearerbox_real(bearerbox_host, bearerbox_port, bearerbox_port_ssl, NULL);
+ boxc->alive = 1;
+ boxc->mo_recode = 0;
+ boxc->msg_acks = dict_create(1024, smpp_pdu_destroy_item);
+
+ return boxc;
+}
+
+static void bbboxc_destroy(BBBoxc *boxc)
+{
+ if (boxc == NULL)
+ return;
+
+ if (boxc->bearerbox_connection)
+ conn_destroy(boxc->bearerbox_connection);
+
+ dict_destroy(boxc->msg_acks);
+
+ gw_free(boxc);
+}
+
/* ------------------------------------------------------------------
* SMPP thingies
* ------------------------------------------------------------------
@@ -1816,7 +2075,9 @@
SMPP_PDU *pdu;
long len;
+ error(0, "opensmppbox: smpp_to_bearerbox: thread starts");
box->last_pdu_received = time(NULL);
+
while (smppbox_status == SMPP_RUNNING && box->alive) {
len = 0;
switch (read_pdu(box, conn, &len, &pdu)) {
@@ -1838,16 +2099,126 @@
}
}
#ifdef HAVE_SHUTDOWN_CONNECTION
+ if (!usesmppboxid)
shutdown_connection(box->bearerbox_connection);
#endif
+ error(0, "opensmppbox: smpp_to_bearerbox: thread terminates");
+}
+
+/*
+ * Check do we have a specific route to pass this msg to client-id?
+ */
+static Octstr *find_configured_box_id(Msg *msg)
+{
+ Octstr *boxc_id = NULL;
+ Octstr *r, *s, *rs;
+ /*
+ * Check if we have a "client-route" for this msg.
+ * Where the shortcode route has a higher priority then the smsc-id rule.
+ * Highest priority has the combined <shortcode>:<smsc-id> route.
+ */
+ if (msg->sms.receiver == NULL)
+ return boxc_id;
+
+ if (msg->sms.smsc_id == NULL)
+ return boxc_id;
+
+ Octstr *os = octstr_format("%s:%s", octstr_get_cstr(msg->sms.receiver),
+ octstr_get_cstr(msg->sms.smsc_id));
+ s = (msg->sms.smsc_id ? dict_get(client_by_smsc, msg->sms.smsc_id) : NULL);
+ r = (msg->sms.receiver ? dict_get(client_by_receiver, msg->sms.receiver) : NULL);
+ rs = (os ? dict_get(client_by_smsc_receiver, os) : NULL);
+ octstr_destroy(os);
+ if (rs)
+ boxc_id = rs;
+ else if (r)
+ boxc_id = r;
+ else if (s)
+ boxc_id = s;
+
+ return boxc_id;
+}
+
+static Boxc *find_box_by_id(Octstr *boxc_id)
+{
+ Boxc *thisbox;
+ long retry = 0;
+ long i = 0;
+ long cnt = gwlist_len(all_boxes);
+ while (i < cnt) {
+ thisbox = gwlist_get(all_boxes, i);
+ if (!thisbox || !(thisbox->boxc_id)) {
+ ++i;
+ continue;
+ }
+
+ /* Reject connection that is just sending*/
+ if (thisbox->login_type == SMPP_LOGIN_TRANSMITTER){
+ ++i;
+ continue;
+ }
+
+ /* If the client was not logged in, wait some time*/
+ if (thisbox->login_type == SMPP_LOGIN_NOTLOGGEDIN && retry < 30){
+ ++retry;
+ if (retry < 30)
+ gwthread_sleep(0.1);
+ else
+ ++i;
+ continue;
+ }
+
+ if (boxc_id && octstr_compare(thisbox->boxc_id, boxc_id) == 0) {
+ return thisbox;
+ }
+ ++i;
+ }
+
+ return NULL;
}
-/* if this login was made as a transmitter, then find the corresponding receiver connection */
-static Boxc *find_receiver_box(Boxc *box)
+/*
+ * This function is used to route msg acks. Ack's msg id maps ack to original
+ * message. The box id of the original message is used for routing.
+ */
+static Boxc *find_receiver_box_by_msg_id(Octstr *msgid, Msg *msg)
+{
+ Msg *sack = NULL;
+ Octstr *boxid = NULL;
+ Boxc *thisbox = NULL;
+
+ sack = dlr_find_by_id(msgid, USE_UUID);
+ if (sack)
+ boxid = sack->sms.boxc_id;
+ else
+ return NULL;
+
+ if (boxid)
+ thisbox = find_box_by_id(boxid);
+ else {
+ msg_destroy(sack); sack = NULL;
+ return NULL;
+ }
+
+ msg_destroy(sack); sack = NULL;
+ return thisbox;
+}
+
+/* if this login was made as a transmitter or receiver, then find the corresponding
+ * receiver connection */
+static Boxc *find_receiver_box(Boxc *box, Msg *msg)
{
Boxc *thisbox;
int cnt;
+ Octstr *boxc_id = NULL;
+ int report_mo = 0;
+ int retry = 0;
+ if (usesmppboxid && octstr_len(msg->sms.boxc_id) > 0) {
+ boxc_id = msg->sms.boxc_id;
+ }
+
+ if (!usesmppboxid) {
if (box->login_type == SMPP_LOGIN_RECEIVER || box->login_type == SMPP_LOGIN_TRANSCEIVER) {
return box;
}
@@ -1858,37 +2229,101 @@
}
}
return box;
+ }
+
+ else {
+ /* If we had no clients, wait a little, bearerbox may resend when they be connecting*/
+ report_mo = 1;
+ while (gwlist_len(all_boxes) == 0 && retry < 3) {
+ gwthread_sleep(1);
+ ++retry;
+ }
+
+ if (gwlist_len(all_boxes) == 0 && retry == 3)
+ return NULL;
+
+ if (msg->sms.sms_type == mo) {
+ report_mo = 0;
+ boxc_id = find_configured_box_id(msg);
+ }
+
+ /*
+ * Mos will be routed simply by they boxc-id, defined by smsbox-route.
+ * If there is none, a random box is picked.
+ */
+ thisbox = find_box_by_id(boxc_id);
+
+ /* If no box was found and we have MO, pick a random box. In case
+ * of DLR, this is an error. */
+ if (!thisbox && !report_mo) {
+ thisbox = gwlist_get(all_boxes, gw_rand() % gwlist_len(all_boxes));
+ return thisbox;
+ }
+
+ return thisbox;
+ }
}
static void bearerbox_to_smpp(void *arg)
{
- Msg *msg, *mack;
- Boxc *box = arg;
- SMPP_PDU *pdu;
- List *pdulist;
+ Msg *msg = NULL, *mack = NULL;
+ Boxc *box = NULL;
+ BBBoxc *bbbox = NULL;
+ SMPP_PDU *pdu = NULL;;
+ List *pdulist = NULL;
int dreport, errcode;
- Boxc *receiver_box;
+ Boxc *receiver_box = NULL;
char id[UUID_STR_LEN + 1];
- Octstr *msgid;
+ Octstr *msgid = NULL;
+ int ret;
- while (smppbox_status == SMPP_RUNNING && box->alive) {
+ error(0, "opensmppbox: bearerbox_to_smpp: thread starts");
- msg = read_from_box(box->bearerbox_connection, box);
- if (msg == NULL) {
- if ((!box->alive) || conn_eof(box->bearerbox_connection)) {
+ if (!usesmppboxid) {
+ box = arg;
+ } else {
+ bbbox = arg;
+ }
+
+ while (smppbox_status == SMPP_RUNNING && (usesmppboxid ? bbbox->alive : box->alive)) {
+
+ if (usesmppboxid)
+ msg = read_from_box(bbbox->bearerbox_connection, smppbox_status == SMPP_RUNNING && bbbox->alive, &ret);
+ else
+ msg = read_from_box(box->bearerbox_connection, smppbox_status == SMPP_RUNNING && box->alive, &ret);
+
+ /* Connection was broken */
+ if (ret == -1) {
/* tell opensmppbox to die */
/* the client closes the connection, after that die in receiver */
+ if (usesmppboxid)
+ if (conn_eof(bbbox->bearerbox_connection))
+ bbbox->alive = 0;
+ else
+ if (conn_eof(box->bearerbox_connection))
box->alive = 0;
+ continue;
}
+
+ /* timeout*/
+ if (ret == 1) {
continue;
}
+
+ /* have a message, hopefully a good one */
if (msg_type(msg) == admin) {
if (msg->admin.command == cmd_shutdown) {
info(0, "Bearerbox told us to die");
+ if (usesmppboxid)
+ bbbox->alive = 0;
+ else
box->alive = 0;
} else if (msg->admin.command == cmd_restart) {
info(0, "Bearerbox told us to restart");
restart = 1;
+ if (usesmppboxid)
+ bbbox->alive = 0;
+ else
box->alive = 0;
}
}
@@ -1901,7 +2336,11 @@
if (msg_type(msg) == ack) {
uuid_unparse(msg->ack.id, id);
msgid = octstr_create(id);
+ if (!usesmppboxid)
pdu = dict_get(box->msg_acks, msgid);
+ else
+ pdu = dict_get(bbbox->msg_acks, msgid);
+
errcode = SMPP_ESME_RMSGQFUL; /* in case we get ack_failed_tmp */
if (pdu) {
switch (msg->ack.nack) {
@@ -1933,26 +2372,39 @@
debug("opensmppbox", 0, "Unknown ack.nack type: %ld.", msg->ack.nack);
break;
}
+ if (!usesmppboxid) {
send_pdu(box->smpp_connection, box->boxc_id, pdu);
dict_put(box->msg_acks, msgid, NULL); /* also destroys item */
+ } else {
+ Boxc *receiver_box = find_receiver_box_by_msg_id(msgid, msg);
+ if (receiver_box) {
+ send_pdu(receiver_box->smpp_connection, receiver_box->boxc_id, pdu);
+ dict_put(receiver_box->msg_acks, msgid, NULL);
+ }
+ //dlr_remove_by_id(msg);
+ }
}
else {
debug("opensmppbox", 0, "Ack to unknown message: %s.", id);
}
octstr_destroy(msgid);
}
- if (!box->alive) {
+ if (usesmppboxid ? !bbbox->alive : !box->alive) {
msg_destroy(msg);
break;
}
if (msg_type(msg) == sms) {
info(0, "We received an SMS message.");
- if (msg->sms.sms_type == report_mo)
+ msg_dump(msg, 0);
+ uuid_unparse(msg->sms.id, id);
+ msgid = octstr_create(id);
+ if (msg_is_report_mo(msg)) {
dreport = 1;
- else
+ } else {
dreport = 0;
+ }
/* Recode to iso-8859-1 the MO message if possible */
- if (box->mo_recode && msg->sms.coding == DC_UCS2) {
+ if ((usesmppboxid ? bbbox->mo_recode : box->mo_recode) && msg->sms.coding == DC_UCS2) {
int converted = 0;
Octstr *text;
@@ -2006,43 +2458,58 @@
mack->ack.nack = ack_failed;
mack->ack.time = msg->sms.time;
uuid_copy(mack->ack.id, msg->sms.id);
- send_msg(box->bearerbox_connection, box, mack);
+ if (usesmppboxid) {
+ send_msg(bbbox->bearerbox_connection, mack);
+ } else
+ send_msg(box->bearerbox_connection, mack);
msg_destroy(msg);
continue;
}
- /* create ack message to be sent afterwards */
+ /* create ack message to be sent afterwards, or immediately, in case of error*/
mack = msg_create(ack);
mack->ack.nack = ack_success;
mack->ack.time = msg->sms.time;
uuid_copy(mack->ack.id, msg->sms.id);
- msgid = NULL;
- receiver_box = find_receiver_box(box);
+ if (usesmppboxid) {
+ restore_box_id(msg);
+ receiver_box = find_receiver_box(NULL, msg);
+ } else
+ receiver_box = find_receiver_box(box, msg);
+ if (receiver_box != NULL)
pdulist = msg_to_pdu(receiver_box, msg);
if (pdulist != NULL) {
while ((pdu = gwlist_extract_first(pdulist)) != NULL) {
- if (NULL == msgid) {
- /* Put ack in dict. We will send it as soon as we received a deliver_sm_resp */
+ octstr_destroy(msgid);
+ /* Put ack in dict. We will send it as soon as we received a deliver_sm_resp.
+ * Note that sequence number is used for identification. */
msgid = octstr_format("%ld", pdu->u.deliver_sm.sequence_number);
dict_put(receiver_box->deliver_acks, msgid, mack);
- }
- send_pdu(receiver_box->smpp_connection, box->boxc_id, pdu);
+
+ send_pdu(receiver_box->smpp_connection, receiver_box->boxc_id, pdu);
smpp_pdu_destroy(pdu);
}
- if (msgid)
- octstr_destroy(msgid);
- gwlist_destroy(pdulist, NULL);
+ gwlist_destroy(pdulist, smpp_pdu_destroy_item);
}
else {
/* Send NACK to bearerbox, otherwise message remains in store file. */
warning(0, "msg_to_pdu failed, sending negative ack");
mack->ack.nack = ack_failed;
- send_msg(box->bearerbox_connection, box, mack);
+ if (usesmppboxid) {
+ send_msg(bbbox->bearerbox_connection, mack);
+ } else
+ send_msg(box->bearerbox_connection, mack);
+ }
+ if (msgid) {
+ octstr_destroy(msgid); msgid = NULL;
}
}
msg_destroy(msg);
}
+
+ error(0, "opensmppbox: bearerbox_to_smpp: thread terminates");
+ smppbox_status = SMPP_SHUTDOWN;
}
static void run_smppbox(void *arg)
@@ -2057,7 +2524,8 @@
panic(0, "Socket accept failed");
return;
}
- newconn->boxc_id = octstr_duplicate(smppbox_id);
+
+ if (!usesmppboxid) {
newconn->bearerbox_connection = connect_to_bearerbox_real(bearerbox_host, bearerbox_port, bearerbox_port_ssl, NULL /* bb_our_host */);
/* XXX add our_host if required */
if (newconn->bearerbox_connection == NULL) {
@@ -2065,6 +2533,7 @@
boxc_destroy(newconn);
return;
}
+ }
gwlist_append(all_boxes, newconn);
@@ -2083,7 +2552,10 @@
boxc_destroy(newconn);
return;
}
+ if (!usesmppboxid)
bearerbox_to_smpp(newconn);
+
+
gwthread_join(sender);
gwlist_delete_equal(all_boxes, newconn);
boxc_destroy(newconn);
@@ -2163,10 +2635,11 @@
switch (signum) {
case SIGINT:
-
+ case SIGTERM:
if (smppbox_status == SMPP_RUNNING) {
error(0, "SIGINT received, aborting program...");
smppbox_status = SMPP_SHUTDOWN;
+ gwthread_wakeup_all();
}
break;
@@ -2198,6 +2671,7 @@
sigaction(SIGQUIT, &act, NULL);
sigaction(SIGHUP, &act, NULL);
sigaction(SIGPIPE, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
}
@@ -2210,6 +2684,110 @@
{
}
+/*
+ * Populates the corresponding client_by_foobar dictionary hash tables
+ */
+static void init_client_routes(Cfg *cfg)
+{
+ CfgGroup *grp;
+ List *list, *items;
+ Octstr *client_id, *smsc_ids, *shortcuts;
+ int i, j;
+
+ client_id = smsc_ids = shortcuts = NULL;
+ list = items = NULL;
+
+ list = cfg_get_multi_group(cfg, octstr_imm("client-route"));
+
+ /* loop multi-group "client-route" */
+ while (list && (grp = gwlist_extract_first(list)) != NULL) {
+ if ((client_id = cfg_get(grp, octstr_imm("client-id"))) == NULL) {
+ grp_dump(grp);
+ panic(0,"'client-route' group without valid 'client-id' directive!");
+ }
+
+ /*
+ * If smsc-id is given, then any message comming from the specified
+ * smsc-id in the list will be routed to this client.
+ * If shortcode is given, then any message with receiver number
+ * matching those will be routed to this client.
+ * If both are given, then only receiver within shortcode originating
+ * from smsc-id list will be routed to this cleint. So if both are
+ * present then this is a logical AND operation.
+ */
+ smsc_ids = cfg_get(grp, octstr_imm("smsc-id"));
+ shortcuts = cfg_get(grp, octstr_imm("shortcode"));
+
+ /* consider now the 3 possibilities: */
+ if (smsc_ids && !shortcuts) {
+ /* smsc-id only, so all MO traffic */
+ items = octstr_split(smsc_ids, octstr_imm(";"));
+ for (i = 0; i < gwlist_len(items); i++) {
+ Octstr *item = gwlist_get(items, i);
+ octstr_strip_blanks(item);
+
+ debug("opensmppbox",0,"Adding client routing to id <%s> for smsc id <%s>",
+ octstr_get_cstr(client_id), octstr_get_cstr(item));
+
+ if (!dict_put_once(client_by_smsc, item, octstr_duplicate(client_id)))
+ panic(0, "Routing for smsc-id <%s> already exists!",
+ octstr_get_cstr(item));
+ }
+ gwlist_destroy(items, octstr_destroy_item);
+ octstr_destroy(smsc_ids);
+ }
+ else if (!smsc_ids && shortcuts) {
+ /* shortcode only, so these MOs from all smscs */
+ items = octstr_split(shortcuts, octstr_imm(";"));
+ for (i = 0; i < gwlist_len(items); i++) {
+ Octstr *item = gwlist_get(items, i);
+ octstr_strip_blanks(item);
+
+ debug("opensmppbox",0,"Adding client routing to id <%s> for receiver no <%s>",
+ octstr_get_cstr(client_id), octstr_get_cstr(item));
+
+ if (!dict_put_once(client_by_receiver, item, octstr_duplicate(client_id)))
+ panic(0, "Routing for receiver no <%s> already exists!",
+ octstr_get_cstr(item));
+ }
+ gwlist_destroy(items, octstr_destroy_item);
+ octstr_destroy(shortcuts);
+ }
+ else if (smsc_ids && shortcuts) {
+ /* both, so only specified MOs from specified smscs */
+ items = octstr_split(shortcuts, octstr_imm(";"));
+ for (i = 0; i < gwlist_len(items); i++) {
+ List *subitems;
+ Octstr *item = gwlist_get(items, i);
+ octstr_strip_blanks(item);
+ subitems = octstr_split(smsc_ids, octstr_imm(";"));
+ for (j = 0; j < gwlist_len(subitems); j++) {
+ Octstr *subitem = gwlist_get(subitems, j);
+ octstr_strip_blanks(subitem);
+
+ debug("opensmppbox",0,"Adding client routing to id <%s> "
+ "for receiver no <%s> and smsc id <%s>",
+ octstr_get_cstr(client_id), octstr_get_cstr(item),
+ octstr_get_cstr(subitem));
+
+ /* construct the dict key '<shortcode>:<smsc-id>' */
+ octstr_insert(subitem, item, 0);
+ octstr_insert_char(subitem, octstr_len(item), ':');
+ if (!dict_put_once(client_by_smsc_receiver, subitem, octstr_duplicate(client_id)))
+ panic(0, "Routing for receiver:smsc <%s> already exists!",
+ octstr_get_cstr(subitem));
+ }
+ gwlist_destroy(subitems, octstr_destroy_item);
+ }
+ gwlist_destroy(items, octstr_destroy_item);
+ octstr_destroy(shortcuts);
+ }
+ octstr_destroy(client_id);
+ }
+
+ gwlist_destroy(list, NULL);
+}
+
static void init_smppbox(Cfg *cfg)
{
CfgGroup *grp;
@@ -2225,9 +2803,7 @@
lvl = 0;
systemidisboxcid = 0; /* default backward compatible */
enablepam = 0; /* also default false */
-
- /* init dlr storage */
- dlr_init(cfg);
+ usesmppboxid = 0; /* Ditto */
/* initialize low level PDUs */
if (smpp_pdu_init(cfg) == -1)
@@ -2298,6 +2873,7 @@
cfg_get_bool(&systemidisboxcid, grp, octstr_imm("use-systemid-as-smsboxid"));
cfg_get_bool(&enablepam, grp, octstr_imm("enable-pam"));
+ cfg_get_bool(&usesmppboxid, grp, octstr_imm("use-smppboxid"));
pamacl = cfg_get(grp, octstr_imm("pam-acl"));
if (NULL == pamacl) {
pamacl = octstr_create("kannel");
@@ -2318,6 +2894,17 @@
boxid = counter_create();
gw_smpp_enter(cfg);
+ /* the client routing specific inits */
+ client_by_smsc = dict_create(30, (void(*)(void *)) octstr_destroy);
+ client_by_receiver = dict_create(50, (void(*)(void *)) octstr_destroy);
+ client_by_smsc_receiver = dict_create(50, (void(*)(void *)) octstr_destroy);
+
+ init_client_routes(cfg);
+
+ /* DLR storage - both ours and Kannel's */
+ dlr_init(cfg);
+ box_dlr_init(cfg);
+
smppbox_status = SMPP_RUNNING;
}
@@ -2381,6 +2968,18 @@
return 0;
}
+static void smppbox_shutdown(void)
+{
+ octstr_destroy(our_system_id); our_system_id = NULL;
+ octstr_destroy(pamacl); pamacl = NULL;
+ octstr_destroy(smpp_logins); smpp_logins = NULL;
+ octstr_destroy(bearerbox_host); bearerbox_host = NULL;
+ octstr_destroy(smppbox_id); smppbox_id = NULL;
+
+ box_dlr_shutdown();
+ smpp_pdu_shutdown();
+}
+
int main(int argc, char **argv)
{
int cf_index;
@@ -2388,7 +2987,7 @@
gwlib_init();
all_boxes = gwlist_create();
- list_dict = dict_create(1, NULL);
+ list_dict = dict_create(32, msg_list_destroy_item);
cf_index = get_and_set_debugs(argc, argv, check_args);
setup_signal_handlers();
@@ -2414,20 +3013,40 @@
octstr_destroy(version);
init_smppbox(cfg);
-
+ if (usesmppboxid) {
+ bbbox = bbboxc_create();
+ identify_to_bearerbox(bbbox->bearerbox_connection, smppbox_id);
+ gwthread_create(bearerbox_to_smpp, bbbox);
+ }
smppboxc_run((void *)smppbox_port);
/* shutdown dlr storage */
heartbeat_stop(ALL_HEARTBEATS);
+ if (usesmppboxid) {
+ gwthread_join_every(bearerbox_to_smpp);
+ bbboxc_destroy(bbbox);
+ }
+
dlr_shutdown();
+ smppbox_shutdown();
counter_destroy(catenated_sms_counter);
counter_destroy(boxid);
+ dict_destroy(list_dict); list_dict = NULL;;
+ dict_destroy(client_by_smsc);
+ client_by_smsc = NULL;
+ dict_destroy(client_by_receiver);
+ client_by_receiver = NULL;
+ dict_destroy(client_by_smsc_receiver);
+ client_by_smsc_receiver = NULL;
+
+ cfg_destroy(cfg);
+
if (restart_smppbox) {
gwthread_sleep(1.0);
}
- gwlist_destroy(all_boxes, NULL);
+ gwlist_destroy(all_boxes, boxc_destroy_item);
gw_smpp_leave();
gwlib_shutdown();