Am 10.07.2014 19:59, schrieb marc-andre.gat...@gameloft.com:
Hi,

I'm using the meta-data to get the E50_HPLMN and set the E50_AC.

here's the patch to support that for the EMI protocol. If you guys have
a better way of doing so please feel free to give me a hint.

I'd like to apply the patch in the main repo asap.

Hi Mark,

thanks a lot for the patch, we appreciate your willingness to contribute.

In fact I had this being tackled in a more generic way, pulling the SMPP TLV code out of the SMPP specific modules into a generic gw/generic_tlv.[ch] module that can be used by any SMSC module.

Please find it attached to this mail for review and voting for commiting to svn trunk. (Though, this WILL go into svn post 1.4.4-stable release).

The SMPP module is modified accordingly, along with additions for CIMD2. I'm sure you will be able to add EMI/UCP too using the same function set.

Stipe

--
-------------------------------------------------------------------
Kölner Landstrasse 419
40589 Düsseldorf, NRW, Germany

Kannel Foundation                 tolj.org system architecture
http://www.kannel.org/            http://www.tolj.org/

mailto:stolj_{at}_kannel.org      mailto:st_{at}_tolj.org
-------------------------------------------------------------------
Index: gw/bb_smscconn.c
===================================================================
--- gw/bb_smscconn.c    (revision 5002)
+++ gw/bb_smscconn.c    (working copy)
@@ -92,7 +92,7 @@
 #include "bb_smscconn_cb.h"    /* callback functions for connections */
 #include "smscconn_p.h"        /* to access counters */
 
-#include "smsc/smpp_pdu.h"     /* access smpp_pdu_init/smpp_pdu_shutdown */
+#include "generic_tlv.h"       /* access generic_tlv_[init|shutdown] */
 
 /* passed from bearerbox core */
 
@@ -728,9 +728,8 @@
     if (handle_concatenated_mo)
         init_concat_handler();
 
-    /* initialize low level PDUs */
-    if (smpp_pdu_init(cfg) == -1)
-        panic(0, "Connot start with PDU init failed.");
+    /* initialize generic TLVs */
+    generic_tlv_init();
 
     smsc_groups = cfg_get_multi_group(cfg, octstr_imm("smsc"));
     gwlist_add_producer(smsc_list);
@@ -1076,8 +1075,8 @@
      */
     gwlist_remove_producer(incoming_sms);
 
-    /* shutdown low levele PDU things */
-    smpp_pdu_shutdown();
+    /* shutdown generic TLVs */
+    generic_tlv_shutdown();
 
     return 0;
 }
Index: gw/generic_tlv.c
===================================================================
--- gw/generic_tlv.c    (revision 0)
+++ gw/generic_tlv.c    (working copy)
@@ -0,0 +1,301 @@
+/* ==================================================================== 
+ * The Kannel Software License, Version 1.0 
+ * 
+ * Copyright (c) 2001-2012 Kannel Group  
+ * Copyright (c) 1998-2001 WapIT Ltd.   
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in 
+ *    the documentation and/or other materials provided with the 
+ *    distribution. 
+ * 
+ * 3. The end-user documentation included with the redistribution, 
+ *    if any, must include the following acknowledgment: 
+ *       "This product includes software developed by the 
+ *        Kannel Group (http://www.kannel.org/)." 
+ *    Alternately, this acknowledgment may appear in the software itself, 
+ *    if and wherever such third-party acknowledgments normally appear. 
+ * 
+ * 4. The names "Kannel" and "Kannel Group" must not be used to 
+ *    endorse or promote products derived from this software without 
+ *    prior written permission. For written permission, please  
+ *    contact o...@kannel.org. 
+ * 
+ * 5. Products derived from this software may not be called "Kannel", 
+ *    nor may "Kannel" appear in their name, without prior written 
+ *    permission of the Kannel Group. 
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * ==================================================================== 
+ * 
+ * This software consists of voluntary contributions made by many 
+ * individuals on behalf of the Kannel Group.  For more information on  
+ * the Kannel Group, please see <http://www.kannel.org/>. 
+ * 
+ * Portions of this software are based upon software originally written at  
+ * WapIT Ltd., Helsinki, Finland for the Kannel project.  
+ */ 
+
+/*
+ * generic_tlv.c - handle generic TLVs for several protocol types
+ *
+ * Alexander Malysh <amalysh at kannel.org>
+ * Stipe Tolj <stolj at kannel.org>
+ */
+
+#include <string.h>
+#include "generic_tlv.h"
+
+#define DEFAULT_SMSC_ID "def;ault"
+
+
+struct tlv_proto {
+       /* Dict(smsc_id, Dict(tag, tlv)) */
+       Dict *tlvs_by_tag;
+       /* Dict(smsc_id, Dict(tag_name, tlv)) */
+       Dict *tlvs_by_name;
+       List *tlvs;
+};
+
+static Dict *tlvs = NULL;
+
+
+static void generic_tlv_destroy(struct generic_tlv *tlv)
+{
+    if (tlv == NULL)
+        return;
+    octstr_destroy(tlv->name);
+    gw_free(tlv);
+}
+
+static void type_destroy(struct tlv_proto *type)
+{
+       if (type == NULL)
+               return;
+    gwlist_destroy(type->tlvs, (void(*)(void*))generic_tlv_destroy);
+    dict_destroy(type->tlvs_by_tag);
+    dict_destroy(type->tlvs_by_name);
+    gw_free(type);
+}
+
+Dict *generic_tlv_get_by_smsc(Octstr *type, Octstr *smsc_id)
+{
+       Dict *res = NULL;
+    struct tlv_proto *t;
+
+    if (tlvs == NULL || (t = dict_get(tlvs, type)) == NULL)
+        return NULL;
+
+    if (smsc_id != NULL) {
+        res = dict_get(t->tlvs_by_name, smsc_id);
+    }
+    if (res == NULL) {
+        /* try default smsc_id */
+        smsc_id = octstr_imm(DEFAULT_SMSC_ID);
+        res = dict_get(t->tlvs_by_name, smsc_id);
+    }
+    return res;
+}
+
+generic_tlv *generic_tlv_get_by_name(Octstr *type, Octstr *smsc_id, Octstr 
*name)
+{
+    struct generic_tlv *res = NULL;
+    struct tlv_proto *t;
+    Dict *tmp_dict;
+
+    if (tlvs == NULL || (t = dict_get(tlvs, type)) == NULL ||
+               t->tlvs_by_name == NULL || name == NULL)
+        return NULL;
+
+    if (smsc_id != NULL) {
+        tmp_dict = dict_get(t->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(t->tlvs_by_name, smsc_id);
+        if (tmp_dict != NULL)
+            res = dict_get(tmp_dict, name);
+    }
+    return res;
+}
+
+generic_tlv *generic_tlv_get_by_tag(Octstr *type, Octstr *smsc_id, long tag)
+{
+    struct generic_tlv *res = NULL;
+    struct tlv_proto *t;
+    Dict *tmp_dict;
+    Octstr *tmp;
+
+    if (tlvs == NULL || (t = dict_get(tlvs, type)) == NULL || t->tlvs_by_tag 
== NULL)
+        return NULL;
+
+    tmp = octstr_format("%ld", tag);
+
+    if (smsc_id != NULL) {
+        tmp_dict = dict_get(t->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(t->tlvs_by_tag, smsc_id);
+        if (tmp_dict != NULL)
+            res = dict_get(tmp_dict, tmp);
+    }
+
+    octstr_destroy(tmp);
+
+    return res;
+}
+
+int generic_tlv_init_smsc(Cfg *cfg, Octstr *context)
+{
+    CfgGroup *grp;
+    List *l;
+    struct tlv_proto *type;
+
+    if (tlvs == NULL)
+       tlvs = dict_create(16, (void(*)(void*))type_destroy);
+
+    /* if we have init'ed this type then bail out */
+    if (dict_get(tlvs, context) != NULL)
+       return 0;
+
+    l = cfg_get_multi_group(cfg, context);
+
+    type = gw_malloc(sizeof(*type));
+    type->tlvs = gwlist_create();
+    type->tlvs_by_tag = dict_create(1024, (void(*)(void*))dict_destroy);
+    type->tlvs_by_name = dict_create(1024, (void(*)(void*))dict_destroy);
+    while (l != NULL && (grp = gwlist_extract_first(l)) != NULL) {
+        struct generic_tlv *tlv;
+        Octstr *tmp, *smsc_id;
+        List *l2;
+
+        tlv = gw_malloc(sizeof(*tlv));
+        if ((tlv->name = cfg_get(grp, octstr_imm("name"))) == NULL) {
+            error(0, "Unable to get `name' for %s.", octstr_get_cstr(context));
+            generic_tlv_destroy(tlv);
+            goto failed;
+        }
+        if (cfg_get_integer(&tlv->tag, grp, octstr_imm("tag")) == -1) {
+            error(0, "Unable to get `tag' for %s.", octstr_get_cstr(context));
+            generic_tlv_destroy(tlv);
+            goto failed;
+        }
+        if (cfg_get_integer(&tlv->length, grp, octstr_imm("length")) == -1) {
+            error(0, "Unable to get `length' for %s.", 
octstr_get_cstr(context));
+            generic_tlv_destroy(tlv);
+            goto failed;
+        }
+        if ((tmp = cfg_get(grp, octstr_imm("type"))) == NULL) {
+            error(0, "Unable to get `type' for %s.", octstr_get_cstr(context));
+            generic_tlv_destroy(tlv);
+            goto failed;
+        }
+        if (octstr_str_case_compare(tmp, "octetstring") == 0)
+            tlv->type = TLV_OCTETS;
+        else if (octstr_str_case_compare(tmp, "nulterminated") == 0)
+            tlv->type = TLV_NULTERMINATED;
+        else if (octstr_str_case_compare(tmp, "integer") == 0)
+            tlv->type = TLV_INTEGER;
+        else {
+            error(0, "Unknown type for %s: `%s'", octstr_get_cstr(context), 
octstr_get_cstr(tmp));
+            octstr_destroy(tmp);
+            generic_tlv_destroy(tlv);
+            goto failed;
+        }
+        octstr_destroy(tmp);
+
+        /* put to all TLVs */
+        gwlist_produce(type->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));
+        }
+        while (l2 != NULL && (smsc_id = gwlist_extract_first(l2)) != NULL) {
+            Dict *tmp_dict;
+
+            debug("sms.tlv", 0, "Adding %s for smsc-id=%s",
+                 octstr_get_cstr(context), octstr_get_cstr(smsc_id));
+
+            tmp_dict = dict_get(type->tlvs_by_name, smsc_id);
+            if (tmp_dict == NULL) {
+                tmp_dict = dict_create(1024, NULL);
+                dict_put(type->tlvs_by_name, smsc_id, tmp_dict);
+            }
+            /* put into dict */
+            if (!dict_put_once(tmp_dict, tlv->name, tlv)) {
+                error(0, "Double TLV name %s found.", 
octstr_get_cstr(tlv->name));
+                octstr_destroy(smsc_id);
+                goto failed;
+            }
+
+            tmp_dict = dict_get(type->tlvs_by_tag, smsc_id);
+            if (tmp_dict == NULL) {
+                tmp_dict = dict_create(1024, NULL);
+                dict_put(type->tlvs_by_tag, smsc_id, tmp_dict);
+            }
+            tmp = octstr_format("%ld", tlv->tag);
+            if (!dict_put_once(tmp_dict, tmp, tlv)) {
+                error(0, "Double TLV tag %s found.", octstr_get_cstr(tmp));
+                gwlist_destroy(l2, octstr_destroy_item);
+                octstr_destroy(tmp);
+                octstr_destroy(smsc_id);
+                goto failed;
+            }
+            octstr_destroy(tmp);
+            octstr_destroy(smsc_id);
+        }
+        gwlist_destroy(l2, octstr_destroy_item);
+    }
+    gwlist_destroy(l, NULL);
+
+    dict_put_once(tlvs, context, type);
+
+    return 0;
+
+failed:
+       type_destroy(type);
+    return -1;
+}
+
+void generic_tlv_init(void)
+{
+       gw_assert(tlvs == NULL);
+       tlvs = dict_create(16, (void(*)(void*))type_destroy);
+}
+
+void generic_tlv_shutdown(void)
+{
+       gw_assert(tlvs != NULL);
+       dict_destroy(tlvs);
+}
+
Index: gw/generic_tlv.h
===================================================================
--- gw/generic_tlv.h    (revision 0)
+++ gw/generic_tlv.h    (working copy)
@@ -0,0 +1,101 @@
+/* ==================================================================== 
+ * The Kannel Software License, Version 1.0 
+ * 
+ * Copyright (c) 2001-2012 Kannel Group  
+ * Copyright (c) 1998-2001 WapIT Ltd.   
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in 
+ *    the documentation and/or other materials provided with the 
+ *    distribution. 
+ * 
+ * 3. The end-user documentation included with the redistribution, 
+ *    if any, must include the following acknowledgment: 
+ *       "This product includes software developed by the 
+ *        Kannel Group (http://www.kannel.org/)." 
+ *    Alternately, this acknowledgment may appear in the software itself, 
+ *    if and wherever such third-party acknowledgments normally appear. 
+ * 
+ * 4. The names "Kannel" and "Kannel Group" must not be used to 
+ *    endorse or promote products derived from this software without 
+ *    prior written permission. For written permission, please  
+ *    contact o...@kannel.org. 
+ * 
+ * 5. Products derived from this software may not be called "Kannel", 
+ *    nor may "Kannel" appear in their name, without prior written 
+ *    permission of the Kannel Group. 
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * ==================================================================== 
+ * 
+ * This software consists of voluntary contributions made by many 
+ * individuals on behalf of the Kannel Group.  For more information on  
+ * the Kannel Group, please see <http://www.kannel.org/>. 
+ * 
+ * Portions of this software are based upon software originally written at  
+ * WapIT Ltd., Helsinki, Finland for the Kannel project.  
+ */ 
+
+/*
+ * generic_tlv.h - handle generic TLVs for several protocol types
+ *
+ * Alexander Malysh <amalysh at kannel.org>
+ * Stipe Tolj <stolj at kannel.org>
+ */
+
+
+#ifndef GENERIC_TLV_H
+#define GENERIC_TLV_H
+
+#include "gwlib/gwlib.h"
+#include "gwlib/dict.h"
+
+enum tlv_type {
+       TLV_OCTETS = 0, TLV_NULTERMINATED = 1, TLV_INTEGER = 2
+};
+typedef enum tlv_type generic_tlv_type;
+
+struct generic_tlv {
+    Octstr *name;
+    long tag;
+    long length;
+    generic_tlv_type type;
+};
+typedef struct generic_tlv generic_tlv;
+
+
+void generic_tlv_init(void);
+void generic_tlv_shutdown(void);
+
+/* initialize all known TLVs for a specific protocol type */
+int generic_tlv_init_smsc(Cfg *cfg, Octstr *context);
+
+/* get the Dict of all TLVs based on protocol type and smsc-id */
+Dict *generic_tlv_get_by_smsc(Octstr *type, Octstr *smsc_id);
+
+/* get the TLV based on protocol type, the smsc-id and the TLV name */
+generic_tlv *generic_tlv_get_by_name(Octstr *type, Octstr *smsc_id, Octstr 
*name);
+
+/* get the TLV based on protocol type, the smsc-id and the TLV tag */
+generic_tlv *generic_tlv_get_by_tag(Octstr *type, Octstr *smsc_id, long tag);
+
+
+#endif /* GENERIC_TLV_H */
Index: gw/smsc/smpp_pdu.c
===================================================================
--- gw/smsc/smpp_pdu.c  (revision 4992)
+++ gw/smsc/smpp_pdu.c  (working copy)
@@ -65,215 +65,13 @@
 
 #include <string.h>
 #include "smpp_pdu.h"
+#include "generic_tlv.h"
 
 #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't be in 
the smsc-id */
-#define DEFAULT_SMSC_ID "def;ault"
 
-struct smpp_tlv {
-    Octstr *name;
-    long tag;
-    long length;
-    enum { SMPP_TLV_OCTETS = 0, SMPP_TLV_NULTERMINATED = 1, SMPP_TLV_INTEGER = 
2 } type;
-};
 
-/* 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;
-
-
-static void smpp_tlv_destroy(struct smpp_tlv *tlv)
-{
-    if (tlv == NULL)
-        return;
-    octstr_destroy(tlv->name);
-    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)
-{
-    CfgGroup *grp;
-    List *l;
-
-    if (initialized)
-        return 0;
-
-    l = cfg_get_multi_group(cfg, octstr_imm("smpp-tlv"));
-    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, *smsc_id;
-        List *l2;
-
-        tlv = gw_malloc(sizeof(*tlv));
-        if ((tlv->name = cfg_get(grp, octstr_imm("name"))) == NULL) {
-            error(0, "SMPP: Unable to get name for smpp-tlv.");
-            smpp_tlv_destroy(tlv);
-            goto failed;
-        }
-        if (cfg_get_integer(&tlv->tag, grp, octstr_imm("tag")) == -1) {
-            error(0, "SMPP: Unable to get tag for smpp-tlv.");
-            smpp_tlv_destroy(tlv);
-            goto failed;
-        }
-        if (cfg_get_integer(&tlv->length, grp, octstr_imm("length")) == -1) {
-            error(0, "SMPP: Unable to get length for smpp-tlv.");
-            smpp_tlv_destroy(tlv);
-            goto failed;
-        }
-        if ((tmp = cfg_get(grp, octstr_imm("type"))) == NULL) {
-            error(0, "SMPP: Unable to get type for smpp-tlv.");
-            smpp_tlv_destroy(tlv);
-            goto failed;
-        }
-        if (octstr_str_case_compare(tmp, "octetstring") == 0)
-            tlv->type = SMPP_TLV_OCTETS;
-        else if (octstr_str_case_compare(tmp, "nulterminated") == 0)
-            tlv->type = SMPP_TLV_NULTERMINATED;
-        else if (octstr_str_case_compare(tmp, "integer") == 0)
-            tlv->type = SMPP_TLV_INTEGER;
-        else {
-            error(0, "SMPP: Unknown type for smpp-tlv: `%s'", 
octstr_get_cstr(tmp));
-            octstr_destroy(tmp);
-            smpp_tlv_destroy(tlv);
-            goto failed;
-        }
-        octstr_destroy(tmp);
-
-        /* 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));
-        }
-        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));
-                gwlist_destroy(l2, octstr_destroy_item);
-                octstr_destroy(tmp);
-                octstr_destroy(smsc_id);
-                goto failed;
-            }
-            octstr_destroy(tmp);
-            octstr_destroy(smsc_id);
-        }
-        gwlist_destroy(l2, octstr_destroy_item);
-    }
-    gwlist_destroy(l, NULL);
-
-    initialized = 1;
-    return 0;
-
-failed:
-    gwlist_destroy(tlvs, (void(*)(void*))smpp_tlv_destroy);
-    dict_destroy(tlvs_by_tag);
-    dict_destroy(tlvs_by_name);
-    return -1;
-}
-
-
-int smpp_pdu_shutdown(void)
-{
-    if (initialized == 0)
-        return 0;
-
-    initialized = 0;
-    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;
-}
-
-
 static long decode_integer(Octstr *os, long pos, int octets)
 {
     unsigned long u;
@@ -373,6 +171,7 @@
     #include "smpp_pdu.def"
     default:
         error(0, "Unknown SMPP_PDU type, internal error while destroying.");
+        break;
     }
     gw_free(pdu);
 }
@@ -405,6 +204,7 @@
     #include "smpp_pdu.def"
     default:
        error(0, "Unknown SMPP_PDU type, internal error while packing.");
+       break;
     }
 
     switch (pdu->type) {
@@ -437,25 +237,25 @@
         if (p->tlv != NULL) { \
             Octstr *key; \
             List *keys; \
-            struct smpp_tlv *tlv; \
+            generic_tlv *tlv; \
             keys = dict_keys(p->tlv); \
-            while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) 
{ \
-                tlv = smpp_tlv_get_by_name(smsc_id, key); \
+            while (keys != NULL && (key = gwlist_extract_first(keys)) != NULL) 
{ \
+                tlv = generic_tlv_get_by_name(octstr_imm("smpp-tlv"), smsc_id, 
key); \
                 if (tlv == NULL) { \
                     error(0, "SMPP: Unknown TLV `%s', don't send.", 
octstr_get_cstr(key)); \
                     octstr_destroy(key); \
                     continue; \
                 } \
-                switch(tlv->type) { \
-                case SMPP_TLV_INTEGER: { \
+                switch (tlv->type) { \
+                case TLV_INTEGER: { \
                     long val = atol(octstr_get_cstr(dict_get(p->tlv, key))); \
                     append_encoded_integer(os, tlv->tag, 2); \
                     append_encoded_integer(os, tlv->length, 2); \
                     append_encoded_integer(os, val, tlv->length); \
                     break; \
                 } \
-                case SMPP_TLV_OCTETS: \
-                case SMPP_TLV_NULTERMINATED: { \
+                case TLV_OCTETS: \
+                case TLV_NULTERMINATED: { \
                     Octstr *val = dict_get(p->tlv, key); \
                     unsigned long len = octstr_len(val); \
                     if (len > tlv->length) { \
@@ -465,12 +265,12 @@
                         continue; \
                     } \
                     append_encoded_integer(os, tlv->tag, 2); \
-                    if (tlv->type == SMPP_TLV_NULTERMINATED) \
+                    if (tlv->type == TLV_NULTERMINATED) \
                         append_encoded_integer(os, len + 1, 2); \
                     else \
                         append_encoded_integer(os, len, 2); \
                     octstr_append(os, val); \
-                    if (tlv->type == SMPP_TLV_NULTERMINATED) \
+                    if (tlv->type == TLV_NULTERMINATED) \
                         octstr_append_char(os, '\0'); \
                     break; \
                 } \
@@ -504,6 +304,7 @@
     #include "smpp_pdu.def"
     default:
         error(0, "Unknown SMPP_PDU type, internal error while packing.");
+        break;
     }
 
     temp = octstr_create("");
@@ -544,14 +345,14 @@
     #define OPTIONAL_BEGIN  \
         {   /* Read optional parameters */  \
             while (pos + 4 <= len) { \
-                struct smpp_tlv *tlv; \
+                generic_tlv *tlv; \
                 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 */ \
-                tlv = smpp_tlv_get_by_tag(smsc_id, opt_tag); \
+                tlv = generic_tlv_get_by_tag(octstr_imm("smpp-tlv"), 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) { \
@@ -601,7 +402,7 @@
                             continue; \
                         } \
                         switch (tlv->type) { \
-                        case SMPP_TLV_INTEGER: { \
+                        case TLV_INTEGER: { \
                             long val_i; \
                             if ((val_i = decode_integer(data_without_len, pos, 
opt_len)) == -1) \
                                 goto err; \
@@ -610,13 +411,13 @@
                             pos += opt_len; \
                             break; \
                         } \
-                        case SMPP_TLV_OCTETS: { \
+                        case TLV_OCTETS: { \
                             val = octstr_copy(data_without_len, pos, opt_len); 
\
                             dict_put(p->tlv, tlv->name, val); \
                             pos += opt_len; \
                             break; \
                         } \
-                        case SMPP_TLV_NULTERMINATED: { \
+                        case TLV_NULTERMINATED: { \
                             if (copy_until_nul(octstr_get_cstr(tlv->name), 
data_without_len, &pos, opt_len, &val) == 0) \
                                 dict_put(p->tlv, tlv->name, val); \
                             break; \
@@ -662,6 +463,7 @@
     #include "smpp_pdu.def"
     default:
        error(0, "Unknown SMPP_PDU type, internal error while unpacking.");
+       break;
     }
 
     return pdu;
Index: gw/smsc/smsc_cimd2.c
===================================================================
--- gw/smsc/smsc_cimd2.c        (revision 4992)
+++ gw/smsc/smsc_cimd2.c        (working copy)
@@ -59,6 +59,7 @@
  * Author: Richard Braakman
  *
  * Upgrade to SMSCConn API: 2002 Kalle Marjola / 2003 Angel Fradejas
+ * Added meta-data support for optional parameters, 2012, Stipe Tolj
  */
 
 /* TODO: Check checksums on incoming packets */
@@ -89,10 +90,11 @@
 #include "smscconn.h"
 #include "smscconn_p.h"
 #include "bb_smscconn_cb.h"
-
 #include "shared.h"
 #include "sms.h"
 #include "dlr.h"
+#include "meta_data.h"
+#include "generic_tlv.h"
 
 
 typedef struct privdata {
@@ -1326,6 +1328,7 @@
     long truncated;
     int dcs = 0;
     int setvalidity = 0;
+    Dict *tlvs;
 
     gw_assert(msg != NULL);
     gw_assert(msg->type == sms);
@@ -1499,6 +1502,48 @@
                 spaceleft);
     }
 
+    /* add optional parameters via meta-data */
+    tlvs = meta_data_get_values(msg->sms.meta_data, "cimd2");
+    if (tlvs != NULL) {
+        Octstr *key;
+        List *keys;
+        generic_tlv *tlv;
+        keys = dict_keys(tlvs);
+        while (keys != NULL && (key = gwlist_extract_first(keys)) != NULL) {
+            tlv = generic_tlv_get_by_name(octstr_imm("cimd2-tlv"), conn->id, 
key);
+            if (tlv == NULL) {
+                error(0, "Unknown TLV `%s', don't send.", 
octstr_get_cstr(key));
+                octstr_destroy(key);
+                continue;
+            }
+            switch (tlv->type) {
+            case TLV_INTEGER: {
+                long val = atol(octstr_get_cstr(dict_get(tlvs, key)));
+               packet_add_int_parm(packet, tlv->tag, val, conn);
+               }
+                break;
+            case TLV_OCTETS:
+            case TLV_NULTERMINATED: {
+                Octstr *val = dict_get(tlvs, key);
+                unsigned long len = octstr_len(val);
+                if (len > tlv->length) {
+                    error(0, "Optional field (%s) with invalid length (%ld) 
(should be %ld) dropped.",
+                          octstr_get_cstr(key), len, tlv->length);
+                    octstr_destroy(key);
+                    continue;
+                }
+               packet_add_parm(packet, P_STRING, tlv->tag, val, conn);
+                break;
+            }
+            default:
+                panic(0, "Internal error, unknown configured TLV type %d.", 
tlv->type);
+                break;
+            }
+            octstr_destroy(key);
+        }
+        gwlist_destroy(keys, octstr_destroy_item);
+    }
+
     octstr_destroy(text);
     return packet;
 }
@@ -1593,6 +1638,7 @@
     Octstr *UDH = NULL;
     Octstr *text = NULL;
     int DCS;
+    Dict *tlvs = NULL, *t;
 
     /* See GSM 03.38.  The bit patterns we can handle are:
      *   000xyyxx  Uncompressed text, yy indicates alphabet.
@@ -1659,6 +1705,49 @@
         message->sms.udhdata = UDH;
     }
     message->sms.msgdata = text;
+
+    /* add optional parameters via meta-data */
+    t = generic_tlv_get_by_smsc(octstr_imm("cimd2-tlv"), conn->id);
+    if (t != NULL) {
+        Octstr *key;
+        List *keys;
+        generic_tlv *tlv;
+        keys = dict_keys(t);
+        tlvs = dict_create(16, octstr_destroy_item);
+        while (keys != NULL && (key = gwlist_extract_first(keys)) != NULL) {
+            tlv = dict_get(t, key);
+            if (tlv == NULL) {
+                octstr_destroy(key);
+                continue;
+            }
+            switch (tlv->type) {
+            case TLV_INTEGER: {
+                int val = packet_get_int_parm(request, tlv->tag);
+                if (val != INT_MIN)
+                    dict_put(tlvs, tlv->name, octstr_format("%ld", val));
+               }
+                break;
+            case TLV_OCTETS:
+            case TLV_NULTERMINATED: {
+                Octstr *val = packet_get_string_parm(request, tlv->tag);
+                if (val != NULL)
+                       dict_put(tlvs, tlv->name, val);
+               }
+               break;
+            default:
+                panic(0, "Internal error, unknown configured TLV type %d.", 
tlv->type);
+                break;
+            }
+            octstr_destroy(key);
+        }
+        gwlist_destroy(keys, octstr_destroy_item);
+
+        if (message->sms.meta_data == NULL)
+            message->sms.meta_data = octstr_create("");
+        meta_data_set_values(message->sms.meta_data, tlvs, "cimd2", 1);
+        dict_destroy(tlvs);
+    }
+
     return message;
 
 error:
@@ -2322,6 +2411,9 @@
     int ok;
     int maxlen;
 
+    if (generic_tlv_init_smsc(cfg_get_config(grp), octstr_imm("cimd2-tlv")) == 
-1)
+        panic(0, "Cannot start with CIMD2 TLV init failed.");
+
     pdata = gw_malloc(sizeof(PrivData));
     conn->data = pdata;
     pdata->conn = conn;
Index: gw/smsc/smsc_smpp.c
===================================================================
--- gw/smsc/smsc_smpp.c (revision 5006)
+++ gw/smsc/smsc_smpp.c (working copy)
@@ -2299,6 +2299,9 @@
     transceiver_mode = 0;
     autodetect_addr = 1;
 
+    if (generic_tlv_init_smsc(cfg_get_config(grp), octstr_imm("smpp-tlv")) == 
-1)
+        panic(0, "Cannot start with SMPP TLV init failed.");
+
     host = cfg_get(grp, octstr_imm("host"));
     if (cfg_get_integer(&port, grp, octstr_imm("port")) == -1)
         port = 0;
Index: gwlib/cfg.c
===================================================================
--- gwlib/cfg.c (revision 4986)
+++ gwlib/cfg.c (working copy)
@@ -70,19 +70,27 @@
 #include <dirent.h>
 #include <errno.h>
 
+struct Cfg {
+    Octstr *filename;
+    Dict *single_groups;
+    Dict *multi_groups;
+};
+
 struct CfgGroup {
+       struct Cfg *cfg;
     Octstr *name;
     Dict *vars;
     Octstr *configfile; 
-    long line; 
+    long line;
 };
 
 
-static CfgGroup *create_group(void)
+static CfgGroup *create_group(Cfg *cfg)
 {
     CfgGroup *grp;
     
     grp = gw_malloc(sizeof(*grp));
+    grp->cfg = cfg;
     grp->name = NULL;
     grp->vars = dict_create(64, octstr_destroy_item);
     grp->configfile = NULL; 
@@ -95,11 +103,11 @@
     CfgGroup *grp;
     
     if (arg != NULL) {
-       grp = arg;
-       octstr_destroy(grp->name);
-       octstr_destroy(grp->configfile); 
-       dict_destroy(grp->vars);
-       gw_free(grp);
+       grp = arg;
+       octstr_destroy(grp->name);
+       octstr_destroy(grp->configfile);
+       dict_destroy(grp->vars);
+       gw_free(grp);
     }
 }
 
@@ -146,13 +154,6 @@
 }
 
 
-struct Cfg {
-    Octstr *filename;
-    Dict *single_groups;
-    Dict *multi_groups;
-};
-
-
 /********************************************************************
  * Section providing hooks to external modules to apply their specific
  * is_allowed_in_group() and is_single_group() with their own
@@ -585,7 +586,7 @@
                 parse_value(value); 
  
                if (grp == NULL)
-                    grp = create_group(); 
+                    grp = create_group(cfg);
                  
                 if (grp->configfile != NULL) {
                     octstr_destroy(grp->configfile); 
@@ -652,7 +653,12 @@
     return octstr_duplicate(grp->configfile);
 }
 
+Cfg *cfg_get_config(CfgGroup *grp)
+{
+    return grp->cfg;
+}
 
+
 Octstr *cfg_get_real(CfgGroup *grp, Octstr *varname, const char *file, 
                     long line, const char *func)
 {
Index: gwlib/cfg.h
===================================================================
--- gwlib/cfg.h (revision 4986)
+++ gwlib/cfg.h (working copy)
@@ -79,6 +79,7 @@
 List *cfg_get_multi_group(Cfg *cfg, Octstr *name);
 Octstr *cfg_get_group_name(CfgGroup *grp);
 Octstr *cfg_get_configfile(CfgGroup *grp);
+Cfg *cfg_get_config(CfgGroup *grp);
 
 Octstr *cfg_get_real(CfgGroup *grp, Octstr *varname, const char *file,
                     long line, const char *func);

Reply via email to