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);
     }
