Re: sending too fast to SMPP SMSC?

Benjamin Lee <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <[email protected]>
Find attached my patch for SMPP bits and pieces.
It is a combined patch (sorry) including:

1.  configurable TON and NPI (modified from Alex Judd>

2.  unbind when shutting down

3.  configurable default priority for SMS messages

4.  configurable throughput to limit (throttle) sending SMS rate to SMPP SMSC

5.  Makefile.in changes, added install -d $(DESTDIR)$(... etc...
    facilitating consistent builds using RPM non-root)


(I apologise for some of the spacing differences...)


On Thursday, 2002-03-21 at 08:43:56 AM, Benjamin Lee scribbled:
> Well, actually nothing smart... we were sleeping when we received a
> THROTTLE off packet from the SMSC but this behaviour isn't actually
> specified in the protocol as far as I know; and such a sleep may or may not
> help with the connection to the SMSC.
> 
> The throughtput is set in the .conf file with:
> 
> throughput = 20
> 
> 20 being 20 messages per second.
> 
> On Wednesday, 2002-03-20 at 11:26:05 PM, Kita Ndara scribbled:
> > What's the principle? Do you detect certain types of
> > errors and re-queue? I can do some testing on my end
> > too, see if it helps more generally.
> > 
> > Let's see it!
> > 
> > Thanks.
> > 
> >  --- Benjamin Lee <[email protected]> wrote: > I
> > finally got around to doing a throughput patch for
> > > SMPP... I'll post it
> > > shortly.
> > > 
> > > On Wednesday, 2002-03-20 at 10:29:26 PM, Kita Ndara
> > > scribbled:
> > > > Hi  
> > > >  I have another issue. When I use kannel to
> > > originate
> > > > messages to many phone numbers, sometimes the SMSC
> > > > (Comverse) returns errors and rejects some of the
> > > > messages. If I slow down the rate at which I'm
> > > > submitting the messages to the SMSC, then it works
> > > > fine. Is there a way for kannel to kind of
> > > > automatically back off from sending too fast in
> > > such
> > > > cases?
> > > > 
> > > > Thanks.
> > > > 
> > > > =====
> > > > Bruce Ndara
> > > > York Messaging
> > > > 
> > > > __________________________________________________
> > > > Do You Yahoo!?
> > > > Everything you'll ever need on one web page
> > > > from News and Sport to Email and Music Charts
> > > > http://uk.my.yahoo.com
> > > 
> > > -- 
> > > Benjamin Lee
> > > 
> > > 71-75 City Rd, South Melbourne, VIC 3006 Australia 
> > > http://www.dotwap.com/
> > > Phone +61 3 9698 1840  Mobile +61 414 717 573  Fax
> > > +61 3 9698 1841 
> > 
> > __________________________________________________
> > Do You Yahoo!?
> > Everything you'll ever need on one web page
> > from News and Sport to Email and Music Charts
> > http://uk.my.yahoo.com
> 
> -- 
> Benjamin Lee
> 
> 71-75 City Rd, South Melbourne, VIC 3006 Australia  http://www.dotwap.com/
> Phone +61 3 9698 1840  Mobile +61 414 717 573  Fax +61 3 9698 1841

-- 
Benjamin Lee

71-75 City Rd, South Melbourne, VIC 3006 Australia  http://www.dotwap.com/
Phone +61 3 9698 1840  Mobile +61 414 717 573  Fax +61 3 9698 1841
combined-cvs-smpp-throttle-priority-unbind-npi-ton.patch (text/plain, 12 KB)
Index: Makefile.in
===================================================================
RCS file: /home/cvs/gateway/Makefile.in,v
retrieving revision 1.56
diff -u -r1.56 Makefile.in
--- Makefile.in	23 Jan 2002 18:33:00 -0000	1.56
+++ Makefile.in	22 Mar 2002 04:12:46 -0000
@@ -228,12 +228,12 @@
 dummy:
 
 install: all
-	$(INSTALL) -d $(bindir)
+	$(INSTALL) -d $(DESTDIR)$(bindir)
 	for prog in $(binprogs); do \
 		$(INSTALL) $$prog \
 		    $(DESTDIR)$(bindir)/`basename $$prog`$(suffix); \
 	done
-	$(INSTALL) -d $(sbindir)
+	$(INSTALL) -d $(DESTDIR)$(sbindir)
 	for prog in $(sbinprogs); do \
 		$(INSTALL) $$prog \
 		    $(DESTDIR)$(sbindir)/`basename $$prog`$(suffix); \
Index: gw/smpp_pdu.def
===================================================================
RCS file: /home/cvs/gateway/gw/smpp_pdu.def,v
retrieving revision 1.3
diff -u -r1.3 smpp_pdu.def
--- gw/smpp_pdu.def	8 Nov 2001 08:41:23 -0000	1.3
+++ gw/smpp_pdu.def	22 Mar 2002 04:12:48 -0000
@@ -162,6 +162,10 @@
     HEADER
 )
 
+PDU(generic_nack_resp,
+    0x80000000,
+    HEADER
+)
 
 #undef PDU
 #undef INTEGER
Index: gw/smsc_smpp.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc_smpp.c,v
retrieving revision 1.51
diff -u -r1.51 smsc_smpp.c
--- gw/smsc_smpp.c	29 Jan 2002 21:38:36 -0000	1.51
+++ gw/smsc_smpp.c	22 Mar 2002 04:12:48 -0000
@@ -70,6 +70,12 @@
     Octstr *username;
     Octstr *password;
     Octstr *address_range;
+    int source_addr_ton;
+    int source_addr_npi;
+    int dest_addr_ton;
+    int dest_addr_npi;
+    int throughput;     /* limit sending rate */
+    int priority;       /* set default priority for messages */
     int transmit_port;
     int receive_port;
     int quitting;
@@ -80,7 +86,10 @@
 static SMPP *smpp_create(SMSCConn *conn, Octstr *host, int transmit_port, 
     	    	    	 int receive_port, Octstr *system_type, 
 			 Octstr *username, Octstr *password,
-    	    	    	 Octstr *address_range)
+    	    	    	 Octstr *address_range, int source_addr_ton,
+                         int source_addr_npi, int dest_addr_ton,
+                         int dest_addr_npi,
+                         int throughput, int priority)
 {
     SMPP *smpp;
     
@@ -97,6 +106,14 @@
     smpp->username = octstr_duplicate(username);
     smpp->password = octstr_duplicate(password);
     smpp->address_range = octstr_duplicate(address_range);
+    smpp->source_addr_ton = source_addr_ton;
+    smpp->source_addr_npi = source_addr_npi;
+    smpp->dest_addr_ton = dest_addr_ton;
+    smpp->dest_addr_npi = dest_addr_npi;
+    
+    smpp->throughput = throughput;
+    smpp->priority = priority;
+    
     smpp->transmit_port = transmit_port;
     smpp->receive_port = receive_port;
     smpp->quitting = 0;
@@ -207,33 +224,45 @@
     pdu = smpp_pdu_create(submit_sm, 
     	    	    	  counter_increase(smpp->message_id_counter));
     	    	   
-    pdu->u.submit_sm.dest_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */
-    pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */
-    pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */
-    pdu->u.submit_sm.dest_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */
-    
     pdu->u.submit_sm.source_addr = octstr_duplicate(msg->sms.sender);
     pdu->u.submit_sm.destination_addr = octstr_duplicate(msg->sms.receiver);
+
+    /* Check for manual override of source ton and npi values */
+    if(smpp->source_addr_ton > -1 && smpp->source_addr_npi > -1) {
+        pdu->u.submit_sm.source_addr_ton = smpp->source_addr_ton;
+        pdu->u.submit_sm.source_addr_npi = smpp->source_addr_npi;
+    } else {
+        pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */
+        pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */
  
-    /* lets see if its international or alphanumeric sender */
-    if( octstr_get_char(pdu->u.submit_sm.source_addr,0) == '+') {
-        if (!octstr_check_range(pdu->u.submit_sm.source_addr, 1, 256, gw_isdigit)) {
-     	    pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; /* alphanum */
-   	    pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;
-    	}
-        else {
-	    /* numeric sender address with + in front -> international*/
-	    octstr_delete(pdu->u.submit_sm.source_addr,0,1);
-           pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_INTERNATIONAL;
-	}
-    }
-    else    {
-	if (!octstr_check_range(pdu->u.submit_sm.source_addr,0, 256, gw_isdigit)) {
-   	    pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC;
-   	    pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;
-   	}
+        /* lets see if its international or alphanumeric sender */
+        if( octstr_get_char(pdu->u.submit_sm.source_addr,0) == '+') {
+            if (!octstr_check_range(pdu->u.submit_sm.source_addr, 1, 256, gw_isdigit)) {
+     	        pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; /* alphanum */
+   	        pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;
+        	}
+            else {
+	        /* numeric sender address with + in front -> international*/
+	        octstr_delete(pdu->u.submit_sm.source_addr,0,1);
+               pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_INTERNATIONAL;
+    	    }
+        }
+        else    {
+    	    if (!octstr_check_range(pdu->u.submit_sm.source_addr,0, 256, gw_isdigit)) {
+   	        pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC;
+   	        pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;
+   	    }
+        }
+    } 
+
+    /* Check for manual override of destination ton and npi values */
+    if(smpp->dest_addr_ton > -1 && smpp->dest_addr_npi > -1) {
+        pdu->u.submit_sm.dest_addr_ton = smpp->dest_addr_ton;
+        pdu->u.submit_sm.dest_addr_npi = smpp->dest_addr_npi;
+    } else {
+        pdu->u.submit_sm.dest_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */
+        pdu->u.submit_sm.dest_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */
     }
-    
 
     /* if its a international number starting with +, lets remove the
     	'+' and set number type to international instead */
@@ -251,12 +280,23 @@
     } else {
 	pdu->u.submit_sm.short_message = octstr_duplicate(msg->sms.msgdata);
 	if(pdu->u.submit_sm.data_coding == 0 ) /*no reencoding for unicode! */
-	   charset_latin1_to_gsm(pdu->u.submit_sm.short_message);		
+	   charset_latin1_to_gsm(pdu->u.submit_sm.short_message);
     }
     /* ask for the delivery reports if needed */
     if (msg->sms.dlr_mask & (DLR_SUCCESS|DLR_FAIL))
  	pdu->u.submit_sm.registered_delivery = 1; 
 
+   
+    if ( smpp->priority > 0 && smpp->priority < 5 ) {
+	    
+	    pdu->u.submit_sm.priority_flag = smpp->priority;
+		
+    } else {
+		/* default priority is 0 */
+		pdu->u.submit_sm.priority_flag = 0;
+		
+	}	
+    
     return pdu;
 }
 
@@ -280,6 +320,21 @@
 }
 
 
+static void send_unbind(SMPP *smpp, Connection *conn)
+{
+    SMPP_PDU *pdu;
+    Octstr *os;
+
+    pdu = smpp_pdu_create(unbind, 
+			  counter_increase(smpp->message_id_counter));
+    dump_pdu("Sending unbind:", pdu);
+    os = smpp_pdu_pack(pdu);
+    conn_write(conn, os); /* Write errors checked by caller. */
+    octstr_destroy(os);
+    smpp_pdu_destroy(pdu);
+}
+
+
 static int send_pdu(Connection *conn, SMPP_PDU *pdu)
 {
     Octstr *os;
@@ -298,11 +353,23 @@
     Msg *msg;
     SMPP_PDU *pdu;
     Octstr *os;
+    
+    unsigned long delay = 0; /* sleep delay for throttling */
 
     if (*pending_submits == -1)
     	return;
 
     while (*pending_submits < SMPP_MAX_PENDING_SUBMITS) {
+
+    if ( smpp->throughput != 0 ) {
+		delay = 1000000 / smpp->throughput;
+    }
+	
+    debug("bb.sms.smpp", 0, "SMPP: delay: %d", delay);
+    
+	/* throttle */
+	usleep(delay);
+	    
     	/* Get next message, quit if none to be sent */
     	msg = list_extract_first(smpp->msgs_to_send);
 	if (msg == NULL)
@@ -623,6 +690,18 @@
 	}
 	break;
 
+    case generic_nack_resp:
+        {
+			error(0, "SMPP: NACK PDU type 0x%08lx, "
+				"code 0x%08lx.",
+				pdu->type, pdu->u.generic_nack_resp.command_status);
+
+        }
+    break;
+    
+    case unbind_resp:
+	break;
+    
     default:
 	error(0, "SMPP: Unknown PDU type 0x%08lx, ignored.", 
 		 pdu->type);
@@ -697,6 +776,27 @@
     	for (;;) {
 	    timeout = last_enquire_sent + SMPP_ENQUIRE_LINK_INTERVAL 
 	    	    	    - date_universal_now();
+        
+        /* unbind... */
+            if (smpp->quitting) {
+                /* if we are quitting */
+                
+                send_unbind(smpp, conn);
+                
+                /* handle unbind_resp */
+	            while ((ret = read_pdu(conn, &len, &pdu)) == 1) {
+    	    	        /* Deal with the PDU we just got */
+		            dump_pdu("Got PDU:", pdu);
+		            handle_pdu(smpp, conn, pdu, &pending_submits);
+	    	        smpp_pdu_destroy(pdu);
+                }
+                
+                debug("bb.sms.smpp", 0, "SMPP: %s: break and shutting down", __PRETTY_FUNCTION__);
+                
+                /* the next if statement will do the real quit */
+            }
+        /* end unbind */
+        
     	    if (smpp->quitting || conn_wait(conn, timeout) == -1)
 	    	break;
 
@@ -804,6 +904,13 @@
     Octstr *system_id;
     Octstr *system_type;
     Octstr *address_range;
+    long source_addr_ton;
+    long source_addr_npi;
+    long dest_addr_ton;
+    long dest_addr_npi;
+    long throughput;
+    long priority;
+    
     SMPP *smpp;
     int ok;
     
@@ -817,6 +924,24 @@
     system_type = cfg_get(grp, octstr_imm("system-type"));
     address_range = cfg_get(grp, octstr_imm("address-range"));
     
+    /* if the ton and npi values are forced, set them, else set them to -1 */
+    cfg_get_integer(&source_addr_ton, grp, octstr_imm("source-addr-ton"));
+    cfg_get_integer(&source_addr_npi, grp, octstr_imm("source-addr-npi"));
+    cfg_get_integer(&dest_addr_ton, grp, octstr_imm("dest-addr-ton"));
+    cfg_get_integer(&dest_addr_npi, grp, octstr_imm("dest-addr-npi"));
+    
+    /* throughput limits the rate at which messages are sent to the SMPP SMSC  */
+	/* if it is not specified, set to 0, which means no limit */
+    if ( cfg_get_integer(&throughput, grp, octstr_imm("throughput")) == -1 ) {
+        throughput = 0;
+    }
+    debug("bb.sms.smpp", 0, "SMPP: throughtput: %d", throughput);
+    
+    if ( cfg_get_integer(&priority, grp, octstr_imm("priority")) == -1 ) {
+        priority = 0;
+    }
+    debug("bb.sms.smpp", 0, "SMPP: priority: %d", priority);
+
     system_id = cfg_get(grp, octstr_imm("system-id"));
     if (system_id != NULL) {
 	warning(0, "SMPP: obsolete system-id variable is set, "
@@ -845,7 +970,9 @@
     	return -1;
 
     smpp = smpp_create(conn, host, port, receive_port, system_type, 
-    	    	       username, password, address_range);
+    	    	       username, password, address_range, source_addr_ton,
+                       source_addr_npi, dest_addr_ton, dest_addr_npi,
+                        throughput, priority);
     conn->data = smpp;
     conn->name = octstr_format("SMPP:%S:%d/%d:%S:%S", 
     	    	    	       host, port,
Index: gw/smsc_wrapper.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc_wrapper.c,v
retrieving revision 1.26
diff -u -r1.26 smsc_wrapper.c
--- gw/smsc_wrapper.c	28 Jul 2001 03:18:23 -0000	1.26
+++ gw/smsc_wrapper.c	22 Mar 2002 04:12:48 -0000
@@ -181,7 +181,7 @@
 
     debug("bb.sms", 0, "smscconn_sender (%s): sending message",
 	  octstr_get_cstr(conn->name));
-        
+
     ret = smscenter_submit_msg(wrap->smsc, msg);
     if (ret == -1) {
 	bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_REJECTED);
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.46
diff -u -r1.46 cfg.def
--- gwlib/cfg.def	21 Mar 2002 03:54:32 -0000	1.46
+++ gwlib/cfg.def	22 Mar 2002 04:12:48 -0000
@@ -194,6 +194,11 @@
     OCTSTR(retry)
     OCTSTR(my-number)
     OCTSTR(sms-center)
+    OCTSTR(source-addr-ton)
+    OCTSTR(source-addr-npi)
+    OCTSTR(dest-addr-ton)
+    OCTSTR(dest-addr-npi)
+    OCTSTR(priority)
 )
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.