Index: gwlib/cfg.def
===================================================================
--- gwlib/cfg.def	(revision 4981)
+++ gwlib/cfg.def	(working copy)
@@ -422,6 +422,8 @@
     OCTSTR(generic-status-sent)
     OCTSTR(generic-status-error)
     OCTSTR(generic-foreign-id-regex)
+    OCTSTR(dlr-retry-count)
+    OCTSTR(dlr-retry-interval)
 )
 
 
Index: doc/userguide/userguide.xml
===================================================================
--- doc/userguide/userguide.xml	(revision 4981)
+++ doc/userguide/userguide.xml	(working copy)
@@ -3576,6 +3576,20 @@
        Defaults to 3.
      </entry></row>
 
+   <row><entry><literal>dlr-retry-count</literal></entry>
+     <entry><literal>number</literal></entry>
+     <entry valign="bottom">
+       Number of attempts to process a delivery report if not found in the delivery
+       reports store. Defaults to 0 times (disabled).
+     </entry></row>
+
+   <row><entry><literal>dlr-retry-interval</literal></entry>
+     <entry><literal>number (seconds)</literal></entry>
+     <entry valign="bottom">
+       This timer specifies the interval time between delivery reports retries.
+       Defaults to 60 seconds.
+     </entry></row>
+
    </tbody></tgroup></informaltable>
 
 </sect2>
Index: gw/smsc/smsc_smpp.c
===================================================================
--- gw/smsc/smsc_smpp.c	(revision 4981)
+++ gw/smsc/smsc_smpp.c	(working copy)
@@ -172,6 +172,10 @@
     int esm_class;
     Load *load;
     SMSCConn *conn;
+    long dlr_retry; /* id of the thread responsible for dlr retries */
+    List *dlr_to_retry; /* list containing dlr waiting for a retry */
+    long dlr_retry_count;
+    long dlr_retry_interval;
 } SMPP;
 
 
@@ -180,6 +184,14 @@
     Msg *msg;
 };
 
+struct dlr_retry {
+    time_t retry_time;
+    long dlr_retry_count;
+    int dlrstat;
+    Octstr *msgid;
+    Octstr *destination_address;
+    Octstr *msgdata;
+};
 
 /*
  * create smpp_msg struct
@@ -211,6 +223,17 @@
     gw_free(msg);
 }
 
+static inline void dlr_retry_destroy(void *arg)
+{
+    struct dlr_retry *dlr;
+    dlr = arg;
+    if (dlr == NULL)
+        return;
+    octstr_destroy(dlr->destination_address);
+    octstr_destroy(dlr->msgdata);
+    octstr_destroy(dlr->msgid);
+    gw_free(dlr);
+}
 
 static SMPP *smpp_create(SMSCConn *conn, Octstr *host, int transmit_port,
                          int receive_port, Octstr *system_type,
@@ -223,7 +246,8 @@
                          Octstr *my_number, int smpp_msg_id_type,
                          int autodetect_addr, Octstr *alt_charset, Octstr *alt_addr_charset,
                          Octstr *service_type, long connection_timeout,
-                         long wait_ack, int wait_ack_action, int esm_class)
+                         long wait_ack, int wait_ack_action, int esm_class,
+                         long dlr_retry_count, long dlr_retry_interval)
 {
     SMPP *smpp;
 
@@ -271,6 +295,10 @@
     smpp->load = load_create_real(0);
     load_add_interval(smpp->load, 1);
     smpp->esm_class = esm_class;
+    smpp->dlr_retry = -1;
+    smpp->dlr_to_retry = gwlist_create();
+    smpp->dlr_retry_count = dlr_retry_count;
+    smpp->dlr_retry_interval = dlr_retry_interval;
 
     return smpp;
 }
@@ -282,6 +310,7 @@
         gw_prioqueue_destroy(smpp->msgs_to_send, msg_destroy_item);
         dict_destroy(smpp->sent_msgs);
         gwlist_destroy(smpp->received_msgs, msg_destroy_item);
+        gwlist_destroy(smpp->dlr_to_retry, dlr_retry_destroy);
         counter_destroy(smpp->message_id_counter);
         octstr_destroy(smpp->host);
         octstr_destroy(smpp->username);
@@ -1475,10 +1504,28 @@
             meta_data_set_value(dlrmsg->sms.meta_data, "smpp", octstr_imm("dlr_err"), network_err, 1);
         }
     } else {
-        error(0,"SMPP[%s]: got DLR but could not find message or was not interested "
-                "in it id<%s> dst<%s>, type<%d>",
-                octstr_get_cstr(smpp->conn->id), octstr_get_cstr(tmp),
-                octstr_get_cstr(destination_addr), dlrstat);
+        if ( smpp->dlr_retry_count > 0 ) {
+            // add the DLR into the retry queue
+            struct dlr_retry *retry = gw_malloc(sizeof(struct dlr_retry));
+            retry->destination_address = octstr_duplicate(destination_addr);
+            retry->dlr_retry_count = 0;
+            retry->dlrstat = dlrstat;
+            retry->msgid = octstr_duplicate(tmp);
+            retry->retry_time = time(NULL) + smpp->dlr_retry_interval;
+
+            retry->msgdata = octstr_duplicate(respstr);
+            gwlist_append(smpp->dlr_to_retry, retry);
+
+            debug("bb.sms.smpp", 0,"SMPP[%s]: Add DLR into the retry queue because it was not found in the DLR storage "
+                    "id<%s> dst<%s>, type<%d>",
+                    octstr_get_cstr(smpp->conn->id), octstr_get_cstr(tmp),
+                    octstr_get_cstr(destination_addr), dlrstat);
+        } else {
+            error(0,"SMPP[%s]: got DLR but could not find message or was not interested "
+                    "in it id<%s> dst<%s>, type<%d>",
+                    octstr_get_cstr(smpp->conn->id), octstr_get_cstr(tmp),
+                    octstr_get_cstr(destination_addr), dlrstat);
+        }
     }
     octstr_destroy(tmp);
     octstr_destroy(network_err);
@@ -1868,8 +1915,76 @@
     return io_arg;
 }
 
+/*
+ * go over all DLRs stored in the dlr_retry list. If some of them
+ * have reached their retry time they are processed again
+ * when a DLR has reached its maximum number of retries it is removed
+ * from the list
+ */
+static void do_dlr_retry_cleanup (SMPP *smpp)
+{
+    long i;
+    Msg *dlrmsg = NULL;
+    for (i = 0; i < gwlist_len(smpp->dlr_to_retry); i++) {
+        struct dlr_retry *dlr;
+        dlr = gwlist_get(smpp->dlr_to_retry, i);
+        if (dlr != NULL ) {
+            if ( difftime(time(NULL),dlr->retry_time) >= 0 ) {
+                debug("bb.sms.smpp", 0,"SMPP[%s]: Attempt <%ld> of <%ld> to process DLR id<%s> dst<%s>, type<%d>",
+                        octstr_get_cstr(smpp->conn->id),
+                        (dlr->dlr_retry_count+1), smpp->dlr_retry_count,
+                        octstr_get_cstr(dlr->msgid),
+                        octstr_get_cstr(dlr->destination_address), dlr->dlrstat);
+                dlrmsg = dlr_find(smpp->conn->id,
+                    dlr->msgid, /* smsc message id */
+                    dlr->destination_address, /* destination */
+                    dlr->dlrstat, 1);
+                if (dlrmsg != NULL) {
+                    debug("bb.sms.smpp", 0,"SMPP[%s]: Found matching DLR id<%s> dst<%s>, type<%d>",
+                            octstr_get_cstr(smpp->conn->id), octstr_get_cstr(dlr->msgid),
+                            octstr_get_cstr(dlr->destination_address), dlr->dlrstat);
+                    dlrmsg->sms.msgdata = octstr_duplicate(dlr->msgdata);
+                    dlrmsg->sms.sms_type = report_mo;
+                    dlrmsg->sms.account = octstr_duplicate(smpp->username);
+                    bb_smscconn_receive(smpp->conn, dlrmsg);
+                    gwlist_delete(smpp->dlr_to_retry,i,1);
+                } else {
+                    dlr->dlr_retry_count++;
+                    if (dlr->dlr_retry_count >= smpp->dlr_retry_count) {
+                        gwlist_delete(smpp->dlr_to_retry,i,1);
+                        error(0,"SMPP[%s]: Number of retry excedeed for DLR "
+                                "id<%s> dst<%s>, type<%d> discarding it",
+                                octstr_get_cstr(smpp->conn->id), octstr_get_cstr(dlr->msgid),
+                                octstr_get_cstr(dlr->destination_address), dlr->dlrstat);
+                    } else {
+                        dlr->retry_time = time(NULL) + smpp->dlr_retry_interval;
+                        debug("bb.sms.smpp", 0,"SMPP[%s]: DLR not yet found re-queueing it id<%s> dst<%s>, type<%d>",
+                                octstr_get_cstr(smpp->conn->id), octstr_get_cstr(dlr->msgid),
+                                octstr_get_cstr(dlr->destination_address), dlr->dlrstat);
+                    }
+                }
+           }
+        }
+    }
+}
 
 /*
+ * execute in a loop do_dlr_retry_cleanup and wait 1sec till the smpp conn is
+ * not quitting
+ */
+static void dlr_retry_thread(void *arg)
+{
+    SMPP *smpp;
+    smpp = arg;
+    /* Make sure we log into our own log-file if defined */
+    log_thread_to(smpp->conn->log_idx);
+    while (!smpp->quitting) {
+        do_dlr_retry_cleanup(smpp);
+        gwthread_sleep(1.0);
+    }
+}
+
+/*
  * sent queue cleanup.
  * @return 1 if io_thread should reconnect; 0 if not
  */
@@ -2060,7 +2175,7 @@
                     break; /* reconnect */
                 time(&last_cleanup);
             }
-            
+
             /* make sure we send */
             if (transmitter && difftime(time(NULL), smpp->throttling_err_time) > SMPP_THROTTLING_SLEEP_TIME) {
                 smpp->throttling_err_time = 0;
@@ -2257,6 +2372,8 @@
     Octstr *alt_addr_charset;
     long connection_timeout, wait_ack, wait_ack_action;
     long esm_class;
+    long dlr_retry_count;
+    long dlr_retry_interval;
 
     my_number = alt_addr_charset = alt_charset = NULL;
     transceiver_mode = 0;
@@ -2401,13 +2518,26 @@
         esm_class = ESM_CLASS_SUBMIT_STORE_AND_FORWARD_MODE;
     }
 
+    /* check for dlr retry count */
+    if (cfg_get_integer(&dlr_retry_count, grp, octstr_imm("dlr-retry-count")) == -1)
+        dlr_retry_count = 0;
+    else if (dlr_retry_count < 0)
+        panic(0, "SMPP: Invalid value for dlr retry count (allowed value >= 0).");
+
+    /* check for dlr retry delay */
+    if (cfg_get_integer(&dlr_retry_interval, grp, octstr_imm("dlr-retry-interval")) == -1)
+        dlr_retry_interval = 60;
+    else if (dlr_retry_interval < 1)
+        panic(0, "SMPP: Invalid value for dlr retry interval (allowed value >= 1).");
+
     smpp = smpp_create(conn, host, port, receive_port, system_type,
                        username, password, address_range,
                        source_addr_ton, source_addr_npi, dest_addr_ton,
                        dest_addr_npi, enquire_link_interval,
                        max_pending_submits, version, priority, validity, my_number,
                        smpp_msg_id_type, autodetect_addr, alt_charset, alt_addr_charset,
-                       service_type, connection_timeout, wait_ack, wait_ack_action, esm_class);
+                       service_type, connection_timeout, wait_ack, wait_ack_action, esm_class,
+                       dlr_retry_count, dlr_retry_interval);
 
     cfg_get_integer(&smpp->bind_addr_ton, grp, octstr_imm("bind-addr-ton"));
     cfg_get_integer(&smpp->bind_addr_npi, grp, octstr_imm("bind-addr-npi"));
@@ -2455,6 +2585,9 @@
     if (receive_port != 0)
         smpp->receiver = gwthread_create(io_thread, io_arg_create(smpp, 0));
 
+    if (smpp->dlr_retry_count > 0)
+        smpp->dlr_retry = gwthread_create(dlr_retry_thread,smpp);
+
     if ((port != 0 && smpp->transmitter == -1) ||
         (receive_port != 0 && smpp->receiver == -1)) {
         error(0, "SMPP[%s]: Couldn't start I/O threads.",
@@ -2468,6 +2601,10 @@
             gwthread_wakeup(smpp->receiver);
             gwthread_join(smpp->receiver);
         }
+        if (smpp->dlr_retry != -1) {
+            gwthread_wakeup(smpp->dlr_retry);
+            gwthread_join(smpp->dlr_retry);
+        }
         smpp_destroy(conn->data);
         conn->data = NULL;
         return -1;
