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();
