Index: gw/smsc/smsc_smpp.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_smpp.c,v
retrieving revision 1.94
diff -u -r1.94 smsc_smpp.c
--- gw/smsc/smsc_smpp.c	1 Jun 2006 21:39:19 -0000	1.94
+++ gw/smsc/smsc_smpp.c	6 Jun 2006 21:43:07 -0000
@@ -157,6 +157,8 @@
     int priority;       /* set default priority for messages */    
     int validityperiod;    
     time_t throttling_err_time;
+    time_t last_msg_time;  /*when the last message was sent for this thread*/
+    int    msg_count;      /*message count for this thread*/
     int smpp_msg_id_type;  /* msg id in C string, hex or decimal */
     int autodetect_addr;
     Octstr *alt_charset;
@@ -1014,6 +1016,34 @@
             smpp_pdu_destroy(pdu);
             octstr_destroy(os);
             ++(*pending_submits);
+	    				/*______________________________________
+					  This section manages the SMSC
+					  connection limits. Two limits are
+					  enforced here. The first is an idle
+					  time limit. This portion of code
+					  merely performs a timestamp. The
+					  check will be done by the code that
+					  calls this function. If no timeout
+					  was specified, no timestamp will be
+					  performed. A NULL value for the
+					  current time inicates that no timeout
+					  was specified.
+
+					  The second limitation is on the
+					  number of messages that can be sent
+					  during a connection session. For this
+					  limitation, the code below will
+					  perform a "count-down". The initial
+					  value to count down from is provided
+					  by the caller of this function. If
+					  that value is 0, no count down will
+					  be performed. The message count has
+					  been exceeded if the count gets to
+					  "1".
+	    				______________________________________*/
+			smpp->last_msg_time = (smpp->last_msg_time)?time(NULL):(time_t)0;
+			smpp->msg_count -= (smpp->msg_count)? 1:0;
+			if(smpp->msg_count == 1) break;
             /*
              * obey throughput speed limit, if any.
              */
@@ -1265,9 +1295,9 @@
             tmp = octstr_duplicate(msgid);
         } else {
             if (smpp->smpp_msg_id_type & 0x02) {
-                tmp = octstr_format("%lu", strtoll(octstr_get_cstr(msgid), NULL, 16));
+                tmp = octstr_format("%ld", strtol(octstr_get_cstr(msgid), NULL, 16));
             } else {
-                tmp = octstr_format("%lu", strtoll(octstr_get_cstr(msgid), NULL, 10));
+                tmp = octstr_format("%ld", strtol(octstr_get_cstr(msgid), NULL, 10));
             }
         }
 
@@ -1481,10 +1511,10 @@
                     tmp = octstr_duplicate(pdu->u.submit_sm_resp.message_id);
                 } else {
                     if (smpp->smpp_msg_id_type & 0x01) {
-                        tmp = octstr_format("%lu", strtoll(  /* hex */
+                        tmp = octstr_format("%ld", strtol(  /* hex */
                             octstr_get_cstr(pdu->u.submit_sm_resp.message_id), NULL, 16));
                     } else {
-                        tmp = octstr_format("%lu", strtoll(  /* decimal */
+                        tmp = octstr_format("%ld", strtol(  /* decimal */
                             octstr_get_cstr(pdu->u.submit_sm_resp.message_id), NULL, 10));
                     }
                 }
@@ -1723,6 +1753,26 @@
     struct io_arg *io_arg;
     int transmitter;
     Connection *conn;
+    					/*______________________________________
+					  This variable is used for 2 purposes.
+					  Initially, it is the return value
+					  obtained from the "read_pdu()" 
+					  function. A value of "1" indicates a
+					  successful read, and causes the read
+					  loop to continue. A value of "0" is
+					  the normal loop exit condition. A
+					  value of "-1" is an error loop exit
+					  condition.
+
+					  The second use for this variable is
+					  to specify that a message timeout or
+					  message count limit has been
+					  exceeded. This will be the case if
+					  (ret == 1).  This will be the 
+					  meaning of the variable as it is
+					  evaluated OUTSIDE of the 
+					  "read_pdu()" loop.
+    					______________________________________*/
     int ret;
     long last_enquire_sent;
     long pending_submits;
@@ -1730,9 +1780,31 @@
     SMPP_PDU *pdu;
     double timeout;
     time_t last_response, last_cleanup;
+    int max_msg_count;
+    int reconnect;
+    time_t max_msg_time;
 
     io_arg = arg;
     smpp = io_arg->smpp;
+    					/*______________________________________
+					  These lines retrive the SMSC
+					  connection limits that were packaged
+					  up by the caller. For a description
+					  of the use of these, see the
+					  send_messages() function.
+
+					  The values originate in a
+					  configuration file. The function that
+					  retrieves this information from the
+					  configuration file is not easily
+					  called from this context. Thus, the
+					  values come via the caller of this
+					  function and are carried in the smpp
+					  structure.
+    					______________________________________*/
+    max_msg_time = smpp->last_msg_time;
+    max_msg_count = smpp->msg_count;
+
     transmitter = io_arg->transmitter;
     gw_free(io_arg);
 
@@ -1752,7 +1824,20 @@
         pending_submits = -1;
         len = 0;
         smpp->throttling_err_time = 0;
+
+			/*______________________________________
+			These lines initialize the SMSC
+			limit management variables. The idea
+			is to reset these each time a
+			connection is made.
+			______________________________________*/
+		if(max_msg_count) smpp->msg_count = max_msg_count + 1;
+		smpp->last_msg_time = (max_msg_time)?time(NULL):(time_t)0;
+		reconnect = 0;
+
+
         for (;conn != NULL;) {
+
             timeout = last_enquire_sent + smpp->enquire_link_interval
                         - date_universal_now();
 
@@ -1763,7 +1848,7 @@
              * Read so long as unbind_resp received or timeout passed. Otherwise we have
              * double delivered messages.
              */
-            if (smpp->quitting) {
+            if (smpp->quitting || reconnect) {
                 send_unbind(smpp, conn);
                 last_response = time(NULL);
                 while(conn_wait(conn, 1.00) != -1 &&
@@ -1783,6 +1868,12 @@
 
             send_enquire_link(smpp, conn, &last_enquire_sent);
 
+		    			/*______________________________________
+					  To see a description of the use of
+					  the "ret" variable, look at the
+					  variable's definition at the start of
+					  this function.
+		    			______________________________________*/
             while ((ret = read_pdu(smpp, conn, &len, &pdu)) == 1) {
                 last_response = time(NULL);
                 /* Deal with the PDU we just got */
@@ -1807,8 +1898,30 @@
                 if (transmitter && difftime(time(NULL), smpp->throttling_err_time) > SMPP_THROTTLING_SLEEP_TIME) {
                     smpp->throttling_err_time = 0;
                     send_messages(smpp, conn, &pending_submits);
-                }
-            }
+				}
+		    			/*______________________________________
+					  This test breaks the connection with
+					  the server if the message count was
+					  exceeded.  
+		    			______________________________________*/
+				if(smpp->msg_count == 1) {
+				    debug("bb.smpp",0, "SMPP %s reached max submits during read_pdu. Reconnecting momentarily.", octstr_get_cstr(smpp->conn->id));
+				    ret = 1;
+				    reconnect = 1;
+				    break;
+				}
+		    			/*______________________________________
+					  This test breaks the connection with
+					  the server if the idle time was
+					  exceeded.  
+		    			______________________________________*/
+				if ( max_msg_time && (max_msg_time < (time(NULL) - smpp->last_msg_time)) ) {
+				    debug("bb.smpp",0, "SMPP %s reached max idle time during read_pdu. Reconnecting momentarily.", octstr_get_cstr(smpp->conn->id));
+				    ret = 1;
+				    reconnect = 1;
+				    break;
+				}
+            }				/*while(read_pdu)*/
 
             if (ret == -1) {
                 error(0, "SMPP[%s]: I/O error or other error. Re-connecting.",
@@ -1824,7 +1937,6 @@
                 break;
             }
 
-
             /* cleanup sent queue */
             if (transmitter && difftime(time(NULL), last_cleanup) > smpp->wait_ack) {
                 if (do_queue_cleanup(smpp, &pending_submits, smpp->wait_ack_action))
@@ -1835,8 +1947,29 @@
             if (transmitter && difftime(time(NULL), smpp->throttling_err_time) > SMPP_THROTTLING_SLEEP_TIME) {
                 smpp->throttling_err_time = 0;
                 send_messages(smpp, conn, &pending_submits);
-            }
-        }
+			}
+		    			/*______________________________________
+					  This test breaks the connection with
+					  the server if the message count was
+					  exceeded.  
+		    			______________________________________*/
+			if(smpp->msg_count == 1) {
+				debug("bb.smpp",0, "SMPP %s reached max submitts. Reconnecting momentarily.", octstr_get_cstr(smpp->conn->id));
+				ret = 1;
+		    	reconnect = 1;
+			}
+		    			/*______________________________________
+					  This test breaks the connection with
+					  the server if the idle time was
+					  exceeded.  
+		    			______________________________________*/
+			if ( max_msg_time && (max_msg_time < (time(NULL) - smpp->last_msg_time)) ) {
+				debug("bb.smpp",0, "SMPP %s reached max idle time. Reconnecting momentarily.", octstr_get_cstr(smpp->conn->id));
+				ret = 1;
+		    	reconnect = 1;
+			}
+		
+        }				/*for ... SMS I/O */
 
         if (conn != NULL) {
             conn_destroy(conn);
@@ -1877,9 +2010,21 @@
          * Reconnect if that was a connection problem.
          */
         if (!smpp->quitting) {
-            error(0, "SMPP[%s]: Couldn't connect to SMS center (retrying in %ld seconds).",
-                  octstr_get_cstr(smpp->conn->id), smpp->conn->reconnect_delay);
-            gwthread_sleep(smpp->conn->reconnect_delay);
+	    					
+		    			/*______________________________________
+					  This section inserts a delay in the 
+					  event that connection to the SMS
+					  server was a problem. Otherwise, no
+					  delay is imposed on the reconnect.
+
+					  The default for the delay imposed
+					  here is 10.0 seconds.
+		    			______________________________________*/
+	    	if(ret != 1) {
+				error(0, "SMPP[%s]: Couldn't connect to SMS center (retrying in %ld seconds).",
+				    octstr_get_cstr(smpp->conn->id), smpp->conn->reconnect_delay);
+				gwthread_sleep(smpp->conn->reconnect_delay);
+			}
         }
     }
     mutex_lock(smpp->conn->flow_mutex);
@@ -1983,6 +2128,28 @@
     Octstr *alt_charset;
     Octstr *alt_addr_charset;
     long connection_timeout, wait_ack, wait_ack_action;
+    long max_msg_count;
+    long max_msg_time;
+
+    					/*______________________________________
+					  These lines retrieve the SMSC
+					  connection limits from the config
+					  file. These are limitations for max
+					  idle time and max message count per
+					  connection.
+
+					  These values are used in the
+					  'io_thread' function. They are
+					  extracted here because the
+					  cfg_get_integer() function requires
+					  the 'grp' resource, which is not
+					  available from within the io_thread
+					  function.
+    					______________________________________*/
+    if (cfg_get_integer(&max_msg_count, grp, octstr_imm("sms-max-submits")) == -1) 
+        max_msg_count = 0; 
+    if (cfg_get_integer(&max_msg_time, grp, octstr_imm("sms-max-idle")) == -1) 
+        max_msg_time = 0; 
 
     my_number = alt_addr_charset = alt_charset = NULL;
     transceiver_mode = 0;
@@ -2150,11 +2317,19 @@
 
     conn->status = SMSCCONN_CONNECTING; 
        
+    					/*______________________________________
+					  These lines package up the SMSC
+					  connection limits so that the
+					  io_thread will be aware of them.
+    					______________________________________*/
+    smpp->last_msg_time =  (time_t)max_msg_time;
+    smpp->msg_count = max_msg_count;
     /* 
      * I/O threads are only started if the corresponding ports 
      * have been configured with positive numbers. Use 0 to  
      * disable the creation of the corresponding thread. 
      */ 
+
     if (port != 0) 
         smpp->transmitter = gwthread_create(io_thread, io_arg_create(smpp,  
                                            (transceiver_mode ? 2 : 1))); 
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.118
diff -u -r1.118 cfg.def
--- gwlib/cfg.def	9 May 2006 14:32:31 -0000	1.118
+++ gwlib/cfg.def	6 Jun 2006 21:43:08 -0000
@@ -368,6 +368,8 @@
     OCTSTR(preferred-prefix-regex)
     OCTSTR(max-error-count)
     OCTSTR(alt-addr-charset)
+    OCTSTR(sms-max-idle)
+    OCTSTR(sms-max-submits)
 )
 
 
