Patch to configure sleep time when encountering SMPP throttling error

Michael Zervakis <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <[email protected]>
Dear all,

SMPP module has hardcoded 1 second sleep time when receiving a 
throttling error from SMSC. This setting is adequate for low latency 
networks but considerably limits performance when SMPP connection is 
using a high latency network for example 100ms. In this case the sleep 
time should be set at msec and not 1 sec. The attached patch maintains 
the default 1 sec. sleep time and is introducing a new configuration 
directive "throttling-sleep-time" which allows the user to define sleep 
time in msec.

BR,

Michael Zervakis
smsc_smpp.c.patch (text/plain, 8.1 KB)
Index: gw/smsc/smsc_smpp.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_smpp.c,v
retrieving revision 1.123
diff -u -r1.123 smsc_smpp.c
--- gw/smsc/smsc_smpp.c	2 Sep 2009 13:10:50 -0000	1.123
+++ gw/smsc/smsc_smpp.c	14 Mar 2010 18:13:21 -0000
@@ -80,6 +80,8 @@
 #include "bearerbox.h"
 #include "meta_data.h"
 #include "load.h"
+#include <sys/time.h>
+#include <limits.h>
 
 #define SMPP_DEFAULT_CHARSET "UTF-8"
 
@@ -112,7 +114,7 @@
 #define SMPP_MAX_PENDING_SUBMITS    10
 #define SMPP_DEFAULT_VERSION        0x34
 #define SMPP_DEFAULT_PRIORITY       0
-#define SMPP_THROTTLING_SLEEP_TIME  1
+#define SMPP_THROTTLING_SLEEP_TIME  1000
 #define SMPP_DEFAULT_CONNECTION_TIMEOUT  10 * SMPP_ENQUIRE_LINK_INTERVAL
 #define SMPP_DEFAULT_WAITACK        60
 #define SMPP_DEFAULT_SHUTDOWN_TIMEOUT 30
@@ -160,7 +162,8 @@
     int version;
     int priority;       /* set default priority for messages */
     int validityperiod;
-    time_t throttling_err_time;
+    long throttling_sleep_time;
+    struct timeval throttling_err_time;
     int smpp_msg_id_type;  /* msg id in C string, hex or decimal */
     int autodetect_addr;
     Octstr *alt_charset;
@@ -221,7 +224,7 @@
                          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)
+                         long wait_ack, int wait_ack_action, int throttling_sleep_time)
 {
     SMPP *smpp;
 
@@ -254,7 +257,9 @@
     smpp->priority = priority;
     smpp->validityperiod = validity;
     smpp->conn = conn;
-    smpp->throttling_err_time = 0;
+    smpp->throttling_sleep_time = throttling_sleep_time * 1000;
+    smpp->throttling_err_time.tv_sec = 0;
+    smpp->throttling_err_time.tv_usec = 0;
     smpp->smpp_msg_id_type = smpp_msg_id_type;
     smpp->autodetect_addr = autodetect_addr;
     smpp->alt_charset = octstr_duplicate(alt_charset);
@@ -1606,10 +1611,12 @@
                  * check to see if we got a "throttling error", in which case we'll just
                  * sleep for a while
                  */
-                if (pdu->u.submit_sm_resp.command_status == SMPP_ESME_RTHROTTLED)
-                    time(&(smpp->throttling_err_time));
-                else
-                    smpp->throttling_err_time = 0;
+                if (pdu->u.submit_sm_resp.command_status == SMPP_ESME_RTHROTTLED) {
+                    gettimeofday(&(smpp->throttling_err_time), NULL);
+                } else {
+                    smpp->throttling_err_time.tv_sec = 0;
+                    smpp->throttling_err_time.tv_usec = 0;
+                }
 
                 bb_smscconn_send_failed(smpp->conn, msg, reason, octstr_format("0x%08lx/%s", pdu->u.submit_sm_resp.command_status,
                                         smpp_error_to_string(pdu->u.submit_sm_resp.command_status)));
@@ -1755,10 +1762,12 @@
                  * check to see if we got a "throttling error", in which case we'll just
                  * sleep for a while
                  */
-                if (cmd_stat == SMPP_ESME_RTHROTTLED)
-                    time(&(smpp->throttling_err_time));
-                else
-                    smpp->throttling_err_time = 0;
+                if (cmd_stat == SMPP_ESME_RTHROTTLED) {
+                    gettimeofday(&(smpp->throttling_err_time), NULL);
+                } else {
+                    smpp->throttling_err_time.tv_sec = 0;
+                    smpp->throttling_err_time.tv_usec = 0;
+                }
 
                 reason = smpp_status_to_smscconn_failure_reason(cmd_stat);
                 bb_smscconn_send_failed(smpp->conn, msg, reason,
@@ -1884,6 +1893,7 @@
     SMPP_PDU *pdu;
     double timeout;
     time_t last_cleanup, last_enquire_sent, last_response, now;
+    struct timeval eval_time;
 
     io_arg = arg;
     smpp = io_arg->smpp;
@@ -1971,8 +1981,8 @@
                 if (!IS_ACTIVE && timeout <= 0)
                     timeout = smpp->enquire_link_interval;
                 if (transmitter && gw_prioqueue_len(smpp->msgs_to_send) > 0 &&
-                    smpp->throttling_err_time > 0 && pending_submits < smpp->max_pending_submits) {
-                    time_t tr_timeout = smpp->throttling_err_time + SMPP_THROTTLING_SLEEP_TIME - now;
+                    smpp->throttling_err_time.tv_sec > 0 && pending_submits < smpp->max_pending_submits) {
+                    time_t tr_timeout = smpp->throttling_err_time.tv_sec + (int) (smpp->throttling_sleep_time / 1000000 + 0.5) - now;
                     timeout = timeout > tr_timeout ? tr_timeout : timeout;
                 } else if (transmitter && gw_prioqueue_len(smpp->msgs_to_send) > 0 && smpp->conn->throughput > 0 &&
                            smpp->max_pending_submits > pending_submits) {
@@ -1996,10 +2006,24 @@
             }
             
             /* make sure we send */
-            if (transmitter && difftime(time(NULL), smpp->throttling_err_time) > SMPP_THROTTLING_SLEEP_TIME) {
-                smpp->throttling_err_time = 0;
-                if (send_messages(smpp, conn, &pending_submits) == -1)
-                    break;
+            if (transmitter) {
+                if (smpp->throttling_err_time.tv_sec == 0) {
+                    if (send_messages(smpp, conn, &pending_submits) == -1)
+                        break;
+                } else {
+                    gettimeofday(&eval_time, NULL);
+                    if (eval_time.tv_sec >= smpp->throttling_err_time.tv_sec && eval_time.tv_sec - smpp->throttling_err_time.tv_sec < (unsigned long)(ULONG_MAX / 1000000 - 0.5)) {
+                        if ((eval_time.tv_sec - smpp->throttling_err_time.tv_sec) * 1000000 + eval_time.tv_usec - smpp->throttling_err_time.tv_usec > smpp->throttling_sleep_time) {
+                             smpp->throttling_err_time.tv_sec = 0;
+                             smpp->throttling_err_time.tv_usec = 0;
+                             if (send_messages(smpp, conn, &pending_submits) == -1)
+                                 break;
+                        }
+                    } else {
+                        if (send_messages(smpp, conn, &pending_submits) == -1)
+                            break;
+                    }
+                }
             }
             
             /* unbind
@@ -2190,6 +2214,7 @@
     Octstr *alt_charset;
     Octstr *alt_addr_charset;
     long connection_timeout, wait_ack, wait_ack_action;
+    long throttling_sleep_time;
 
     my_number = alt_addr_charset = alt_charset = NULL;
     transceiver_mode = 0;
@@ -2229,6 +2254,9 @@
     if (cfg_get_integer(&max_pending_submits, grp,
                         octstr_imm("max-pending-submits")) == -1)
         max_pending_submits = SMPP_MAX_PENDING_SUBMITS;
+    if (cfg_get_integer(&throttling_sleep_time, grp,
+                        octstr_imm("throttling-sleep-time")) == -1)
+        throttling_sleep_time = SMPP_THROTTLING_SLEEP_TIME;
 
     /* Check that config is OK */
     ok = 1;
@@ -2328,7 +2356,7 @@
                        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);
+                       service_type, connection_timeout, wait_ack, wait_ack_action, throttling_sleep_time);
 
     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"));
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.142
diff -u -r1.142 cfg.def
--- gwlib/cfg.def	6 Dec 2009 17:24:14 -0000	1.142
+++ gwlib/cfg.def	14 Mar 2010 18:13:21 -0000
@@ -366,6 +366,7 @@
     OCTSTR(source-addr-autodetect)
     OCTSTR(enquire-link-interval)
     OCTSTR(max-pending-submits)
+    OCTSTR(throttling-sleep-time)
     OCTSTR(reconnect-delay)
     OCTSTR(transceiver-mode)
     OCTSTR(interface-version)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.