core: internal module interface changes
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Wed, 4 Aug 2010 13:38:58 +0000 (15:38 +0200)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Wed, 4 Aug 2010 13:38:58 +0000 (15:38 +0200)
Use a new internal representation for the module interface, that
combines the ser & kamailio module interfaces plus some extra
internal stuff.
This allows using extra flags (e.g. the new internal fixup_flags)
and also simplifies all the functions dealing with the module
interface or cmd_exports (since now there is a single internal
interface there's no need to check its version and access it
differently depending on it).
The ser or kamailio module interfaces are converted to the new
sr31 mod interface when the modules are loaded
(register_module()).

action.c
cfg.y
modparam.c
route.c
sr_module.c
sr_module.h

index 283dbe0..e8a80e5 100644 (file)
--- a/action.c
+++ b/action.c
@@ -172,9 +172,9 @@ struct onsend_info* p_onsend=0; /* onsend route send info */
                                (dst)[i+2].u.string = s.s; \
                                (dst)[i+2].u.str.len = s.len; \
                                rval_destroy(rv); \
-                               if ((cmd)->c.fixup && \
-                                               (long)(cmd)->c.fixup & FIXUP_F_FPARAM_RVE) { \
-                                       call_fixup((cmd)->c.fixup, &(dst)[i+2].u.data, i+1); \
+                               if ((cmd)->fixup && \
+                                               (cmd)->fixup_flags & FIXUP_F_FPARAM_RVE) { \
+                                       call_fixup((cmd)->fixup, &(dst)[i+2].u.data, i+1); \
                                        if ((dst)[i+2].u.data != s.s) \
                                                (dst)[i+2].type = FPARAM_DYN_ST; \
                                } \
@@ -201,14 +201,14 @@ struct onsend_info* p_onsend=0; /* onsend route send info */
 #define MODF_CALL(f_type, h, msg, src, ...) \
        do { \
                cmd=(src)[0].u.data; \
-               ret=((f_type)cmd->c.function)((msg), __VAR_ARGS__); \
+               ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
                MODF_HANDLE_RETCODE(h, ret); \
        } while (0)
 #else  /* ! __SUNPRO_C  (gcc, icc a.s.o) */
 #define MODF_CALL(f_type, h, msg, src, params...) \
        do { \
                cmd=(src)[0].u.data; \
-               ret=((f_type)cmd->c.function)((msg), ## params ); \
+               ret=((f_type)cmd->function)((msg), ## params ); \
                MODF_HANDLE_RETCODE(h, ret); \
        } while (0)
 #endif /* __SUNPRO_C */
@@ -235,7 +235,7 @@ struct onsend_info* p_onsend=0; /* onsend route send info */
        do { \
                cmd=(src)[0].u.data; \
                MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
-               ret=((f_type)cmd->c.function)((msg), __VAR_ARGS__); \
+               ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
                MODF_HANDLE_RETCODE(h, ret); \
                /* free strings allocated by us or fixups */ \
                MODF_RVE_PARAM_FREE(src, dst); \
@@ -245,7 +245,7 @@ struct onsend_info* p_onsend=0; /* onsend route send info */
        do { \
                cmd=(src)[0].u.data; \
                MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
-               ret=((f_type)cmd->c.function)((msg), ## params ); \
+               ret=((f_type)cmd->function)((msg), ## params ); \
                MODF_HANDLE_RETCODE(h, ret); \
                /* free strings allocated by us or fixups */ \
                MODF_RVE_PARAM_FREE(src, dst); \
@@ -263,7 +263,7 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
        struct dest_info dst;
        char* tmp;
        char *new_uri, *end, *crt;
-       union cmd_export_u* cmd;
+       sr31_cmd_export_t* cmd;
        int len;
        int user;
        struct sip_uri uri, next_hop;
@@ -1484,11 +1484,9 @@ end:
        /* process module onbreak handlers if present */
        if (h->rec_lev==0 && ret==0)
                for (mod=modules;mod;mod=mod->next)
-                       if ((mod->mod_interface_ver==0) && mod->exports && 
-                                       mod->exports->v0.onbreak_f) {
-                               mod->exports->v0.onbreak_f( msg );
-                               DBG("DEBUG: %s onbreak handler called\n",
-                                               mod->exports->c.name);
+                       if (mod->exports.onbreak_f) {
+                               mod->exports.onbreak_f( msg );
+                               DBG("DEBUG: %s onbreak handler called\n", mod->exports.name);
                        }
        return ret;
 
diff --git a/cfg.y b/cfg.y
index 8074ad8..f97c408 100644 (file)
--- a/cfg.y
+++ b/cfg.y
@@ -2697,7 +2697,7 @@ rval: intno                       {$$=mk_rve_rval(RV_INT, (void*)$1); }
 
 
 rve_un_op: NOT { $$=RVE_LNOT_OP; }
-               |  MINUS %prec UNARY    { $$=RVE_UMINUS_OP; } 
+               |  MINUS %prec UNARY    { $$=RVE_UMINUS_OP; }
                /* TODO: RVE_BOOL_OP, RVE_NOT_OP? */
        ;
 
@@ -3704,7 +3704,7 @@ static int case_check_default(struct case_stms* stms)
  */
 static int mod_f_params_pre_fixup(struct action* a)
 {
-       union cmd_export_u* cmd_exp;
+       sr31_cmd_export_t* cmd_exp;
        action_u_t* params;
        int param_no;
        struct rval_expr* rve;
@@ -3716,7 +3716,7 @@ static int mod_f_params_pre_fixup(struct action* a)
        param_no = a->val[1].u.number;
        params = &a->val[2];
        
-       switch(cmd_exp->c.param_no) {
+       switch(cmd_exp->param_no) {
                case 0:
                        a->type = MODULE0_T;
                        break;
@@ -3743,24 +3743,22 @@ static int mod_f_params_pre_fixup(struct action* a)
                        break;
                default:
                        yyerror("function %s: bad definition"
-                                       " (invalid number of parameters)", cmd_exp->c.name);
+                                       " (invalid number of parameters)", cmd_exp->name);
                        return -1;
        }
        
-       if ( cmd_exp->c.fixup) {
-               if (is_fparam_rve_fixup(cmd_exp->c.fixup))
+       if ( cmd_exp->fixup) {
+               if (is_fparam_rve_fixup(cmd_exp->fixup))
                        /* mark known fparam rve safe fixups */
-                       cmd_exp->c.fixup  = (fixup_function)
-                                                                       ((unsigned long) cmd_exp->c.fixup |
-                                                                                FIXUP_F_FPARAM_RVE);
-               else if (!((unsigned long)cmd_exp->c.fixup & FIXUP_F_FPARAM_RVE)) {
+                       cmd_exp->fixup_flags  |= FIXUP_F_FPARAM_RVE;
+               else if (!(cmd_exp->fixup_flags & FIXUP_F_FPARAM_RVE)) {
                        /* v0 or v1 functions that have fixups need constant,
                          string params.*/
                        for (r=0; r < param_no; r++) {
                                rve=params[r].u.data;
                                if (!rve_is_constant(rve)) {
                                        yyerror_at(&rve->fpos, "function %s: parameter %d is not"
-                                                               " constant\n", cmd_exp->c.name, r+1);
+                                                               " constant\n", cmd_exp->name, r+1);
                                        return -1;
                                }
                                if ((rv = rval_expr_eval(0, 0, rve)) == 0 ||
@@ -3768,7 +3766,7 @@ static int mod_f_params_pre_fixup(struct action* a)
                                        /* out of mem or bug ? */
                                        rval_destroy(rv);
                                        yyerror_at(&rve->fpos, "function %s: bad parameter %d"
-                                                                       " expression\n", cmd_exp->c.name, r+1);
+                                                                       " expression\n", cmd_exp->name, r+1);
                                        return -1;
                                }
                                rval_destroy(rv);
@@ -3796,12 +3794,10 @@ static int mod_f_params_pre_fixup(struct action* a)
  */
 static void free_mod_func_action(struct action* a)
 {
-       union cmd_export_u* cmd_exp;
        action_u_t* params;
        int param_no;
        int r;
        
-       cmd_exp = a->val[0].u.data;
        param_no = a->val[1].u.number;
        params = &a->val[2];
        
index ca34bef..ffc3125 100644 (file)
@@ -91,9 +91,9 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
 
        mod_found = 0;
        for(t = modules; t; t = t->next) {
-               if (regexec(&preg, t->exports->c.name, 0, 0, 0) == 0) {
+               if (regexec(&preg, t->exports.name, 0, 0, 0) == 0) {
                        DBG("set_mod_param_regex: '%s' matches module '%s'\n",
-                                       regex, t->exports->c.name);
+                                       regex, t->exports.name);
                        mod_found = 1;
                        /* PARAM_STR (PARAM_STRING) may be assigned also to PARAM_STRING(PARAM_STR) so let get both module param */
                        ptr = find_param_export(t, name, type | ((type & (PARAM_STR|PARAM_STRING))?PARAM_STR|PARAM_STRING:0), &param_type);
@@ -109,7 +109,7 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
                                        val2 = val;
                                }
                                DBG("set_mod_param_regex: found <%s> in module %s [%s]\n",
-                                               name, t->exports->c.name, t->path);
+                                               name, t->exports.name, t->path);
                                if (param_type & PARAM_USE_FUNC) {
                                        if ( ((param_func_t)(ptr))(param_type, val2) < 0) {
                                                regfree(&preg);
@@ -147,7 +147,7 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
                        }
                        else {
                                LOG(L_ERR, "set_mod_param_regex: parameter <%s> not found in"
-                                                       " module <%s>\n", name, t->exports->c.name);
+                                                       " module <%s>\n", name, t->exports.name);
                                regfree(&preg);
                                pkg_free(reg);
                                return -3;
diff --git a/route.c b/route.c
index 25eb512..e603030 100644 (file)
--- a/route.c
+++ b/route.c
@@ -634,7 +634,7 @@ int fix_actions(struct action* a)
        void *tmp_p;
        int ret;
        int i;
-       union cmd_export_u* cmd;
+       sr31_cmd_export_t* cmd;
        str s;
        struct hostent* he;
        struct ip_addr ip;
@@ -920,9 +920,9 @@ int fix_actions(struct action* a)
                                cmd = t->val[0].u.data;
                                rve_param_no = 0;
                                if (cmd) {
-                                       DBG("fixing %s()\n", cmd->c.name);
+                                       DBG("fixing %s()\n", cmd->name);
                                        if (t->val[1].u.number==0) {
-                                               ret = call_fixup(cmd->c.fixup, 0, 0);
+                                               ret = call_fixup(cmd->fixup, 0, 0);
                                                if (ret < 0)
                                                        goto error;
                                        }
@@ -948,7 +948,7 @@ int fix_actions(struct action* a)
                                                                /* len is not used for now */
                                                                t->val[i+2].u.str.len = s.len;
                                                                tmp_p = t->val[i+2].u.data;
-                                                               ret = call_fixup(cmd->c.fixup,
+                                                               ret = call_fixup(cmd->fixup,
                                                                                                &t->val[i+2].u.data, i+1);
                                                                if (t->val[i+2].u.data != tmp_p)
                                                                        t->val[i+2].type = MODFIXUP_ST;
@@ -967,7 +967,7 @@ int fix_actions(struct action* a)
                                                        }
                                                } else  if (t->val[i+2].type == STRING_ST) {
                                                        tmp_p = t->val[i+2].u.data;
-                                                       ret = call_fixup(cmd->c.fixup,
+                                                       ret = call_fixup(cmd->fixup,
                                                                                        &t->val[i+2].u.data, i+1);
                                                        if (t->val[i+2].u.data != tmp_p)
                                                                t->val[i+2].type = MODFIXUP_ST;
@@ -984,12 +984,11 @@ int fix_actions(struct action* a)
                                           (constant RVEs), MODFIXUP_ST (fixed up)
                                           or RVE_ST (non-ct RVEs) */
                                        if (rve_param_no) { /* we have to fix the type */
-                                               if (cmd->c.fixup &&
-                                                       !((unsigned long)cmd->c.fixup &
-                                                               FIXUP_F_FPARAM_RVE)) {
+                                               if (cmd->fixup &&
+                                                       !(cmd->fixup_flags & FIXUP_F_FPARAM_RVE)) {
                                                        BUG("non-ct RVEs (%d) in module function call"
                                                                        "that does not support them (%s)\n",
-                                                                       rve_param_no, cmd->c.name);
+                                                                       rve_param_no, cmd->name);
                                                        ret = E_BUG;
                                                        goto error;
                                                }
index eb9b54a..5089f5f 100644 (file)
@@ -150,6 +150,66 @@ int register_builtin_modules()
 
 
 
+/** convert cmd exports to current format.
+  * @param ver - module interface versions (0 == ser, 1 == kam).
+  * @param src - null terminated array of cmd exports
+  *              (either ser_cmd_export_t or kam_cmd_export_t, depending
+  *               on ver).
+  * @param mod - pointer to module exports structure.
+  * @return - pkg_malloc'ed null terminated sr_cmd_export_v31_t array with
+  *           the converted cmd exports  or 0 on error.
+  */
+static sr31_cmd_export_t* sr_cmd_exports_convert(unsigned ver,
+                                                                                                       void* src, void* mod)
+{
+       int i, n;
+       ser_cmd_export_t* ser_cmd;
+       kam_cmd_export_t* kam_cmd;
+       sr31_cmd_export_t* ret;
+       
+       ser_cmd = 0;
+       kam_cmd = 0;
+       ret = 0;
+       n = 0;
+       /* count the number of elements */
+       if (ver == 0) {
+               ser_cmd = src;
+               for (; ser_cmd[n].name; n++);
+       } else if (ver == 1) {
+               kam_cmd = src;
+               for (; kam_cmd[n].name; n++);
+       } else goto error; /* unknown interface version */
+       /* alloc & init new array */
+       ret = pkg_malloc(sizeof(*ret)*(n+1));
+       memset(ret, 0, sizeof(*ret)*(n+1));
+       /* convert/copy */
+       for (i=0; i < n; i++) {
+               if (ver == 0) {
+                       ret[i].name = ser_cmd[i].name;
+                       ret[i].function = ser_cmd[i].function;
+                       ret[i].param_no = ser_cmd[i].param_no;
+                       ret[i].fixup = ser_cmd[i].fixup;
+                       ret[i].free_fixup = 0; /* no present in ser  <= 2.1 */
+                       ret[i].flags = ser_cmd[i].flags;
+               } else {
+                       ret[i].name = kam_cmd[i].name;
+                       ret[i].function = kam_cmd[i].function;
+                       ret[i].param_no = kam_cmd[i].param_no;
+                       ret[i].fixup = kam_cmd[i].fixup;
+                       ret[i].free_fixup = kam_cmd[i].free_fixup;
+                       ret[i].flags = kam_cmd[i].flags;
+               }
+               /* 3.1+ specific stuff */
+               ret[i].fixup_flags = 0;
+               ret[i].module_exports = mod;
+       }
+       return ret;
+error:
+       return 0;
+}
+
+
+
 /* registers a module,  register_f= module register  functions
  * returns <0 on error, 0 on success */
 static int register_module(unsigned ver, union module_exports_u* e,
@@ -169,36 +229,96 @@ static int register_module(unsigned ver, union module_exports_u* e,
        memset(mod,0, sizeof(struct sr_module));
        mod->path=path;
        mod->handle=handle;
-       mod->mod_interface_ver=ver;
-       mod->exports=e;
-       mod->next=modules;
-       modules=mod;
+       mod->orig_mod_interface_ver=ver;
+       /* convert exports to sr31 format */
+       if (ver == 0) {
+               /* ser <= 3.0 */
+               mod->exports.name = e->v0.name;
+               if (e->v0.cmds) {
+                       mod->exports.cmds = sr_cmd_exports_convert(ver, e->v0.cmds, mod);
+                       if (mod->exports.cmds == 0) {
+                               ERR("failed to convert module command exports to 3.1 format"
+                                               " for module \"%s\" (%s), interface version %d\n",
+                                               mod->exports.name, mod->path, ver);
+                               ret = E_UNSPEC;
+                               goto error;
+                       }
+               }
+               mod->exports.params = e->v0.params;
+               mod->exports.init_f = e->v0.init_f;
+               mod->exports.response_f = e->v0.response_f;
+               mod->exports.destroy_f = e->v0.destroy_f;
+               mod->exports.onbreak_f = e->v0.onbreak_f;
+               mod->exports.init_child_f = e->v0.init_child_f;
+               mod->exports.dlflags = 0; /* not used in ser <= 3.0 */
+               mod->exports.rpc_methods = e->v0.rpc_methods;
+               /* the rest are 0, not used in ser */
+       } else if (ver == 1) {
+               /* kamailio <= 3.0 */
+               mod->exports.name = e->v1.name;
+               if (e->v1.cmds) {
+                       mod->exports.cmds = sr_cmd_exports_convert(ver, e->v1.cmds, mod);
+                       if (mod->exports.cmds == 0) {
+                               ERR("failed to convert module command exports to 3.1 format"
+                                               " for module \"%s\" (%s), interface version %d\n",
+                                               mod->exports.name, mod->path, ver);
+                               ret = E_UNSPEC;
+                               goto error;
+                       }
+               }
+               mod->exports.params = e->v1.params;
+               mod->exports.init_f = e->v1.init_f;
+               mod->exports.response_f = e->v1.response_f;
+               mod->exports.destroy_f = e->v1.destroy_f;
+               mod->exports.onbreak_f = 0; /* not used in k <= 3.0 */
+               mod->exports.init_child_f = e->v1.init_child_f;
+               mod->exports.dlflags = e->v1.dlflags;
+               mod->exports.rpc_methods = 0; /* not used in k <= 3.0 */
+               mod->exports.stats = e->v1.stats;
+               mod->exports.mi_cmds = e->v1.mi_cmds;
+               mod->exports.items = e->v1.items;
+               mod->exports.procs = e->v1.procs;
+       } else {
+               ERR("unsupported module interface version %d\n", ver);
+               ret = E_UNSPEC;
+               goto error;
+       }
 
-       if (ver==1 && e->v1.items) {
+       if (mod->exports.items) {
                /* register module pseudo-variables for kamailio modules */
-               LM_DBG("register PV from: %s\n", e->c.name);
-               if (register_pvars_mod(e->c.name, e->v1.items)!=0) {
-                       LM_ERR("failed to register pseudo-variables for module %s\n",
-                               e->c.name);
-                       pkg_free(mod);
-                       return -1;
+               LM_DBG("register PV from: %s\n", mod->exports.name);
+               if (register_pvars_mod(mod->exports.name, mod->exports.items)!=0) {
+                       LM_ERR("failed to register pseudo-variables for module %s (%s)\n",
+                               mod->exports.name, path);
+                       ret = E_UNSPEC;
+                       goto error;
                }
-       }else if (ver==0 && e->v0.rpc_methods){
+       }
+       if (mod->exports.rpc_methods){
                /* register rpcs for ser modules */
-               i=rpc_register_array(e->v0.rpc_methods);
+               i=rpc_register_array(mod->exports.rpc_methods);
                if (i<0){
-                       ERR("failed to register RPCs for module %s\n", e->c.name);
+                       ERR("failed to register RPCs for module %s (%s)\n",
+                                       mod->exports.name, path);
+                       ret = E_UNSPEC;
                        goto error;
                }else if (i>0){
                        ERR("%d duplicate RPCs name detected while registering RPCs"
-                                       " declared in modules %s\n", i, e->c.name);
+                                       " declared in module %s (%s)\n",
+                                       i, mod->exports.name, path);
+                       ret = E_UNSPEC;
                        goto error;
                }
                /* i==0 => success */
        }
 
+       /* link module in the list */
+       mod->next=modules;
+       modules=mod;
        return 0;
 error:
+       if (mod)
+               pkg_free(mod);
        return ret;
 }
 
@@ -473,51 +593,33 @@ skip:
 
 /* searches the module list for function name in module mod and returns 
  *  a pointer to the "name" function record union or 0 if not found
- * sets also *mod_if_ver to the module interface version (needed to know
- * which member of the union should be accessed v0 or v1)
+ * sets also *mod_if_ver to the original module interface version.
  * mod==0 is a wildcard matching all modules
  * flags parameter is OR value of all flags that must match
  */
-union cmd_export_u* find_mod_export_record(char* mod, char* name,
+sr31_cmd_export_t* find_mod_export_record(char* mod, char* name,
                                                                                        int param_no, int flags,
                                                                                        unsigned* mod_if_ver)
 {
        struct sr_module* t;
-       union cmd_export_u* cmd;
-       int i;
-       unsigned mver;
-
-#define FIND_EXPORT_IN_MOD(VER) \
-               if (t->exports->VER.cmds) \
-                       for(i=0, cmd=(void*)&t->exports->VER.cmds[0]; cmd->VER.name; \
-                                       i++, cmd=(void*)&t->exports->VER.cmds[i]){\
-                               if((strcmp(name, cmd->VER.name)==0)&& \
-                                       ((cmd->VER.param_no==param_no) || \
-                                        (cmd->VER.param_no==VAR_PARAM_NO)) && \
-                                       ((cmd->VER.flags & flags) == flags) \
-                               ){ \
-                                       DBG("find_export_record: found <%s> in module %s [%s]\n", \
-                                               name, t->exports->VER.name, t->path); \
-                                       *mod_if_ver=mver; \
-                                       return cmd; \
-                               } \
-                       }
+       sr31_cmd_export_t* cmd;
 
        for(t=modules;t;t=t->next){
-               if (mod!=0 && (strcmp(t->exports->c.name, mod) !=0))
+               if (mod!=0 && (strcmp(t->exports.name, mod) !=0))
                        continue;
-               mver=t->mod_interface_ver;
-               switch (mver){
-                       case 0:
-                               FIND_EXPORT_IN_MOD(v0);
-                               break;
-                       case 1:
-                               FIND_EXPORT_IN_MOD(v1);
-                               break;
-                       default:
-                               BUG("invalid module interface version %d for modules %s\n",
-                                               t->mod_interface_ver, t->path);
-               }
+               if (t->exports.cmds)
+                       for(cmd=&t->exports.cmds[0]; cmd->name; cmd++) {
+                               if((strcmp(name, cmd->name) == 0) &&
+                                       ((cmd->param_no == param_no) ||
+                                        (cmd->param_no==VAR_PARAM_NO)) &&
+                                       ((cmd->flags & flags) == flags)
+                               ){
+                                       DBG("find_export_record: found <%s> in module %s [%s]\n",
+                                               name, t->exports.name, t->path);
+                                       *mod_if_ver=t->orig_mod_interface_ver;
+                                       return cmd;
+                               }
+                       }
        }
        DBG("find_export_record: <%s> not found \n", name);
        return 0;
@@ -532,7 +634,7 @@ union cmd_export_u* find_mod_export_record(char* mod, char* name,
  * mod==0 is a wildcard matching all modules
  * flags parameter is OR value of all flags that must match
  */
-union cmd_export_u* find_export_record(char* name,
+sr31_cmd_export_t* find_export_record(char* name,
                                                                                        int param_no, int flags,
                                                                                        unsigned* mod_if_ver)
 {
@@ -543,11 +645,11 @@ union cmd_export_u* find_export_record(char* name,
 
 cmd_function find_export(char* name, int param_no, int flags)
 {
-       union cmd_export_u* cmd;
+       sr31_cmd_export_t* cmd;
        unsigned mver;
        
        cmd = find_export_record(name, param_no, flags, &mver);
-       return cmd?cmd->c.function:0;
+       return cmd?cmd->function:0;
 }
 
 
@@ -565,12 +667,12 @@ rpc_export_t* find_rpc_export(char* name, int flags)
  */
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
 {
-       union cmd_export_u* cmd;
+       sr31_cmd_export_t* cmd;
        unsigned mver;
 
        cmd=find_mod_export_record(mod, name, param_no, flags, &mver);
        if (cmd)
-               return cmd->c.function;
+               return cmd->function;
        
        DBG("find_mod_export: <%s> in module <%s> not found\n", name, mod);
        return 0;
@@ -581,7 +683,7 @@ struct sr_module* find_module_by_name(char* mod) {
        struct sr_module* t;
 
        for(t = modules; t; t = t->next) {
-               if (strcmp(mod, t->exports->c.name) == 0) {
+               if (strcmp(mod, t->exports.name) == 0) {
                        return t;
                }
        }
@@ -597,30 +699,17 @@ void* find_param_export(struct sr_module* mod, char* name,
 
        if (!mod)
                return 0;
-       param=0;
-       switch(mod->mod_interface_ver){
-               case 0:
-                       param=mod->exports->v0.params;
-                       break;
-               case 1:
-                       param=mod->exports->v1.params;
-                       break;
-               default:
-                       BUG("bad module interface version %d in module %s [%s]\n",
-                                       mod->mod_interface_ver, mod->exports->c.name, mod->path);
-                       return 0;
-       }
-       for(;param && param->name ; param++) {
+       for(param = mod->exports.params ;param && param->name ; param++) {
                if ((strcmp(name, param->name) == 0) &&
                        ((param->type & PARAM_TYPE_MASK(type_mask)) != 0)) {
                        DBG("find_param_export: found <%s> in module %s [%s]\n",
-                               name, mod->exports->c.name, mod->path);
+                               name, mod->exports.name, mod->path);
                        *param_type = param->type;
                        return param->param_pointer;
                }
        }
        DBG("find_param_export: parameter <%s> not found in module <%s>\n",
-                       name, mod->exports->c.name);
+                       name, mod->exports.name);
        return 0;
 }
 
@@ -632,19 +721,8 @@ void destroy_modules()
        t=modules;
        while(t) {
                foo=t->next;
-               if (t->exports){
-                       switch(t->mod_interface_ver){
-                               case 0:
-                                       if ((t->exports->v0.destroy_f)) t->exports->v0.destroy_f();
-                                       break;
-                               case 1:
-                                       if ((t->exports->v1.destroy_f)) t->exports->v1.destroy_f();
-                                       break;
-                               default:
-                                       BUG("bad module interface version %d in module %s [%s]\n",
-                                               t->mod_interface_ver, t->exports->c.name,
-                                               t->path);
-                       }
+               if (t->exports.destroy_f){
+                       t->exports.destroy_f();
                }
                pkg_free(t);
                t=foo;
@@ -667,36 +745,14 @@ int init_modules(void)
        struct sr_module* t;
 
        for(t = modules; t; t = t->next) {
-               if (t->exports){
-                       switch(t->mod_interface_ver){
-                               case 0:
-                                       if (t->exports->v0.init_f)
-                                               if (t->exports->v0.init_f() != 0) {
-                                                       LOG(L_ERR, "init_modules(): Error while"
-                                                                               " initializing module %s\n",
-                                                                               t->exports->v0.name);
-                                                       return -1;
-                                               }
-                                       if (t->exports->v0.response_f)
-                                               mod_response_cbk_no++;
-                                       break;
-                               case 1:
-                                       if (t->exports->v1.init_f)
-                                               if (t->exports->v1.init_f() != 0) {
-                                                       LOG(L_ERR, "init_modules(): Error while"
-                                                                               " initializing module %s\n",
-                                                                               t->exports->v1.name);
-                                                       return -1;
-                                               }
-                                       if (t->exports->v1.response_f)
-                                               mod_response_cbk_no++;
-                                       break;
-                               default:
-                                       BUG("bad module interface version %d in module %s [%s]\n",
-                                               t->exports->c.name, t->path);
-                                       return -1;
+               if (t->exports.init_f)
+                       if (t->exports.init_f() != 0) {
+                               LOG(L_ERR, "init_modules(): Error while"
+                                               " initializing module %s\n", t->exports.name);
+                               return -1;
                        }
-               }
+               if (t->exports.response_f)
+                       mod_response_cbk_no++;
        }
        mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
                                                                        sizeof(response_function));
@@ -705,27 +761,17 @@ int init_modules(void)
                                        " for %d response_f callbacks\n", mod_response_cbk_no);
                return -1;
        }
-       for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
-               if (t->exports){
-                       switch(t->mod_interface_ver){
-                               case 0:
-                                       if (t->exports->v0.response_f){
-                                               mod_response_cbks[i]=t->exports->v0.response_f;
-                                               i++;
-                                       }
-                                       break;
-                               case 1:
-                                       if (t->exports->v1.response_f){
-                                               mod_response_cbks[i]=t->exports->v1.response_f;
-                                               i++;
-                                       }
-                                       break;
-                       }
+       for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next) {
+               if (t->exports.response_f) {
+                       mod_response_cbks[i]=t->exports.response_f;
+                       i++;
                }
        }
        return 0;
 }
 
+
+
 /*
  * per-child initialization
  */
@@ -745,30 +791,12 @@ int init_child(int rank)
 
 
        for(t = modules; t; t = t->next) {
-               switch(t->mod_interface_ver){
-                       case 0:
-                               if (t->exports->v0.init_child_f) {
-                                       if ((t->exports->v0.init_child_f(rank)) < 0) {
-                                               LOG(L_ERR, "init_child(): Initialization of child"
-                                                                       " %d failed\n", rank);
-                                               return -1;
-                                       }
-                               }
-                               break;
-                       case 1:
-                               if (t->exports->v1.init_child_f) {
-                                       if ((t->exports->v1.init_child_f(rank)) < 0) {
-                                               LOG(L_ERR, "init_child(): Initialization of child"
-                                                                       " %d failed\n", rank);
-                                               return -1;
-                                       }
-                               }
-                               break;
-                       default:
-                               BUG("bad module interface version %d in module %s [%s]\n",
-                                               t->mod_interface_ver, t->exports->c.name,
-                                               t->path);
+               if (t->exports.init_child_f) {
+                       if ((t->exports.init_child_f(rank)) < 0) {
+                               LOG(L_ERR, "init_child(): Initialization of child"
+                                                       " %d failed\n", rank);
                                return -1;
+                       }
                }
        }
        return 0;
@@ -789,43 +817,19 @@ static int init_mod_child( struct sr_module* m, int rank )
                   propagate it up the stack
                 */
                if (init_mod_child(m->next, rank)!=0) return -1;
-               if (m->exports){
-                       switch(m->mod_interface_ver){
-                               case 0:
-                                       if (m->exports->v0.init_child_f) {
-                                               DBG("DEBUG: init_mod_child (%d): %s\n",
-                                                               rank, m->exports->v0.name);
-                                               if (m->exports->v0.init_child_f(rank)<0) {
-                                                       LOG(L_ERR, "init_mod_child(): Error while"
-                                                                               " initializing module %s\n",
-                                                                               m->exports->v0.name);
-                                                       return -1;
-                                               } else {
-                                                       /* module correctly initialized */
-                                                       return 0;
-                                               }
-                                       }
-                                       /* no init function -- proceed with success */
-                                       return 0;
-                               case 1:
-                                       if (m->exports->v1.init_child_f) {
-                                               DBG("DEBUG: init_mod_child (%d): %s\n",
-                                                               rank, m->exports->v1.name);
-                                               if (m->exports->v1.init_child_f(rank)<0) {
-                                                       LOG(L_ERR, "init_mod_child(): Error while"
-                                                                               " initializing module %s\n",
-                                                                               m->exports->v1.name);
-                                                       return -1;
-                                               } else {
-                                                       /* module correctly initialized */
-                                                       return 0;
-                                               }
-                                       }
-                                       /* no init function -- proceed with success */
-                                       return 0;
+               if (m->exports.init_child_f) {
+                       DBG("DEBUG: init_mod_child (%d): %s\n", rank, m->exports.name);
+                       if (m->exports.init_child_f(rank)<0) {
+                               LOG(L_ERR, "init_mod_child(): Error while"
+                                                       " initializing module %s (%s)\n",
+                                                       m->exports.name, m->path);
+                               return -1;
+                       } else {
+                               /* module correctly initialized */
+                               return 0;
                        }
                }
-               /* no exports -- proceed with success */
+               /* no init function -- proceed with success */
                return 0;
        } else {
                /* end of list */
@@ -856,40 +860,20 @@ static int init_mod( struct sr_module* m )
                   propagate it up the stack
                 */
                if (init_mod(m->next)!=0) return -1;
-               if (m->exports){
-                       switch(m->mod_interface_ver){
-                               case 0:
-                                       if ( m->exports->v0.init_f) {
-                                               DBG("DEBUG: init_mod: %s\n", m->exports->v0.name);
-                                               if (m->exports->v0.init_f()!=0) {
-                                                       LOG(L_ERR, "init_mod(): Error while initializing"
-                                                                               " module %s\n", m->exports->v0.name);
-                                                       return -1;
-                                               } else {
-                                                       /* module correctly initialized */
-                                                       return 0;
-                                               }
-                                       }
-                                       /* no init function -- proceed with success */
-                                       return 0;
-                               case 1:
-                                       if ( m->exports->v1.init_f) {
-                                               DBG("DEBUG: init_mod: %s\n", m->exports->v1.name);
-                                               if (m->exports->v1.init_f()!=0) {
-                                                       LOG(L_ERR, "init_mod(): Error while initializing"
-                                                                               " module %s\n", m->exports->v1.name);
-                                                       return -1;
-                                               } else {
-                                                       /* module correctly initialized */
-                                                       return 0;
-                                               }
-                                       }
-                                       /* no init function -- proceed with success */
+                       if (m->exports.init_f) {
+                               DBG("DEBUG: init_mod: %s\n", m->exports.name);
+                               if (m->exports.init_f()!=0) {
+                                       LOG(L_ERR, "init_mod(): Error while initializing"
+                                                               " module %s (%s)\n",
+                                                               m->exports.name, m->path);
+                                       return -1;
+                               } else {
+                                       /* module correctly initialized */
                                        return 0;
+                               }
                        }
-               }
-               /* no exports -- proceed with success */
-               return 0;
+                       /* no init function -- proceed with success */
+                       return 0;
        } else {
                /* end of list */
                return 0;
@@ -910,18 +894,8 @@ int init_modules(void)
                return i;
 
        for(t = modules; t; t = t->next)
-               if (t->exports){
-                       switch(t->mod_interface_ver){
-                               case 0:
-                                       if (t->exports->v0.response_f)
-                                               mod_response_cbk_no++;
-                                       break;
-                               case 1:
-                                       if (t->exports->v1.response_f)
-                                               mod_response_cbk_no++;
-                                       break;
-                       }
-               }
+               if (t->exports.response_f)
+                       mod_response_cbk_no++;
        mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
                                                                        sizeof(response_function));
        if (mod_response_cbks==0){
@@ -929,24 +903,11 @@ int init_modules(void)
                                        " for %d response_f callbacks\n", mod_response_cbk_no);
                return -1;
        }
-       for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
-               if (t->exports){
-                       switch(t->mod_interface_ver){
-                               case 0:
-                                       if (t->exports->v0.response_f){
-                                               mod_response_cbks[i]=t->exports->v0.response_f;
-                                               i++;
-                                       }
-                                       break;
-                               case 1:
-                                       if (t->exports->v1.response_f){
-                                               mod_response_cbks[i]=t->exports->v1.response_f;
-                                               i++;
-                                       }
-                                       break;
-                       }
+       for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next)
+               if (t->exports.response_f) {
+                       mod_response_cbks[i]=t->exports.response_f;
+                       i++;
                }
-       }
        
        return 0;
 }
index e69d553..8048b6c 100644 (file)
@@ -153,12 +153,9 @@ typedef int (*param_func_t)( modparam_t type, void* val);
  * They are kept in the first 2 bits inside the pointer
  */
 #define FIXUP_F_FPARAM_RVE (unsigned long)1 /* fparam fixup, rve ready */
-#define FIXUP_F_RESERVED (unsigned long)2  /* not used for now */
-#define FIXUP_MASK (~((unsigned long)3)) /* mask for obtainin the pointer val*/
 
 #define call_fixup(fixup, param, param_no) \
-       (((long)(fixup) & FIXUP_MASK)? \
-               (((fixup_function)((long)(fixup) & FIXUP_MASK))(param, param_no)):0)
+       ((fixup) ? (fixup)(param, param_no) : 0)
 
 /* Macros - used as rank in child_init function */
 #define PROC_MAIN      0  /* Main ser process */
@@ -223,6 +220,20 @@ struct kam_cmd_export_ {
 };
 
 
+struct sr31_cmd_export_ {
+       char* name;             /* null terminated command name */
+       cmd_function function;  /* pointer to the corresponding function */
+       int param_no;           /* number of parameters used by the function */
+       fixup_function fixup;   /* pointer to the function called to "fix" the
+                                                          parameters */
+       free_fixup_function free_fixup; /* function called to free the "fixed"
+                                                                          parameters */
+       int flags;              /* Function flags */
+       int fixup_flags;
+       void* module_exports; /* pointer to module structure */
+};
+
+
 /* members situated at the same place in memory in both ser & kamailio
    cmd_export */
 struct cmd_export_common_ {
@@ -288,12 +299,15 @@ typedef struct param_export_ param_export_t;
 typedef struct ser_cmd_export_ ser_cmd_export_t;
 typedef struct kam_cmd_export_ kam_cmd_export_t;
 typedef struct cmd_export_common_ cmd_export_common_t;
+typedef struct sr31_cmd_export_ sr31_cmd_export_t;
 
+#if 0
 union cmd_export_u{
        cmd_export_common_t c; /* common members for everybody */
        ser_cmd_export_t v0;
        kam_cmd_export_t v1;
 };
+#endif
 
 
 /* ser module exports version */
@@ -361,6 +375,47 @@ struct kam_module_exports {
 
 
 
+/** sr/ser 3.1+ module exports version.
+ * Includes ser and kamailio versions, re-arraranged + some extras.
+ * Note: some of the members will be obsoleted and are kept only for
+ * backward compatibility (avoid re-writing all the modules exports
+ * declarations).
+ */
+struct sr31_module_exports {
+       char* name;                     /* null terminated module name */
+       sr31_cmd_export_t* cmds;      /* null terminated array of the exported
+                                                                          commands */
+       param_export_t* params;         /* null terminated array of the exported
+                                                                          module parameters */
+       init_function init_f;           /* Initialization function */
+       response_function response_f;   /* function used for responses,
+                                                                          returns yes or no; can be null */
+       destroy_function destroy_f;     /* function called when the module should
+                                                                          be "destroyed", e.g: on ser exit;
+                                                                          can be null */
+       onbreak_function onbreak_f;
+       child_init_function init_child_f;  /* function called by all processes
+                                                                                 after the fork */
+       unsigned int dlflags;           /**< flags for dlopen */
+       /* ser specific exports
+          (to be obsoleted and replaced by register_...) */
+       rpc_export_t* rpc_methods;      /* null terminated array of exported
+                                                                          rpc methods */
+       /* kamailio specific exports
+          (to be obsoleted and replaced by register_...) */
+       stat_export_t* stats;                   /*!< null terminated array of the exported
+                                                                         module statistics */
+       mi_export_t* mi_cmds;                   /*!< null terminated array of the exported
+                                                                         MI functions */
+       pv_export_t* items;                             /*!< null terminated array of the exported
+                                                                          module items (pseudo-variables) */
+       proc_export_t* procs;                   /*!< null terminated array of the
+                                                                         additional processes required by the
+                                                                         module */
+};
+
+
+
 /* module exports in the same place in memory in both ser & kamailio */
 struct module_exports_common{
        char* name;
@@ -377,8 +432,8 @@ union module_exports_u {
 struct sr_module{
        char* path;
        void* handle;
-       unsigned int mod_interface_ver;
-       union module_exports_u* exports;
+       unsigned int orig_mod_interface_ver;
+       struct sr31_module_exports exports;
        struct sr_module* next;
 };
 
@@ -388,9 +443,8 @@ extern response_function* mod_response_cbks;/* response callback array */
 extern int mod_response_cbk_no;    /* size of reponse callbacks array */
 
 int register_builtin_modules(void);
-/*int register_module(unsigned , struct module_exports*, char*,  void*);*/
 int load_module(char* path);
-union cmd_export_u* find_export_record(char* name, int param_no, int flags,
+sr31_cmd_export_t* find_export_record(char* name, int param_no, int flags,
                                                                                unsigned *ver);
 cmd_function find_export(char* name, int param_no, int flags);
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags);