Re: Patch: test/drive_smpp.c

"Nikos Balkanas" <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <AD9592BDE7B845A5A3B69FEE31E1855C@drwho>
Hi,

Fixed identation. Beafed up smsbox_thread and routed most variables to 
configuration. Uses main kannel configuration. Just add an smpp smsc 
definition to 127.0.0.1 for it. It will test main kannel configuration in 
addition to TLVs. As already mentioned I extended its functionality to 
handle external messaging and concatenation. It is a FAKE smpp server, that 
also, benchmarks bearerbox's SMPP implementation.

Anyone interested, please grab. If it makes it to kannel, i will also 
provide documentation.

BR,
Nikos
drive_smpp.diff (application/octet-stream, 12.8 KB)
Index: test/drive_smpp.c
===================================================================
--- test/drive_smpp.c	(revision 4833)
+++ test/drive_smpp.c	(working copy)
@@ -69,16 +69,22 @@
 #include "gwlib/gwlib.h"
 #include "gw/smsc/smpp_pdu.h"
 #include "gw/msg.h"
+#include "shared.h"
 
+#define MAX_SMS_OCTETS 140
+#define CATENATE_UDH_LEN 5
 
+typedef unsigned char uchar;
+
 static int quitting = 0;
 static Octstr *smsc_system_id;
 static Octstr *smsc_source_addr;
 static Counter *message_id_counter;
 static Octstr *bearerbox_host;
-static int port_for_smsbox;
+static long port_for_smsbox;
 static Counter *num_to_esme;
 static long max_to_esme;
+static long port;
 static Counter *num_from_bearerbox;
 static Counter *num_to_bearerbox;
 static Counter *num_from_esme;
@@ -89,6 +95,9 @@
 static time_t first_from_bb = (time_t) -1;
 static time_t last_to_bb = (time_t) -1;
 static long enquire_interval = 1; /* Measured in messages, not time. */
+static Octstr *SMS = NULL;
+static Octstr *smsbox_id;
+static Octstr *smsc_id;
 
 
 static void quit(void)
@@ -109,7 +118,7 @@
 static ESME *esme_create(Connection *conn)
 {
     ESME *esme;
-    
+
     esme = gw_malloc(sizeof(*esme));
     esme->conn = conn;
     esme->transmitter = 0;
@@ -131,7 +140,7 @@
 static SMPP_PDU *handle_bind_transmitter(ESME *esme, SMPP_PDU *pdu)
 {
     SMPP_PDU *resp;
-    
+
     esme->transmitter = 1;
     esme->version = pdu->u.bind_transmitter.interface_version;
     resp = smpp_pdu_create(bind_transmitter_resp,
@@ -147,7 +156,7 @@
 static SMPP_PDU *handle_bind_receiver(ESME *esme, SMPP_PDU *pdu)
 {
     SMPP_PDU *resp;
-    
+
     esme->receiver = 1;
     esme->version = pdu->u.bind_receiver.interface_version;
     resp = smpp_pdu_create(bind_receiver_resp,
@@ -163,7 +172,7 @@
 {
     SMPP_PDU *resp;
     unsigned long id;
-    
+
     debug("test.smpp", 0, "submit_sm: short_message = <%s>",
     	  octstr_get_cstr(pdu->u.submit_sm.short_message));
     id = counter_increase(num_from_esme) + 1;
@@ -189,7 +198,7 @@
 static SMPP_PDU *handle_unbind(ESME *esme, SMPP_PDU *pdu)
 {
     SMPP_PDU *resp;
-    
+
     resp = smpp_pdu_create(unbind_resp, pdu->u.unbind.sequence_number);
     return resp;
 }
@@ -249,16 +258,24 @@
     smpp_pdu_dump(pdu);
 }
 
+void load_deliver_pdu(SMPP_PDU *pdu, Octstr *data, ESME *esme)
+{
+   pdu->u.deliver_sm.source_addr = octstr_create("456");
+   pdu->u.deliver_sm.destination_addr = octstr_create("123");
+   pdu->u.deliver_sm.short_message = data;
+   if (esme->version > 0x33)
+      pdu->u.deliver_sm.receipted_message_id = octstr_create("receipted_message_id\0");
+}
 
 static void send_smpp_thread(void *arg)
 {
     ESME *esme;
-    Octstr *os;
+    Octstr *os, *data;
     SMPP_PDU *pdu;
     unsigned long id;
 
     esme = arg;
-    
+
     id = 0;
     while (!quitting && counter_value(num_to_esme) < max_to_esme) {
         id = counter_increase(num_to_esme) + 1;
@@ -266,23 +283,67 @@
             gwthread_sleep(1.0);
         if (quitting)
             break;
-        pdu = smpp_pdu_create(deliver_sm, counter_increase(message_id_counter));
-        pdu->u.deliver_sm.source_addr = octstr_create("456");
-        pdu->u.deliver_sm.destination_addr = octstr_create("123");
-        pdu->u.deliver_sm.short_message = octstr_format("%ld", id);
-        if (esme->version > 0x33)
-            pdu->u.deliver_sm.receipted_message_id = octstr_create("receipted_message_id\0");
+         if (SMS)
+         {
+            if (octstr_len(SMS) <= (MAX_SMS_OCTETS * 8)/7)
+            {
+               data = octstr_create(octstr_get_cstr(SMS));
+               goto single;
+            }
+            else
+            {
+               uchar   *start = octstr_get_cstr(SMS), *p = start, *end, c;
+               int   len = octstr_len(SMS), part = 0, num_msgs, part_len;
+
+               part_len = (MAX_SMS_OCTETS - CATENATE_UDH_LEN - 1) *8/7;
+               num_msgs = len/part_len;
+               if (len%part_len) num_msgs++;
+               while (start - p < len)
+               {
+                  part++;
+                  end = start + part_len;
+                  if (end < p + len)
+                  {
+                     c = *end;
+                     *end = '\0';
+                  }
+                  else end = p + len;
+                  data = octstr_format("%c%c\3\xAF%c%c", CATENATE_UDH_LEN, 0,
+                     num_msgs, part);
+                  octstr_append_data(data, start, end - start);
+                  if (end < p + len) *end = c;
+                  pdu = smpp_pdu_create(deliver_sm, counter_increase
+                     (message_id_counter));
+                  load_deliver_pdu(pdu, data, esme);
+                  pdu->u.deliver_sm.esm_class = pdu->u.deliver_sm.esm_class |
+                     ESM_CLASS_DELIVER_UDH_INDICATOR;
         os = smpp_pdu_pack(NULL, pdu);
         conn_write(esme->conn, os);
         octstr_destroy(os);
         smpp_pdu_destroy(pdu);
+                  start = end;
+               }
+            }
+         }
+         else
+         {
+            data = octstr_format("%ld", id);
+single:      pdu = smpp_pdu_create(deliver_sm, counter_increase
+               (message_id_counter));
+            load_deliver_pdu(pdu, data, esme);
+            os = smpp_pdu_pack(NULL, pdu);
+            conn_write(esme->conn, os);
+            octstr_destroy(os);
+            smpp_pdu_destroy(pdu);
+         }
         if (first_to_esme == (time_t) -1)
             time(&first_to_esme);
         debug("test.smpp", 0, "Delivered SMS %ld of %ld to bearerbox via SMPP.",
               id, max_to_esme);
 
         if ((id % enquire_interval) == 0) {
-            pdu = smpp_pdu_create(enquire_link, counter_increase(message_id_counter));
+            pdu = smpp_pdu_create(enquire_link, counter_increase
+                  (message_id_counter));
             os = smpp_pdu_pack(NULL, pdu);
             conn_write(esme->conn, os);
             octstr_destroy(os);
@@ -306,7 +367,7 @@
     SMPP_PDU *pdu;
 
     esme = arg;
-    
+
     sender_id = -1;
     len = 0;
     while (!quitting && conn_wait(esme->conn, -1.0) != -1) {
@@ -322,7 +383,7 @@
 		    break;
 		}
 	    }
-    
+
     	    gw_assert(len > 0);
 	    os = smpp_pdu_read_data(esme->conn, len);
 	    if (os != NULL) {
@@ -356,30 +417,53 @@
     debug("test.smpp", 0, "%s terminates.", __func__);
 }
 
+/*
+ * Identify ourself to bearerbox for smsbox-specific routing inside bearerbox.
+ * Do this even while no smsbox-id is given to unlock the sender thread in
+ * bearerbox.
+ */
+static void announce_to_bearerbox(Connection *conn)
+{
+   Msg      *msg;
+   Octstr   *pack;
 
+   debug("smpp.test", 0, "Announcing smsbox %s to bearerbox", octstr_get_cstr
+      (smsbox_id));
+   msg = msg_create(admin);
+   msg->admin.command = cmd_identify;
+   msg->admin.boxc_id = octstr_duplicate(smsbox_id);
+   pack = msg_pack(msg);
+   conn_write_withlen(conn, pack);
+   octstr_destroy(pack);
+}
+
 static void smsbox_thread(void *arg)
 {
     Connection *conn;
-    Msg *msg;
+   Msg *msg, *msgin = NULL;
     Octstr *os;
-    Octstr *reply_msg;
+   Octstr *reply_msg = NULL;
     unsigned long count;
-    
+
     msg = msg_create(sms);
     msg->sms.sender = octstr_create("123");
     msg->sms.receiver = octstr_create("456");
     msg->sms.msgdata = octstr_create("hello world");
-    reply_msg = msg_pack(msg);
-    msg_destroy(msg);
 
     gwthread_sleep(1.0);
     conn = conn_open_tcp(bearerbox_host, port_for_smsbox, NULL);
-    if (conn == NULL) {
+   if (conn == NULL)
+   {
 	gwthread_sleep(2.0);
 	conn = conn_open_tcp(bearerbox_host, port_for_smsbox, NULL);
     	if (conn == NULL)
 	    panic(0, "Couldn't connect to bearerbox as smsbox");
+      else debug("test.smpp", 0, "Connected as smsbox to bearerbox %s:%ld",
+         octstr_get_cstr(bearerbox_host), port_for_smsbox);
     }
+   else debug("test.smpp", 0, "Connected as smsbox to bearerbox %s:%ld",
+      octstr_get_cstr(bearerbox_host), port_for_smsbox);
+   announce_to_bearerbox(conn);
 
     while (!quitting && conn_wait(conn, -1.0) != -1) {
     	for (;;) {
@@ -389,32 +473,38 @@
 		    goto error;
 		break;
 	    }
-	    
-	    msg = msg_unpack(os);
-	    if (msg == NULL || msg->type == wdp_datagram)
+
+         msgin = msg_unpack(os);
+         if (msgin == NULL || msgin->type == wdp_datagram)
 		error(0, "Bearerbox sent garbage to smsbox");
 
-	    if (msg->type == sms) {
+         if (msgin->type == sms) {
 		if (first_from_bb == (time_t) -1)
 		    time(&first_from_bb);
 		count = counter_increase(num_from_bearerbox) + 1;
 		debug("test.smpp", 0, 
 		      "Bearerbox sent sms #%ld <%s> to smsbox, sending reply.",
-		      count, octstr_get_cstr(msg->sms.msgdata));
+                  count, octstr_get_cstr(msgin->sms.msgdata));
 		if (count == max_to_esme)
 		    info(0, "Bearerbox has sent all messages to smsbox.");
+            octstr_destroy(msg->sms.smsc_id);
+            msg->sms.smsc_id = msgin->sms.smsc_id;
+            msgin->sms.smsc_id = NULL;
+            octstr_destroy(reply_msg);
+            reply_msg = msg_pack(msg);
+            msg_destroy(msgin);
 		conn_write_withlen(conn, reply_msg);
 		counter_increase(num_to_bearerbox);
 	    }
-	    msg_destroy(msg);
 	    octstr_destroy(os);
 	    time(&last_to_bb);
 	}
     }
-    
-error:
+
+   error:
     conn_destroy(conn);
     octstr_destroy(reply_msg);
+   msg_destroy(msg);
     debug("test.smpp", 0, "%s terminates.", __func__);
 }
 
@@ -428,7 +518,7 @@
     struct sockaddr addr;
     long smsbox_thread_id;
     
-    port = *(int *) arg;
+    port = *(long *) arg;
     fd = make_server_socket(port, NULL);
     if (fd == -1)
     	panic(0, "Couldn't create SMPP listen port.");
@@ -459,15 +549,50 @@
 
 static void help(void)
 {
-    info(0, "drive_smpp [-h] [-v level][-l logfile][-p port][-m msgs][-c config]");
+    info(0, "drive_smpp [-h][-v level][-l logfile][-p http_port][-M SMS][-m msgs][-c config]");
 }
 
+void smpp_init(Cfg *cfg)
+{
+   CfgGroup   *grp;
+   Octstr   *value;
+   List      *grplist;
 
+   if (!(grp = cfg_get_single_group(cfg, octstr_imm("core"))))
+      panic(0, "Missing core group");
+   if (cfg_get_integer(&port_for_smsbox, grp, octstr_imm("smsbox-port")) == -1)
+      port_for_smsbox = 13001;
+   if (!(grp = cfg_get_single_group(cfg, octstr_imm("smsbox"))))
+      panic(0, "Missing smsbox definition");
+   if (!(smsbox_id = cfg_get(grp, octstr_imm("smsbox-id"))))
+      panic(0, "Missing smsbox-id definition");
+   if ((grplist = cfg_get_multi_group(cfg, octstr_imm("smsc"))))
+   {
+      while ((grp = gwlist_extract_first(grplist)))
+      {
+         if ((value = cfg_get(grp, octstr_imm("host"))) && octstr_compare
+            (value, octstr_imm("127.0.0.1")) == 0)
+         {
+            if (!(smsc_id = cfg_get(grp, octstr_imm("smsc-id"))))
+               panic(0, "Missing smsc-id in smpp smsc definition");
+            if (cfg_get_integer(&port, grp, octstr_imm("port")) == -1)
+               port = 2345;
+            break;
+         }
+         octstr_destroy(value);
+      }
+   }
+   else panic(0, "Missing smpp smsc definition");
+   if (!smsc_id) panic(0, "Missing local (127.0.0.1) smpp smsc definition");
+   gwlist_destroy(grplist, NULL);
+   smpp_pdu_init(cfg);
+}
+
+
 int main(int argc, char **argv)
 {
     struct sigaction act;
     int http_port;
-    int port;
     int opt;
     double run_time;
     char *log_file;
@@ -481,13 +606,11 @@
     sigaction(SIGTERM, &act, NULL);
     sigaction(SIGINT, &act, NULL);
 
-    port = 2345;
     http_port = 8080;
     smsc_system_id = octstr_create("kannel_smpp");
     smsc_source_addr = octstr_create("123456");
     message_id_counter = counter_create();
     bearerbox_host = octstr_create("127.0.0.1");
-    port_for_smsbox = 13001;
     max_to_esme = 1;
     num_to_esme = counter_create();
     num_from_esme = counter_create();
@@ -495,7 +618,7 @@
     num_from_bearerbox = counter_create();
     log_file = config_file = NULL;
 
-    while ((opt = getopt(argc, argv, "hv:p:P:m:l:c:")) != EOF) {
+    while ((opt = getopt(argc, argv, "hv:p:M:m:l:c:")) != EOF) {
 	switch (opt) {
 	case 'v':
 	    log_set_output_level(atoi(optarg));
@@ -509,18 +632,18 @@
 	    max_to_esme = atoi(optarg);
 	    break;
 
-	case 'p':
-	    port = atoi(optarg);
+         case 'M':
+            SMS = octstr_imm(optarg);
 	    break;
 
-	case 'P':
+         case 'p':
 	    http_port = atoi(optarg);
 	    break;
 
     case 'l':
         log_file = optarg;
         break;
-    
+
     case 'c':
         config_file = optarg;
         break;
@@ -539,15 +662,15 @@
     if (config_file != NULL) {
         Cfg *cfg;
         Octstr *tmp = octstr_create(config_file);
-        
+
         cfg = cfg_create(tmp);
         octstr_destroy(tmp);
         if (cfg_read(cfg) == -1)
             panic(0, "Errors in config file.");
-        smpp_pdu_init(cfg);
+        smpp_init(cfg);
         cfg_destroy(cfg);
     }
-            
+
     info(0, "Starting drive_smpp test.");
     gwthread_create(accept_thread, &port);
     gwthread_join_all();
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.