[PATCH] Smppbox acks
"Rene Kluwen" <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Message-ID | <[email protected]> |
Here is a more advanced patch. Messages to bearerbox are acked, once the deliver_sm_resp pdu is in. Also submit_sm pdu's get their responses, after bearerbox has acked the message. And if not, a failure notice is returned. Before, message acks were given right away, without checking for failure or rejection. Tomasz: Would it be possible for you to test this patch in your environment? Victor: Would you review for stupidities? Comments are welcome. == Rene
acks_patch.patch
(application/octet-stream, 5 KB)
Index: gw/smppbox.c
===================================================================
--- gw/smppbox.c (revision 35)
+++ gw/smppbox.c (working copy)
@@ -139,6 +139,8 @@
Octstr *boxc_id; /* identifies the connected smppbox instance */
Octstr *account;
Octstr *route_to_smsc;
+ Dict *msg_acks;
+ Dict *deliver_acks;
/* used to mark connection usable or still waiting for ident. msg */
volatile int routable;
@@ -157,6 +159,12 @@
} Boxc;
+
+void smpp_pdu_destroy_item(void *pdu)
+{
+ smpp_pdu_destroy(pdu);
+}
+
/* check if login exists in database */
int check_login(Boxc *boxc, Octstr *system_id, Octstr *password, Octstr *system_type, smpp_login login_type) {
int box;
@@ -1235,11 +1243,12 @@
static void handle_pdu(Connection *conn, Boxc *box, SMPP_PDU *pdu) {
SMPP_PDU *resp = NULL;
- Msg *msg, *msg2;
+ Msg *msg, *msg2, *mack;
long reason;
Octstr *msgid = NULL;
int msg_to_send = 1;
List *parts_list = NULL;
+ char id[UUID_STR_LEN + 1];
dump_pdu("Got PDU:", box->boxc_id, pdu);
switch (pdu->type) {
@@ -1339,6 +1348,10 @@
dlr_add(box->boxc_id, msgid, msg2);
octstr_destroy(msgid);
}
+ uuid_unparse(msg2->sms.id, id);
+ msgid = octstr_create(id);
+ dict_put(box->msg_acks, msgid, resp);
+ resp = NULL;
send_msg(box->bearerbox_connection, box, msg2);
if (parts_list) {
/* destroy values */
@@ -1373,6 +1386,10 @@
dlr_add(box->boxc_id, msgid, msg2);
octstr_destroy(msgid);
}
+ uuid_unparse(msg2->sms.id, id);
+ msgid = octstr_create(id);
+ dict_put(box->msg_acks, msgid, resp);
+ resp = NULL;
send_msg(box->bearerbox_connection, box, msg2);
if (parts_list) {
/* destroy values */
@@ -1382,7 +1399,18 @@
}
break;
case deliver_sm_resp:
- /* thank you */
+ msgid = octstr_format("%ld", pdu->u.deliver_sm_resp.sequence_number);
+ mack = dict_get(box->deliver_acks, msgid);
+ if (mack) {
+ msg = msg_duplicate(mack);
+ /* TODO: ack_failed_tmp */
+ 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);
+ }
+ octstr_destroy(msgid);
break;
case unbind_resp:
box->logged_in = 0;
@@ -1433,6 +1461,8 @@
boxc->alt_charset = NULL; /* todo: get from config */
boxc->version = 0x33; /* default value, set upon receiving a bind */
boxc->route_to_smsc = route_to_smsc ? octstr_duplicate(route_to_smsc) : NULL;
+ boxc->msg_acks = dict_create(10, smpp_pdu_destroy_item);
+ boxc->deliver_acks = dict_create(10, msg_destroy_item);
boxc->service_type = NULL;
@@ -1471,6 +1501,8 @@
}
if (boxc->client_ip)
octstr_destroy(boxc->client_ip);
+ dict_destroy(boxc->msg_acks);
+ dict_destroy(boxc->deliver_acks);
gw_free(boxc);
}
@@ -1570,6 +1602,8 @@
List *pdulist;
int dreport;
Connection *receiver_connection;
+ char id[UUID_STR_LEN + 1];
+ Octstr *msgid;
while (smppbox_status == SMPP_RUNNING && box->alive) {
@@ -1599,7 +1633,40 @@
continue;
}
if (msg_type(msg) == ack) {
- // todo: what do we do here?
+ uuid_unparse(msg->ack.id, id);
+ msgid = octstr_create(id);
+ pdu = dict_get(box->msg_acks, msgid);
+ if (pdu) {
+ switch (msg->ack.nack) {
+ case ack_buffered:
+ case ack_success:
+ /* we can send the submit_sm_resp as-is */
+ break;
+ case ack_failed:
+ case ack_failed_tmp:
+ switch (pdu->type) {
+ case submit_sm_resp:
+ octstr_destroy(pdu->u.submit_sm_resp.message_id);
+ pdu->u.submit_sm_resp.message_id = NULL;
+ pdu->u.submit_sm_resp.command_status = SMPP_ESME_RSUBMITFAIL;
+ break;
+ case data_sm_resp:
+ octstr_destroy(pdu->u.data_sm_resp.message_id);
+ pdu->u.data_sm_resp.message_id = NULL;
+ pdu->u.data_sm_resp.command_status = SMPP_ESME_RSUBMITFAIL;
+ break;
+ }
+ default:
+ debug("smppbox", 0, "Unknown ack.nack type: %i.", msg->ack.nack);
+ break;
+ }
+ send_pdu(box->smpp_connection, box->boxc_id, pdu);
+ dict_put(box->msg_acks, msgid, NULL); /* also destroys item */
+ }
+ else {
+ debug("smppbox", 0, "Ack to unknown message: %s.", id);
+ }
+ octstr_destroy(msgid);
}
if (!box->alive) {
msg_destroy(msg);
@@ -1677,16 +1744,23 @@
mack->ack.time = msg->sms.time;
uuid_copy(mack->ack.id, msg->sms.id);
+ msgid = NULL;
pdulist = msg_to_pdu(box, msg);
if (pdulist != NULL) {
receiver_connection = find_receiver_connection(box);
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 */
+ msgid = octstr_format("%ld", pdu->u.deliver_sm.sequence_number);
+ dict_put(box->deliver_acks, msgid, mack);
+ }
send_pdu(receiver_connection, box->boxc_id, pdu);
smpp_pdu_destroy(pdu);
}
+ if (msgid)
+ octstr_destroy(msgid);
gwlist_destroy(pdulist, NULL);
}
- send_msg(box->bearerbox_connection, box, mack);
}
msg_destroy(msg);
}