Hi,

I have developed an enhancement to the bearerbox. I have added
"sender-number" and "default-sender-number" to group "smsc". This allows to
replace originator address for outgoing traffic (MT) of specified smsc-id.
The "default-sender-number" parameter defines default number for outgoing
SMS if there's no explict rule for replacing originator address by
specified smsbox-id(s) (see "sender" parameter). You may use the
combination of these two parameters.

It very helpful when you have many SMSC connections as well as ESMEs with
different assigned numbers and difficult MT routing between these
connections. Depending on the route it helps disguise the originator
address for specified smsc-id.

In this example if route of MT traffic will go through mysmsc1, for
smsbox-id test1 originator address will change to 79031111101 and for
smsbox-id test2 it changes to 79031111102. For another smsbox-ids it will
replaced by default number 79031111103. And if route of MT traffic will go
through mysmsc2 all messages will have outgoing alphanumber 1111:

group = smsc
smsc-id = mysmsc1
...
allowed-prefix="+7;+7903;+7905;+7906;+7909;+796;+976"
preferred-prefix="+7903;+7905;+7906;+7909;+796;+976"
preferred-smsc-id = "mysmsc1;outgoing"
sender-number = "test1,79031111101;test2:79031111102"
default-sender-number = "79031111103"

group = smsc
smsc-id = mysmsc2
...
allowed-prefix="+791;+798"
preferred-prefix="+791;+798"
preferred-smsc-id = "mysmsc2;outgoing"
default-sender-number = "1111"

The second enhancement allows to add the route for MO traffic based on
originator address(es) to specified smsbox-id. I have added "sender" to the
"smsbox-route" group for such behavior. This helps route incoming traffic
from specified sims to some test smsbox-id for example.

This this example all incoming traffic (MO) from sims 79032222222 and
79101111111 should route to the mytestbox smsbox-id (no matter what source
SMSC is). All over traffic from two SMSCs mysmsc1 and mysmsc2 will go to
prodbox (this is default rule for these SMSCs).

group = smsbox-route
smsbox-id = prodbox
smsc-id = mysmsc1

group = smsbox-route
smsbox-id = prodbox
smsc-id = mysmsc2

group = smsbox-route
sender = "+79032222222;+79101111111"
smsbox-id = testbox

Included below is the diff with the documentation update. Please let me
know if you have any questions or comments.

--
Regards,
Denis S.Davydov
Index: doc/userguide/userguide.xml
===================================================================
--- doc/userguide/userguide.xml (revision 5195)
+++ doc/userguide/userguide.xml (working copy)
@@ -3059,6 +3059,26 @@
         </entry>   
      </row>
 
+     <row><entry><literal>default-sender-number</literal></entry>
+        <entry>string</entry>
+        <entry valign="bottom">
+        The default originator number to be used for outgoing messages (MT). 
This allows to replace
+        originator address in submit_sm if there is no explict rules for 
messages that are coming 
+        from specified smsbox-id (see sender-number).
+        </entry>
+     </row>
+
+     <row><entry><literal>sender-number</literal></entry>
+        <entry>string</entry>
+        <entry valign="bottom">
+        Defines the explicit originator number for messages that are coming 
from specified smsbox-id.
+        Format is that first comes the smsbox-id which the messages are coming 
from, then originator 
+        address which should be replaced by, separated with comma (','). For 
example, originator 
+        addresses 7777 for messages that are coming from smsbox-id A and 8888 
from smsbox-id B would 
+        look like: "A,7777;B,8888".
+        </entry>
+     </row>
+
   </tbody>
   </tgroup>
  </table>
@@ -6648,8 +6668,23 @@
        Which means any inbound message with receiver number 1111 or 2222 that 
have
        been originating from the smsc-id connections A, B or C will be 
delivered
        to the via the id "mysmsc" to bearerbox.
-       </para>
 
+<programlisting>
+group = smsbox
+...
+smsbox-id = mysmsc
+...
+
+group = smsbox-route
+smsbox-id = mysmsc
+sender = "+77777777777;+88888888888"
+</programlisting>
+
+        Which means any inbound message with sender number +77777777777 or 
+88888888888
+        that have been originating from any of smsc-id connections will be 
delivered to
+        the via the id "mysmsc" to bearerbox.
+        </para>
+
    <para>smsbox-route inherits from core the following fields:
    </para>
 
@@ -6695,9 +6730,18 @@
                  by semicolon (";"). This rule may be used to pull receiver 
number
                  specific message streams to an smsbox instance. If used in 
combination
                  with config directive smsc-id, then only messages originating 
from
-                 the connections in the smsc-id are matched against the 
shortcode list.
+                  the connections in the smsc-id are matched against the 
shortcode list.
      </entry></row>
 
+         <row><entry><literal>sender</literal></entry>
+     <entry>number-list</entry>
+     <entry valign="bottom">
+        Same as shortcode, but specifies which sender numbers for inbound 
messages 
+                  should be routed to this smsbox instance. List contains 
numbers
+                  separated by semicolon (";"). This rule may used to pull 
sender number
+                  specific message streams to an smsbox instance.
+     </entry></row>
+
   </tbody>
   </tgroup>
  </table>
Index: gw/bb_boxc.c
===================================================================
--- gw/bb_boxc.c        (revision 5195)
+++ gw/bb_boxc.c        (working copy)
@@ -111,6 +111,7 @@
 static Dict *smsbox_by_smsc;
 static Dict *smsbox_by_receiver;
 static Dict *smsbox_by_smsc_receiver;
+static Dict *smsbox_by_sender;
 
 static long    smsbox_port;
 static int smsbox_port_ssl;
@@ -1066,6 +1067,8 @@
     smsbox_by_receiver = NULL;
     dict_destroy(smsbox_by_smsc_receiver);
     smsbox_by_smsc_receiver = NULL;
+    dict_destroy(smsbox_by_sender);
+    smsbox_by_sender = NULL;
 
     gwlist_remove_producer(flow_threads);
 }
@@ -1120,10 +1123,10 @@
 {
     CfgGroup *grp;
     List *list, *items;
-    Octstr *boxc_id, *smsc_ids, *shortcuts;
+    Octstr *boxc_id, *smsc_ids, *shortcuts, *senders;
     int i, j;
 
-    boxc_id = smsc_ids = shortcuts = NULL;
+    boxc_id = smsc_ids = shortcuts = senders = NULL;
 
     list = cfg_get_multi_group(cfg, octstr_imm("smsbox-route"));
 
@@ -1146,9 +1149,27 @@
          */
         smsc_ids = cfg_get(grp, octstr_imm("smsc-id"));
         shortcuts = cfg_get(grp, octstr_imm("shortcode"));
+        senders = cfg_get(grp, octstr_imm("sender"));
 
-        /* consider now the 3 possibilities: */
-        if (smsc_ids && !shortcuts) {
+        /* consider now the 4 possibilities: */
+        if (senders) {
+            /* senders only, so these MOs from specified numbers */
+            items = octstr_split(senders, octstr_imm(";"));
+            for (i = 0; i < gwlist_len(items); i++) {
+                Octstr *item = gwlist_get(items, i);
+                octstr_strip_blanks(item);
+
+                debug("bb.boxc",0,"Adding smsbox routing to id <%s> for sender 
no <%s>",
+                      octstr_get_cstr(boxc_id), octstr_get_cstr(item));
+
+                if (!dict_put_once(smsbox_by_sender, item, 
octstr_duplicate(boxc_id)))
+                    panic(0, "Routing for sender no <%s> already exists!",
+                          octstr_get_cstr(item));
+            }
+            gwlist_destroy(items, octstr_destroy_item);
+            octstr_destroy(senders);
+        }
+        else if (smsc_ids && !shortcuts) {
             /* smsc-id only, so all MO traffic */
             items = octstr_split(smsc_ids, octstr_imm(";"));
             for (i = 0; i < gwlist_len(items); i++) {
@@ -1270,6 +1291,7 @@
     smsbox_by_smsc = dict_create(30, (void(*)(void *)) octstr_destroy);
     smsbox_by_receiver = dict_create(50, (void(*)(void *)) octstr_destroy);
     smsbox_by_smsc_receiver = dict_create(50, (void(*)(void *)) 
octstr_destroy);
+    smsbox_by_sender = dict_create(250, (void(*)(void *)) octstr_destroy);
 
     /* load the defined smsbox routing rules */
     init_smsbox_routes(cfg);
@@ -1511,7 +1533,7 @@
 int route_incoming_to_boxc(Msg *msg)
 {
     Boxc *bc = NULL;
-    Octstr *s, *r, *rs, *boxc_id = NULL;
+    Octstr *s, *r, *rs, *boxc_id = NULL, *sender;
     long len, b, i;
     int full_found = 0;
 
@@ -1551,10 +1573,14 @@
         rs = (os ? dict_get(smsbox_by_smsc_receiver, os) : NULL);
         octstr_destroy(os);
 
+       sender = (msg->sms.sender ? dict_get(smsbox_by_sender, msg->sms.sender) 
: NULL);
+
         if (rs)
             boxc_id = rs;
+        else if (sender)
+           boxc_id = sender;
         else if (r)
-            boxc_id = r;
+           boxc_id = r;
         else if (s)
             boxc_id = s;
     }
Index: gw/smsc/smsc_smpp.c
===================================================================
--- gw/smsc/smsc_smpp.c (revision 5195)
+++ gw/smsc/smsc_smpp.c (working copy)
@@ -1527,6 +1527,8 @@
     if (network_error_code != NULL) {
         err_int = error_from_network_error_code(network_error_code);
         network_err = octstr_duplicate(network_error_code);
+        debug("bb.sms.smpp", 0, "SMPP[%s]: PDU network error %d: %s",
+               octstr_get_cstr(smpp->conn->id), err_int, 
octstr_get_cstr(network_err));
     }
     
     /* check for SMPP v.3.4. and message_payload */
Index: gw/smscconn.c
===================================================================
--- gw/smscconn.c       (revision 5195)
+++ gw/smscconn.c       (working copy)
@@ -145,7 +145,60 @@
     }
 }
 
+/*
+ * Add sender numbers to the connection data. Where the priority
+ * is in the order: sender-number, default-sender-number.
+ */
+static void init_senders(SMSCConn *conn, CfgGroup *grp)
+{
+    Octstr *rule;
+    long i;
 
+    if ((conn->default_sender_number = cfg_get(grp, 
octstr_imm("default-sender-number"))) != NULL) {
+       debug("smscconn", 0, "Adding default sender number <%s> for smsc id 
<%s>",
+           octstr_get_cstr(conn->id), 
octstr_get_cstr(conn->default_sender_number));
+    }
+    
+    if ((rule = cfg_get(grp, octstr_imm("sender-number"))) != NULL) {
+        List *numbers;
+
+        /* create hash dictionary for this smsc-id */
+        conn->sender_by_smsbox_id = dict_create(20, (void(*)(void *)) 
octstr_destroy);
+
+        numbers = octstr_split(rule, octstr_imm(";"));
+        for (i = 0; i < gwlist_len(numbers); i++) {
+            Octstr *item = gwlist_get(numbers, i);
+            Octstr *smsbox_id, *sender;
+           List *list;
+
+            /* first word is the smsbox-id, second word is the sender-number */
+            list = octstr_split(item, octstr_imm(","));
+            smsbox_id = gwlist_extract_first(list);
+            if (smsbox_id)
+                octstr_strip_blanks(smsbox_id);
+            sender = gwlist_extract_first(list);
+            if (sender)
+                octstr_strip_blanks(sender);
+
+           if (smsbox_id && octstr_len(smsbox_id) && sender && 
octstr_len(sender)) {
+               debug("smscconn",0,"Adding sender number for smsc id <%s>: 
smsbox-id <%s> to number <%s>",
+                   octstr_get_cstr(conn->id), octstr_get_cstr(smsbox_id), 
octstr_get_cstr(sender));
+               if (!dict_put_once(conn->sender_by_smsbox_id, smsbox_id, 
octstr_duplicate(sender)))
+                   panic(0, "Could not add sender number <%s> to smsbox-id 
<%s> on smsc id <%s>, because"
+                       "smsbox-id has already entry!", octstr_get_cstr(sender),
+                           octstr_get_cstr(smsbox_id), 
octstr_get_cstr(conn->id));
+           }
+           
+            octstr_destroy(smsbox_id);
+            octstr_destroy(sender);
+            gwlist_destroy(list, octstr_destroy_item);
+        }
+        octstr_destroy(rule);
+        gwlist_destroy(numbers, octstr_destroy_item);
+    }
+}
+
+
 unsigned int smscconn_instances(CfgGroup *grp)
 {
     long i;
@@ -299,6 +352,9 @@
 
     /* configure the internal rerouting rules for this smsc id */
     init_reroute(conn, grp);
+    
+    /* configure the sender rules for this smsc id */
+    init_senders(conn, grp);
 
     if (cfg_get_integer(&conn->log_level, grp, octstr_imm("log-level")) == -1)
         conn->log_level = 0;
@@ -436,6 +492,10 @@
     octstr_destroy(conn->log_file);
     octstr_destroy(conn->chksum);
     octstr_destroy(conn->chksum_conn);
+    
+    octstr_destroy(conn->default_sender_number);
+    octstr_destroy(conn->sender_number);
+    dict_destroy(conn->sender_by_smsbox_id);
 
     if (conn->denied_smsc_id_regex != NULL) 
gw_regex_destroy(conn->denied_smsc_id_regex);
     if (conn->allowed_smsc_id_regex != NULL) 
gw_regex_destroy(conn->allowed_smsc_id_regex);
@@ -595,8 +655,9 @@
 
 int smscconn_send(SMSCConn *conn, Msg *msg)
 {
-    int ret = -1;
+    int ret = -1, replaced = 0;
     List *parts = NULL;
+    Octstr *sender = NULL;
     
     gw_assert(conn != NULL);
     mutex_lock(conn->flow_mutex);
@@ -605,6 +666,29 @@
         return -1;
     }
 
+    /* Replace MT sender number with sender-number */
+    if (conn->sender_by_smsbox_id && octstr_len(msg->sms.service) > 0) {
+        sender = dict_get(conn->sender_by_smsbox_id, msg->sms.service);
+       if (sender) {
+           octstr_destroy(msg->sms.sender);
+           msg->sms.sender = octstr_duplicate(sender);
+           debug("smscconn",0,"Replacing MT for smsc id <%s>: msg sent from 
smsbox-id <%s>, sender replaced by <%s>",
+               octstr_get_cstr(conn->id), octstr_get_cstr(msg->sms.service), 
octstr_get_cstr(msg->sms.sender));
+           replaced = 1;
+       } else {
+           debug("smscconn", 0, "Replacing MT for smsc id <%s>: Cannot find 
sender number for smsbox-id <%s>",
+               octstr_get_cstr(conn->id), octstr_get_cstr(msg->sms.service));
+       }
+    }
+    
+    /* Default rule for replacing MT sender number with default-sender-number 
*/
+    if (!replaced && octstr_len(conn->default_sender_number) > 0) {
+       octstr_destroy(msg->sms.sender);
+       msg->sms.sender = octstr_duplicate(conn->default_sender_number);
+       debug("smscconn", 0, "Replacing MT for smsc id <%s>: sender replaced by 
default <%s>",
+               octstr_get_cstr(conn->id), octstr_get_cstr(msg->sms.sender));
+    }
+
     /* if this a retry of splitted message, don't unify prefix and don't try 
to split */
     if (msg->sms.split_parts == NULL) {    
         /* normalize the destination number for this smsc */
@@ -742,6 +826,11 @@
     GET_OPTIONAL_REGEX(conn->denied_prefix_regex, "denied-prefix-regex");
     GET_OPTIONAL_REGEX(conn->preferred_prefix_regex, "preferred-prefix-regex");
 
+    octstr_destroy(conn->default_sender_number);
+    octstr_destroy(conn->sender_number);
+    dict_destroy(conn->sender_by_smsbox_id);
+    init_senders(conn, grp);
+
     octstr_destroy(conn->reroute_to_smsc);
     dict_destroy(conn->reroute_by_receiver);
     init_reroute(conn, grp);
Index: gw/smscconn_p.h
===================================================================
--- gw/smscconn_p.h     (revision 5195)
+++ gw/smscconn_p.h     (working copy)
@@ -191,6 +191,11 @@
 
     Octstr *our_host;   /* local device IP to bind for TCP communication */
 
+    /* Replacement of sender's number */
+    Octstr *default_sender_number; /* default MT sender number you want to 
disguise */
+    Octstr *sender_number; /* Same, but within specified smsbox-id: 
smsbox-id:number */
+    Dict *sender_by_smsbox_id;
+
     /* Our smsc specific log-file data */
     Octstr *log_file;
     long log_level;
Index: gwlib/cfg.def
===================================================================
--- gwlib/cfg.def       (revision 5195)
+++ gwlib/cfg.def       (working copy)
@@ -305,6 +305,7 @@
     OCTSTR(smsbox-id)
     OCTSTR(smsc-id)
     OCTSTR(shortcode)
+    OCTSTR(sender)
 )
 
 
@@ -435,6 +436,8 @@
     OCTSTR(generic-status-error)
     OCTSTR(generic-foreign-id-regex)
     OCTSTR(instances)
+    OCTSTR(default-sender-number)
+    OCTSTR(sender-number)
 )
 
 

Reply via email to