[PATCH] add support of smsc-id for smpp-tlv group

Alexander Malysh <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <[email protected]>
Hi list,

seems I was to lazy and didn't implement smsc-id support for smpp-tlv  
group :)
Attached is patch that corrects this.

The rule to look for smpp-tlv group is as follows:
1) by start we put smpp-tlv to smsc-id specific Dict if none given to  
default smsc-id.
      smsc-id may be a list splitted by ;
2) then if we need tlv by name/tag we look first for specific smsc-id  
Dict and if tlv
      not found for default smsc-id

Comments are welcome.

Thanks,
Alexander Malysh
smpp-tlv-smsc-id.diff (application/octet-stream, 14.7 KB)
diff --git a/doc/userguide/userguide.xml b/doc/userguide/userguide.xml
index 2573966..4f414aa 100644
--- a/doc/userguide/userguide.xml
+++ b/doc/userguide/userguide.xml
@@ -9638,6 +9638,7 @@ name = my_tlv_name
 tag = 0x1601
 type = octetstring
 length = 20
+smsc-id = a;b;c
 </programlisting>
 
 <informaltable frame="none">
@@ -9667,9 +9668,16 @@ length = 20
         Maximum data length expected in bytes. Must match SMPP specifications for the TLV (or be agreed with the SMSC operator).
      </entry></row>
 
+   <row><entry><literal>smsc-id</literal></entry>
+     <entry><literal>stringr</literal></entry>
+     <entry valign="bottom">
+        An optional smsc-id for which this TLV valid. If smsc-id is not given
+		then this TLV valid for all SMSCs.
+		To define list of smsc-id, just use ; as split char.
+     </entry></row>
 
-		</tbody>
-	</tgroup>
+	</tbody>
+  </tgroup>
 </informaltable>
       <sect2>
         <title>MO Messages</title>
diff --git a/gw/smsc/smpp_pdu.c b/gw/smsc/smpp_pdu.c
index add0253..bf55b61 100644
--- a/gw/smsc/smpp_pdu.c
+++ b/gw/smsc/smpp_pdu.c
@@ -69,7 +69,8 @@
 #define MIN_SMPP_PDU_LEN    (4*4)
 /* old value was (1024). We need more because message_payload can be up to 64K octets*/
 #define MAX_SMPP_PDU_LEN    (7424)
-
+/* we use ; in the middle because ; is split char in smsc-id and can'be in the smsc-id */
+#define DEFAULT_SMSC_ID "def;ault"
 
 struct smpp_tlv {
     Octstr *name;
@@ -78,9 +79,11 @@ struct smpp_tlv {
     enum { SMPP_TLV_OCTETS = 0, SMPP_TLV_NULTERMINATED = 1, SMPP_TLV_INTEGER = 2 } type;
 };
 
-
-static Dict *tlv_by_tag;
-static Dict *tlv_by_name;
+/* Dict(smsc_id, Dict(tag, tlv)) */
+static Dict *tlvs_by_tag;
+/* Dict(smsc_id, Dict(tag_name, tlv)) */
+static Dict *tlvs_by_name;
+static List *tlvs;
 static int initialized;
 
 
@@ -92,6 +95,57 @@ static void smpp_tlv_destroy(struct smpp_tlv *tlv)
     gw_free(tlv);
 }
 
+static struct smpp_tlv *smpp_tlv_get_by_name(Octstr *smsc_id, Octstr *name)
+{
+    struct smpp_tlv *res = NULL;
+    Dict *tmp_dict;
+
+    if (tlvs_by_name == NULL || name == NULL)
+        return NULL;
+
+    if (smsc_id != NULL) {
+        tmp_dict = dict_get(tlvs_by_name, smsc_id);
+        if (tmp_dict != NULL)
+            res = dict_get(tmp_dict, name);
+    }
+    if (res == NULL) {
+        /* try default smsc_id */
+        smsc_id = octstr_imm(DEFAULT_SMSC_ID);
+        tmp_dict = dict_get(tlvs_by_name, smsc_id);
+        if (tmp_dict != NULL)
+            res = dict_get(tmp_dict, name);
+    }
+    return res;
+}
+
+static struct smpp_tlv *smpp_tlv_get_by_tag(Octstr *smsc_id, long tag)
+{
+    struct smpp_tlv *res = NULL;
+    Dict *tmp_dict;
+    Octstr *tmp;
+
+    if (tlvs_by_tag == NULL)
+        return NULL;
+
+    tmp = octstr_format("%ld", tag);
+
+    if (smsc_id != NULL) {
+        tmp_dict = dict_get(tlvs_by_tag, smsc_id);
+        if (tmp_dict != NULL)
+            res = dict_get(tmp_dict, tmp);
+    }
+    if (res == NULL) {
+        /* try default smsc_id */
+        smsc_id = octstr_imm(DEFAULT_SMSC_ID);
+        tmp_dict = dict_get(tlvs_by_tag, smsc_id);
+        if (tmp_dict != NULL)
+            res = dict_get(tmp_dict, tmp);
+    }
+
+    octstr_destroy(tmp);
+
+    return res;
+}
 
 int smpp_pdu_init(Cfg *cfg)
 {
@@ -101,13 +155,14 @@ int smpp_pdu_init(Cfg *cfg)
     if (initialized)
         return 0;
 
-
     l = cfg_get_multi_group(cfg, octstr_imm("smpp-tlv"));
-    tlv_by_tag = dict_create(gwlist_len(l) > 0 ? gwlist_len(l) : 1, (void(*)(void*))smpp_tlv_destroy);
-    tlv_by_name = dict_create(gwlist_len(l) > 0 ? gwlist_len(l) : 1, NULL);
+    tlvs = gwlist_create();
+    tlvs_by_tag = dict_create(1024, (void(*)(void*))dict_destroy);
+    tlvs_by_name = dict_create(1024, (void(*)(void*))dict_destroy);
     while (l != NULL && (grp = gwlist_extract_first(l)) != NULL) {
         struct smpp_tlv *tlv;
-        Octstr *tmp;
+        Octstr *tmp, *smsc_id;
+        List *l2;
 
         tlv = gw_malloc(sizeof(*tlv));
         if ((tlv->name = cfg_get(grp, octstr_imm("name"))) == NULL) {
@@ -143,19 +198,51 @@ int smpp_pdu_init(Cfg *cfg)
             goto failed;
         }
         octstr_destroy(tmp);
-        /* put into dict */
-        if (!dict_put_once(tlv_by_name, tlv->name, tlv)) {
-            error(0, "SMPP: Double TLV name %s found.", octstr_get_cstr(tlv->name));
-            smpp_tlv_destroy(tlv);
-            goto failed;
+
+        /* put to all TLVs */
+        gwlist_produce(tlvs, tlv);
+
+        smsc_id = cfg_get(grp, octstr_imm("smsc-id"));
+        if (smsc_id != NULL) {
+            l2 = octstr_split(smsc_id, octstr_imm(";"));
+            octstr_destroy(smsc_id);
+        } else {
+            l2 = gwlist_create();
+            gwlist_produce(l2, octstr_create(DEFAULT_SMSC_ID));
         }
-        tmp = octstr_format("%ld", tlv->tag);
-        if (!dict_put_once(tlv_by_tag, tmp, tlv)) {
-            error(0, "SMPP: Double TLV tag %s found.", octstr_get_cstr(tmp));
+        while(l2 != NULL && (smsc_id = gwlist_extract_first(l2)) != NULL) {
+            Dict *tmp_dict;
+
+            debug("sms.smpp", 0, "adding smpp-tlv for smsc-id=%s", octstr_get_cstr(smsc_id));
+
+            tmp_dict = dict_get(tlvs_by_name, smsc_id);
+            if (tmp_dict == NULL) {
+                tmp_dict = dict_create(1024, NULL);
+                dict_put(tlvs_by_name, smsc_id, tmp_dict);
+            }
+            /* put into dict */
+            if (!dict_put_once(tmp_dict, tlv->name, tlv)) {
+                error(0, "SMPP: Double TLV name %s found.", octstr_get_cstr(tlv->name));
+                octstr_destroy(smsc_id);
+                goto failed;
+            }
+
+            tmp_dict = dict_get(tlvs_by_tag, smsc_id);
+            if (tmp_dict == NULL) {
+                tmp_dict = dict_create(1024, NULL);
+                dict_put(tlvs_by_tag, smsc_id, tmp_dict);
+            }
+            tmp = octstr_format("%ld", tlv->tag);
+            if (!dict_put_once(tmp_dict, tmp, tlv)) {
+                error(0, "SMPP: Double TLV tag %s found.", octstr_get_cstr(tmp));
+                octstr_destroy(tmp);
+                octstr_destroy(smsc_id);
+                goto failed;
+            }
             octstr_destroy(tmp);
-            goto failed;
+            octstr_destroy(smsc_id);
         }
-        octstr_destroy(tmp);
+        gwlist_destroy(l2, octstr_destroy_item);
     }
     gwlist_destroy(l, NULL);
 
@@ -163,8 +250,9 @@ int smpp_pdu_init(Cfg *cfg)
     return 0;
 
 failed:
-    dict_destroy(tlv_by_tag);
-    dict_destroy(tlv_by_name);
+    gwlist_destroy(tlvs, (void(*)(void*))smpp_tlv_destroy);
+    dict_destroy(tlvs_by_tag);
+    dict_destroy(tlvs_by_name);
     return -1;
 }
 
@@ -175,9 +263,11 @@ int smpp_pdu_shutdown(void)
         return 0;
 
     initialized = 0;
-    dict_destroy(tlv_by_tag);
-    dict_destroy(tlv_by_name);
-    tlv_by_tag = tlv_by_name = NULL;
+    gwlist_destroy(tlvs, (void(*)(void*))smpp_tlv_destroy);
+    tlvs = NULL;
+    dict_destroy(tlvs_by_tag);
+    dict_destroy(tlvs_by_name);
+    tlvs_by_tag = tlvs_by_name = NULL;
 
     return 0;
 }
@@ -287,7 +377,7 @@ void smpp_pdu_destroy(SMPP_PDU *pdu)
 }
 
 
-Octstr *smpp_pdu_pack(SMPP_PDU *pdu)
+Octstr *smpp_pdu_pack(Octstr *smsc_id, SMPP_PDU *pdu)
 {
     Octstr *os;
     Octstr *temp;
@@ -349,7 +439,7 @@ Octstr *smpp_pdu_pack(SMPP_PDU *pdu)
             struct smpp_tlv *tlv; \
             keys = dict_keys(p->tlv); \
             while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \
-                tlv = dict_get(tlv_by_name, key); \
+                tlv = smpp_tlv_get_by_name(smsc_id, key); \
                 if (tlv == NULL) { \
                     error(0, "SMPP: Unknown TLV `%s', don't send.", octstr_get_cstr(key)); \
                     octstr_destroy(key); \
@@ -424,7 +514,7 @@ Octstr *smpp_pdu_pack(SMPP_PDU *pdu)
 }
 
 
-SMPP_PDU *smpp_pdu_unpack(Octstr *data_without_len)
+SMPP_PDU *smpp_pdu_unpack(Octstr *smsc_id, Octstr *data_without_len)
 {
     SMPP_PDU *pdu;
     unsigned long type;
@@ -454,16 +544,13 @@ SMPP_PDU *smpp_pdu_unpack(Octstr *data_without_len)
         {   /* Read optional parameters */  \
             while (pos + 4 <= len) { \
                 struct smpp_tlv *tlv; \
-                Octstr *tmp; \
                 unsigned long opt_tag, opt_len; \
                 opt_tag = decode_integer(data_without_len, pos, 2); pos += 2; \
                 debug("sms.smpp", 0, "Optional parameter tag (0x%04lx)", opt_tag);  \
                 opt_len = decode_integer(data_without_len, pos, 2); pos += 2;  \
                 debug("sms.smpp", 0, "Optional parameter length read as %ld", opt_len); \
                 /* check configured TLVs */ \
-                tmp = octstr_format("%ld", opt_tag); \
-                tlv = dict_get(tlv_by_tag, tmp); \
-                octstr_destroy(tmp); \
+                tlv = smpp_tlv_get_by_tag(smsc_id, opt_tag); \
                 if (tlv != NULL) debug("sms.smpp", 0, "Found configured optional parameter `%s'", octstr_get_cstr(tlv->name));
     #define TLV_INTEGER(mname, octets) \
                 if (SMPP_##mname == opt_tag) { \
diff --git a/gw/smsc/smpp_pdu.h b/gw/smsc/smpp_pdu.h
index bd658bf..2143ebb 100644
--- a/gw/smsc/smpp_pdu.h
+++ b/gw/smsc/smpp_pdu.h
@@ -232,8 +232,8 @@ int smpp_pdu_shutdown(void);
 SMPP_PDU *smpp_pdu_create(unsigned long type, unsigned long seq_no);
 void smpp_pdu_destroy(SMPP_PDU *pdu);
 int smpp_pdu_is_valid(SMPP_PDU *pdu); /* XXX */
-Octstr *smpp_pdu_pack(SMPP_PDU *pdu);
-SMPP_PDU *smpp_pdu_unpack(Octstr *data_without_len);
+Octstr *smpp_pdu_pack(Octstr *smsc_id, SMPP_PDU *pdu);
+SMPP_PDU *smpp_pdu_unpack(Octstr *smsc_id, Octstr *data_without_len);
 void smpp_pdu_dump(SMPP_PDU *pdu);
 
 long smpp_pdu_read_len(Connection *conn);
diff --git a/gw/smsc/smsc_smpp.c b/gw/smsc/smsc_smpp.c
index a41dbf3..c25257a 100644
--- a/gw/smsc/smsc_smpp.c
+++ b/gw/smsc/smsc_smpp.c
@@ -328,7 +328,7 @@ static int read_pdu(SMPP *smpp, Connection *conn, long *len, SMPP_PDU **pdu)
     }
     *len = 0;
 
-    *pdu = smpp_pdu_unpack(os);
+    *pdu = smpp_pdu_unpack(smpp->conn->id, os);
     if (*pdu == NULL) {
         error(0, "SMPP[%s]: PDU unpacking failed.",
               octstr_get_cstr(smpp->conn->id));
@@ -970,7 +970,7 @@ static int send_enquire_link(SMPP *smpp, Connection *conn, long *last_sent)
 
     pdu = smpp_pdu_create(enquire_link, counter_increase(smpp->message_id_counter));
     dump_pdu("Sending enquire link:", smpp->conn->id, pdu);
-    os = smpp_pdu_pack(pdu);
+    os = smpp_pdu_pack(smpp->conn->id, pdu);
     if (os != NULL)
         ret = conn_write(conn, os); /* Write errors checked by caller. */
     else
@@ -990,7 +990,7 @@ static int send_gnack(SMPP *smpp, Connection *conn, long reason, unsigned long s
     pdu = smpp_pdu_create(generic_nack, seq_num);
     pdu->u.generic_nack.command_status = reason;
     dump_pdu("Sending generic_nack:", smpp->conn->id, pdu);
-    os = smpp_pdu_pack(pdu);
+    os = smpp_pdu_pack(smpp->conn->id, pdu);
     if (os != NULL)
         ret = conn_write(conn, os);
     else
@@ -1009,7 +1009,7 @@ static int send_unbind(SMPP *smpp, Connection *conn)
 
     pdu = smpp_pdu_create(unbind, counter_increase(smpp->message_id_counter));
     dump_pdu("Sending unbind:", smpp->conn->id, pdu);
-    os = smpp_pdu_pack(pdu);
+    os = smpp_pdu_pack(smpp->conn->id, pdu);
     if (os != NULL)
         ret = conn_write(conn, os);
     else
@@ -1027,7 +1027,7 @@ static int send_pdu(Connection *conn, Octstr *id, SMPP_PDU *pdu)
     int ret;
 
     dump_pdu("Sending PDU:", id, pdu);
-    os = smpp_pdu_pack(pdu);
+    os = smpp_pdu_pack(id, pdu);
     if (os) {
         /* Caller checks for write errors later */
         ret = conn_write(conn, os);
diff --git a/test/drive_smpp.c b/test/drive_smpp.c
index 2ae5ede..ff013b6 100644
--- a/test/drive_smpp.c
+++ b/test/drive_smpp.c
@@ -236,7 +236,7 @@ static void handle_pdu(ESME *esme, SMPP_PDU *pdu)
     	if (handlers[i].type == pdu->type) {
 	    resp = handlers[i].handler(esme, pdu);
 	    if (resp != NULL) {
-	    	os = smpp_pdu_pack(resp);
+	    	os = smpp_pdu_pack(NULL, resp);
 		conn_write(esme->conn, os);
 		octstr_destroy(os);
 		smpp_pdu_destroy(resp);
@@ -272,7 +272,7 @@ static void send_smpp_thread(void *arg)
         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");
-        os = smpp_pdu_pack(pdu);
+        os = smpp_pdu_pack(NULL, pdu);
         conn_write(esme->conn, os);
         octstr_destroy(os);
         smpp_pdu_destroy(pdu);
@@ -283,7 +283,7 @@ static void send_smpp_thread(void *arg)
 
         if ((id % enquire_interval) == 0) {
             pdu = smpp_pdu_create(enquire_link, counter_increase(message_id_counter));
-            os = smpp_pdu_pack(pdu);
+            os = smpp_pdu_pack(NULL, pdu);
             conn_write(esme->conn, os);
             octstr_destroy(os);
             smpp_pdu_destroy(pdu);
@@ -327,7 +327,7 @@ static void receive_smpp_thread(void *arg)
 	    os = smpp_pdu_read_data(esme->conn, len);
 	    if (os != NULL) {
     	    	len = 0;
-		pdu = smpp_pdu_unpack(os);
+		pdu = smpp_pdu_unpack(NULL, os);
 		if (pdu == NULL) {
 		    error(0, "PDU unpacking failed!");
 		    octstr_dump(os, 0);
diff --git a/test/drive_smpp.conf b/test/drive_smpp.conf
index 0e4e32a..a8cb552 100644
--- a/test/drive_smpp.conf
+++ b/test/drive_smpp.conf
@@ -23,6 +23,7 @@ name   = my_receipted_message_id
 tag    = 0x001E
 type   = octetstring
 length = 65
+#smsc-id = smpp
 
 group = smsbox
 bearerbox-host = 127.0.0.1
diff --git a/test/test_smsc.c b/test/test_smsc.c
index 92d2670..66ee306 100644
--- a/test/test_smsc.c
+++ b/test/test_smsc.c
@@ -313,7 +313,7 @@ static void smpp_emu_writer(void *arg)
     	pdu->u.deliver_sm.source_addr = octstr_create("123");
     	pdu->u.deliver_sm.destination_addr = octstr_create("456");
 	pdu->u.deliver_sm.short_message = octstr_format("%ld", e->time);
-	os = smpp_pdu_pack(pdu);
+	os = smpp_pdu_pack(NULL, pdu);
 	conn_write(p->conn, os);
 	octstr_destroy(os);
 	smpp_pdu_destroy(pdu);
@@ -372,7 +372,7 @@ static void smpp_emu_handle_pdu(struct smpp_emu_arg *p, SMPP_PDU *pdu)
     }
 		
     if (resp != NULL) {
-	os = smpp_pdu_pack(resp);
+	os = smpp_pdu_pack(NULL, resp);
 	conn_write(p->conn, os);
 	octstr_destroy(os);
 	smpp_pdu_destroy(resp);
@@ -408,7 +408,7 @@ static void smpp_emu_reader(void *arg)
 	    os = smpp_pdu_read_data(p->conn, len);
 	    if (os != NULL) {
     	    	len = 0;
-		pdu = smpp_pdu_unpack(os);
+		pdu = smpp_pdu_unpack(NULL, os);
 		if (pdu == NULL) {
 		    error(0, "PDU unpacking failed!");
 		    octstr_dump(os, 0);
@@ -541,7 +541,7 @@ static void smsc_emu_submit_ack(Event *e)
     Octstr *os;
 
     resp = smpp_pdu_create(submit_sm_resp, e->sequence_number);
-    os = smpp_pdu_pack(resp);
+    os = smpp_pdu_pack(NULL, resp);
     conn_write(e->conn, os);
     octstr_destroy(os);
     smpp_pdu_destroy(resp);
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.