Browse code

core: internal module interface changes

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

Andrei Pelinescu-Onciul authored on 04/08/2010 13:38:58
Showing 6 changed files
... ...
@@ -172,9 +172,9 @@ struct onsend_info* p_onsend=0; /* onsend route send info */
172 172
 				(dst)[i+2].u.string = s.s; \
173 173
 				(dst)[i+2].u.str.len = s.len; \
174 174
 				rval_destroy(rv); \
175
-				if ((cmd)->c.fixup && \
176
-						(long)(cmd)->c.fixup & FIXUP_F_FPARAM_RVE) { \
177
-					call_fixup((cmd)->c.fixup, &(dst)[i+2].u.data, i+1); \
175
+				if ((cmd)->fixup && \
176
+						(cmd)->fixup_flags & FIXUP_F_FPARAM_RVE) { \
177
+					call_fixup((cmd)->fixup, &(dst)[i+2].u.data, i+1); \
178 178
 					if ((dst)[i+2].u.data != s.s) \
179 179
 						(dst)[i+2].type = FPARAM_DYN_ST; \
180 180
 				} \
... ...
@@ -201,14 +201,14 @@ struct onsend_info* p_onsend=0; /* onsend route send info */
201 201
 #define MODF_CALL(f_type, h, msg, src, ...) \
202 202
 	do { \
203 203
 		cmd=(src)[0].u.data; \
204
-		ret=((f_type)cmd->c.function)((msg), __VAR_ARGS__); \
204
+		ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
205 205
 		MODF_HANDLE_RETCODE(h, ret); \
206 206
 	} while (0)
207 207
 #else  /* ! __SUNPRO_C  (gcc, icc a.s.o) */
208 208
 #define MODF_CALL(f_type, h, msg, src, params...) \
209 209
 	do { \
210 210
 		cmd=(src)[0].u.data; \
211
-		ret=((f_type)cmd->c.function)((msg), ## params ); \
211
+		ret=((f_type)cmd->function)((msg), ## params ); \
212 212
 		MODF_HANDLE_RETCODE(h, ret); \
213 213
 	} while (0)
214 214
 #endif /* __SUNPRO_C */
... ...
@@ -235,7 +235,7 @@ struct onsend_info* p_onsend=0; /* onsend route send info */
235 235
 	do { \
236 236
 		cmd=(src)[0].u.data; \
237 237
 		MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
238
-		ret=((f_type)cmd->c.function)((msg), __VAR_ARGS__); \
238
+		ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
239 239
 		MODF_HANDLE_RETCODE(h, ret); \
240 240
 		/* free strings allocated by us or fixups */ \
241 241
 		MODF_RVE_PARAM_FREE(src, dst); \
... ...
@@ -245,7 +245,7 @@ struct onsend_info* p_onsend=0; /* onsend route send info */
245 245
 	do { \
246 246
 		cmd=(src)[0].u.data; \
247 247
 		MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
248
-		ret=((f_type)cmd->c.function)((msg), ## params ); \
248
+		ret=((f_type)cmd->function)((msg), ## params ); \
249 249
 		MODF_HANDLE_RETCODE(h, ret); \
250 250
 		/* free strings allocated by us or fixups */ \
251 251
 		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)
263 263
 	struct dest_info dst;
264 264
 	char* tmp;
265 265
 	char *new_uri, *end, *crt;
266
-	union cmd_export_u* cmd;
266
+	sr31_cmd_export_t* cmd;
267 267
 	int len;
268 268
 	int user;
269 269
 	struct sip_uri uri, next_hop;
... ...
@@ -1484,11 +1484,9 @@ end:
1484 1484
 	/* process module onbreak handlers if present */
1485 1485
 	if (h->rec_lev==0 && ret==0)
1486 1486
 		for (mod=modules;mod;mod=mod->next)
1487
-			if ((mod->mod_interface_ver==0) && mod->exports && 
1488
-					mod->exports->v0.onbreak_f) {
1489
-				mod->exports->v0.onbreak_f( msg );
1490
-				DBG("DEBUG: %s onbreak handler called\n",
1491
-						mod->exports->c.name);
1487
+			if (mod->exports.onbreak_f) {
1488
+				mod->exports.onbreak_f( msg );
1489
+				DBG("DEBUG: %s onbreak handler called\n", mod->exports.name);
1492 1490
 			}
1493 1491
 	return ret;
1494 1492
 
... ...
@@ -2697,7 +2697,7 @@ rval: intno			{$$=mk_rve_rval(RV_INT, (void*)$1); }
2697 2697
 
2698 2698
 
2699 2699
 rve_un_op: NOT	{ $$=RVE_LNOT_OP; }
2700
-		|  MINUS %prec UNARY	{ $$=RVE_UMINUS_OP; } 
2700
+		|  MINUS %prec UNARY	{ $$=RVE_UMINUS_OP; }
2701 2701
 		/* TODO: RVE_BOOL_OP, RVE_NOT_OP? */
2702 2702
 	;
2703 2703
 
... ...
@@ -3704,7 +3704,7 @@ static int case_check_default(struct case_stms* stms)
3704 3704
  */
3705 3705
 static int mod_f_params_pre_fixup(struct action* a)
3706 3706
 {
3707
-	union cmd_export_u* cmd_exp;
3707
+	sr31_cmd_export_t* cmd_exp;
3708 3708
 	action_u_t* params;
3709 3709
 	int param_no;
3710 3710
 	struct rval_expr* rve;
... ...
@@ -3716,7 +3716,7 @@ static int mod_f_params_pre_fixup(struct action* a)
3716 3716
 	param_no = a->val[1].u.number;
3717 3717
 	params = &a->val[2];
3718 3718
 	
3719
-	switch(cmd_exp->c.param_no) {
3719
+	switch(cmd_exp->param_no) {
3720 3720
 		case 0:
3721 3721
 			a->type = MODULE0_T;
3722 3722
 			break;
... ...
@@ -3743,24 +3743,22 @@ static int mod_f_params_pre_fixup(struct action* a)
3743 3743
 			break;
3744 3744
 		default:
3745 3745
 			yyerror("function %s: bad definition"
3746
-					" (invalid number of parameters)", cmd_exp->c.name);
3746
+					" (invalid number of parameters)", cmd_exp->name);
3747 3747
 			return -1;
3748 3748
 	}
3749 3749
 	
3750
-	if ( cmd_exp->c.fixup) {
3751
-		if (is_fparam_rve_fixup(cmd_exp->c.fixup))
3750
+	if ( cmd_exp->fixup) {
3751
+		if (is_fparam_rve_fixup(cmd_exp->fixup))
3752 3752
 			/* mark known fparam rve safe fixups */
3753
-			cmd_exp->c.fixup  = (fixup_function)
3754
-									((unsigned long) cmd_exp->c.fixup |
3755
-										 FIXUP_F_FPARAM_RVE);
3756
-		else if (!((unsigned long)cmd_exp->c.fixup & FIXUP_F_FPARAM_RVE)) {
3753
+			cmd_exp->fixup_flags  |= FIXUP_F_FPARAM_RVE;
3754
+		else if (!(cmd_exp->fixup_flags & FIXUP_F_FPARAM_RVE)) {
3757 3755
 			/* v0 or v1 functions that have fixups need constant,
3758 3756
 			  string params.*/
3759 3757
 			for (r=0; r < param_no; r++) {
3760 3758
 				rve=params[r].u.data;
3761 3759
 				if (!rve_is_constant(rve)) {
3762 3760
 					yyerror_at(&rve->fpos, "function %s: parameter %d is not"
3763
-								" constant\n", cmd_exp->c.name, r+1);
3761
+								" constant\n", cmd_exp->name, r+1);
3764 3762
 					return -1;
3765 3763
 				}
3766 3764
 				if ((rv = rval_expr_eval(0, 0, rve)) == 0 ||
... ...
@@ -3768,7 +3766,7 @@ static int mod_f_params_pre_fixup(struct action* a)
3768 3768
 					/* out of mem or bug ? */
3769 3769
 					rval_destroy(rv);
3770 3770
 					yyerror_at(&rve->fpos, "function %s: bad parameter %d"
3771
-									" expression\n", cmd_exp->c.name, r+1);
3771
+									" expression\n", cmd_exp->name, r+1);
3772 3772
 					return -1;
3773 3773
 				}
3774 3774
 				rval_destroy(rv);
... ...
@@ -3796,12 +3794,10 @@ static int mod_f_params_pre_fixup(struct action* a)
3796 3796
  */
3797 3797
 static void free_mod_func_action(struct action* a)
3798 3798
 {
3799
-	union cmd_export_u* cmd_exp;
3800 3799
 	action_u_t* params;
3801 3800
 	int param_no;
3802 3801
 	int r;
3803 3802
 	
3804
-	cmd_exp = a->val[0].u.data;
3805 3803
 	param_no = a->val[1].u.number;
3806 3804
 	params = &a->val[2];
3807 3805
 	
... ...
@@ -91,9 +91,9 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
91 91
 
92 92
 	mod_found = 0;
93 93
 	for(t = modules; t; t = t->next) {
94
-		if (regexec(&preg, t->exports->c.name, 0, 0, 0) == 0) {
94
+		if (regexec(&preg, t->exports.name, 0, 0, 0) == 0) {
95 95
 			DBG("set_mod_param_regex: '%s' matches module '%s'\n",
96
-					regex, t->exports->c.name);
96
+					regex, t->exports.name);
97 97
 			mod_found = 1;
98 98
 			/* PARAM_STR (PARAM_STRING) may be assigned also to PARAM_STRING(PARAM_STR) so let get both module param */
99 99
 			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)
109 109
 					val2 = val;
110 110
 				}
111 111
 				DBG("set_mod_param_regex: found <%s> in module %s [%s]\n",
112
-						name, t->exports->c.name, t->path);
112
+						name, t->exports.name, t->path);
113 113
 				if (param_type & PARAM_USE_FUNC) {
114 114
 					if ( ((param_func_t)(ptr))(param_type, val2) < 0) {
115 115
 						regfree(&preg);
... ...
@@ -147,7 +147,7 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
147 147
 			}
148 148
 			else {
149 149
 				LOG(L_ERR, "set_mod_param_regex: parameter <%s> not found in"
150
-							" module <%s>\n", name, t->exports->c.name);
150
+							" module <%s>\n", name, t->exports.name);
151 151
 				regfree(&preg);
152 152
 				pkg_free(reg);
153 153
 				return -3;
... ...
@@ -634,7 +634,7 @@ int fix_actions(struct action* a)
634 634
 	void *tmp_p;
635 635
 	int ret;
636 636
 	int i;
637
-	union cmd_export_u* cmd;
637
+	sr31_cmd_export_t* cmd;
638 638
 	str s;
639 639
 	struct hostent* he;
640 640
 	struct ip_addr ip;
... ...
@@ -920,9 +920,9 @@ int fix_actions(struct action* a)
920 920
 				cmd = t->val[0].u.data;
921 921
 				rve_param_no = 0;
922 922
 				if (cmd) {
923
-					DBG("fixing %s()\n", cmd->c.name);
923
+					DBG("fixing %s()\n", cmd->name);
924 924
 					if (t->val[1].u.number==0) {
925
-						ret = call_fixup(cmd->c.fixup, 0, 0);
925
+						ret = call_fixup(cmd->fixup, 0, 0);
926 926
 						if (ret < 0)
927 927
 							goto error;
928 928
 					}
... ...
@@ -948,7 +948,7 @@ int fix_actions(struct action* a)
948 948
 								/* len is not used for now */
949 949
 								t->val[i+2].u.str.len = s.len;
950 950
 								tmp_p = t->val[i+2].u.data;
951
-								ret = call_fixup(cmd->c.fixup,
951
+								ret = call_fixup(cmd->fixup,
952 952
 												&t->val[i+2].u.data, i+1);
953 953
 								if (t->val[i+2].u.data != tmp_p)
954 954
 									t->val[i+2].type = MODFIXUP_ST;
... ...
@@ -967,7 +967,7 @@ int fix_actions(struct action* a)
967 967
 							}
968 968
 						} else  if (t->val[i+2].type == STRING_ST) {
969 969
 							tmp_p = t->val[i+2].u.data;
970
-							ret = call_fixup(cmd->c.fixup,
970
+							ret = call_fixup(cmd->fixup,
971 971
 											&t->val[i+2].u.data, i+1);
972 972
 							if (t->val[i+2].u.data != tmp_p)
973 973
 								t->val[i+2].type = MODFIXUP_ST;
... ...
@@ -984,12 +984,11 @@ int fix_actions(struct action* a)
984 984
 					   (constant RVEs), MODFIXUP_ST (fixed up)
985 985
 					   or RVE_ST (non-ct RVEs) */
986 986
 					if (rve_param_no) { /* we have to fix the type */
987
-						if (cmd->c.fixup &&
988
-							!((unsigned long)cmd->c.fixup &
989
-								FIXUP_F_FPARAM_RVE)) {
987
+						if (cmd->fixup &&
988
+							!(cmd->fixup_flags & FIXUP_F_FPARAM_RVE)) {
990 989
 							BUG("non-ct RVEs (%d) in module function call"
991 990
 									"that does not support them (%s)\n",
992
-									rve_param_no, cmd->c.name);
991
+									rve_param_no, cmd->name);
993 992
 							ret = E_BUG;
994 993
 							goto error;
995 994
 						}
... ...
@@ -150,6 +150,66 @@ int register_builtin_modules()
150 150
 
151 151
 
152 152
 
153
+/** convert cmd exports to current format.
154
+  * @param ver - module interface versions (0 == ser, 1 == kam).
155
+  * @param src - null terminated array of cmd exports
156
+  *              (either ser_cmd_export_t or kam_cmd_export_t, depending
157
+  *               on ver).
158
+  * @param mod - pointer to module exports structure.
159
+  * @return - pkg_malloc'ed null terminated sr_cmd_export_v31_t array with
160
+  *           the converted cmd exports  or 0 on error.
161
+  */
162
+static sr31_cmd_export_t* sr_cmd_exports_convert(unsigned ver,
163
+													void* src, void* mod)
164
+{
165
+	int i, n;
166
+	ser_cmd_export_t* ser_cmd;
167
+	kam_cmd_export_t* kam_cmd;
168
+	sr31_cmd_export_t* ret;
169
+	
170
+	ser_cmd = 0;
171
+	kam_cmd = 0;
172
+	ret = 0;
173
+	n = 0;
174
+	/* count the number of elements */
175
+	if (ver == 0) {
176
+		ser_cmd = src;
177
+		for (; ser_cmd[n].name; n++);
178
+	} else if (ver == 1) {
179
+		kam_cmd = src;
180
+		for (; kam_cmd[n].name; n++);
181
+	} else goto error; /* unknown interface version */
182
+	/* alloc & init new array */
183
+	ret = pkg_malloc(sizeof(*ret)*(n+1));
184
+	memset(ret, 0, sizeof(*ret)*(n+1));
185
+	/* convert/copy */
186
+	for (i=0; i < n; i++) {
187
+		if (ver == 0) {
188
+			ret[i].name = ser_cmd[i].name;
189
+			ret[i].function = ser_cmd[i].function;
190
+			ret[i].param_no = ser_cmd[i].param_no;
191
+			ret[i].fixup = ser_cmd[i].fixup;
192
+			ret[i].free_fixup = 0; /* no present in ser  <= 2.1 */
193
+			ret[i].flags = ser_cmd[i].flags;
194
+		} else {
195
+			ret[i].name = kam_cmd[i].name;
196
+			ret[i].function = kam_cmd[i].function;
197
+			ret[i].param_no = kam_cmd[i].param_no;
198
+			ret[i].fixup = kam_cmd[i].fixup;
199
+			ret[i].free_fixup = kam_cmd[i].free_fixup;
200
+			ret[i].flags = kam_cmd[i].flags;
201
+		}
202
+		/* 3.1+ specific stuff */
203
+		ret[i].fixup_flags = 0;
204
+		ret[i].module_exports = mod;
205
+	}
206
+	return ret;
207
+error:
208
+	return 0;
209
+}
210
+
211
+
212
+
153 213
 /* registers a module,  register_f= module register  functions
154 214
  * returns <0 on error, 0 on success */
155 215
 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,
169 169
 	memset(mod,0, sizeof(struct sr_module));
170 170
 	mod->path=path;
171 171
 	mod->handle=handle;
172
-	mod->mod_interface_ver=ver;
173
-	mod->exports=e;
174
-	mod->next=modules;
175
-	modules=mod;
172
+	mod->orig_mod_interface_ver=ver;
173
+	/* convert exports to sr31 format */
174
+	if (ver == 0) {
175
+		/* ser <= 3.0 */
176
+		mod->exports.name = e->v0.name;
177
+		if (e->v0.cmds) {
178
+			mod->exports.cmds = sr_cmd_exports_convert(ver, e->v0.cmds, mod);
179
+			if (mod->exports.cmds == 0) {
180
+				ERR("failed to convert module command exports to 3.1 format"
181
+						" for module \"%s\" (%s), interface version %d\n",
182
+						mod->exports.name, mod->path, ver);
183
+				ret = E_UNSPEC;
184
+				goto error;
185
+			}
186
+		}
187
+		mod->exports.params = e->v0.params;
188
+		mod->exports.init_f = e->v0.init_f;
189
+		mod->exports.response_f = e->v0.response_f;
190
+		mod->exports.destroy_f = e->v0.destroy_f;
191
+		mod->exports.onbreak_f = e->v0.onbreak_f;
192
+		mod->exports.init_child_f = e->v0.init_child_f;
193
+		mod->exports.dlflags = 0; /* not used in ser <= 3.0 */
194
+		mod->exports.rpc_methods = e->v0.rpc_methods;
195
+		/* the rest are 0, not used in ser */
196
+	} else if (ver == 1) {
197
+		/* kamailio <= 3.0 */
198
+		mod->exports.name = e->v1.name;
199
+		if (e->v1.cmds) {
200
+			mod->exports.cmds = sr_cmd_exports_convert(ver, e->v1.cmds, mod);
201
+			if (mod->exports.cmds == 0) {
202
+				ERR("failed to convert module command exports to 3.1 format"
203
+						" for module \"%s\" (%s), interface version %d\n",
204
+						mod->exports.name, mod->path, ver);
205
+				ret = E_UNSPEC;
206
+				goto error;
207
+			}
208
+		}
209
+		mod->exports.params = e->v1.params;
210
+		mod->exports.init_f = e->v1.init_f;
211
+		mod->exports.response_f = e->v1.response_f;
212
+		mod->exports.destroy_f = e->v1.destroy_f;
213
+		mod->exports.onbreak_f = 0; /* not used in k <= 3.0 */
214
+		mod->exports.init_child_f = e->v1.init_child_f;
215
+		mod->exports.dlflags = e->v1.dlflags;
216
+		mod->exports.rpc_methods = 0; /* not used in k <= 3.0 */
217
+		mod->exports.stats = e->v1.stats;
218
+		mod->exports.mi_cmds = e->v1.mi_cmds;
219
+		mod->exports.items = e->v1.items;
220
+		mod->exports.procs = e->v1.procs;
221
+	} else {
222
+		ERR("unsupported module interface version %d\n", ver);
223
+		ret = E_UNSPEC;
224
+		goto error;
225
+	}
176 226
 
177
-	if (ver==1 && e->v1.items) {
227
+	if (mod->exports.items) {
178 228
 		/* register module pseudo-variables for kamailio modules */
179
-		LM_DBG("register PV from: %s\n", e->c.name);
180
-		if (register_pvars_mod(e->c.name, e->v1.items)!=0) {
181
-			LM_ERR("failed to register pseudo-variables for module %s\n",
182
-				e->c.name);
183
-			pkg_free(mod);
184
-			return -1;
229
+		LM_DBG("register PV from: %s\n", mod->exports.name);
230
+		if (register_pvars_mod(mod->exports.name, mod->exports.items)!=0) {
231
+			LM_ERR("failed to register pseudo-variables for module %s (%s)\n",
232
+				mod->exports.name, path);
233
+			ret = E_UNSPEC;
234
+			goto error;
185 235
 		}
186
-	}else if (ver==0 && e->v0.rpc_methods){
236
+	}
237
+	if (mod->exports.rpc_methods){
187 238
 		/* register rpcs for ser modules */
188
-		i=rpc_register_array(e->v0.rpc_methods);
239
+		i=rpc_register_array(mod->exports.rpc_methods);
189 240
 		if (i<0){
190
-			ERR("failed to register RPCs for module %s\n", e->c.name);
241
+			ERR("failed to register RPCs for module %s (%s)\n",
242
+					mod->exports.name, path);
243
+			ret = E_UNSPEC;
191 244
 			goto error;
192 245
 		}else if (i>0){
193 246
 			ERR("%d duplicate RPCs name detected while registering RPCs"
194
-					" declared in modules %s\n", i, e->c.name);
247
+					" declared in module %s (%s)\n",
248
+					i, mod->exports.name, path);
249
+			ret = E_UNSPEC;
195 250
 			goto error;
196 251
 		}
197 252
 		/* i==0 => success */
198 253
 	}
199 254
 
255
+	/* link module in the list */
256
+	mod->next=modules;
257
+	modules=mod;
200 258
 	return 0;
201 259
 error:
260
+	if (mod)
261
+		pkg_free(mod);
202 262
 	return ret;
203 263
 }
204 264
 
... ...
@@ -473,51 +593,33 @@ skip:
473 473
 
474 474
 /* searches the module list for function name in module mod and returns 
475 475
  *  a pointer to the "name" function record union or 0 if not found
476
- * sets also *mod_if_ver to the module interface version (needed to know
477
- * which member of the union should be accessed v0 or v1)
476
+ * sets also *mod_if_ver to the original module interface version.
478 477
  * mod==0 is a wildcard matching all modules
479 478
  * flags parameter is OR value of all flags that must match
480 479
  */
481
-union cmd_export_u* find_mod_export_record(char* mod, char* name,
480
+sr31_cmd_export_t* find_mod_export_record(char* mod, char* name,
482 481
 											int param_no, int flags,
483 482
 											unsigned* mod_if_ver)
484 483
 {
485 484
 	struct sr_module* t;
486
-	union cmd_export_u* cmd;
487
-	int i;
488
-	unsigned mver;
489
-
490
-#define FIND_EXPORT_IN_MOD(VER) \
491
-		if (t->exports->VER.cmds) \
492
-			for(i=0, cmd=(void*)&t->exports->VER.cmds[0]; cmd->VER.name; \
493
-					i++, cmd=(void*)&t->exports->VER.cmds[i]){\
494
-				if((strcmp(name, cmd->VER.name)==0)&& \
495
-					((cmd->VER.param_no==param_no) || \
496
-					 (cmd->VER.param_no==VAR_PARAM_NO)) && \
497
-					((cmd->VER.flags & flags) == flags) \
498
-				){ \
499
-					DBG("find_export_record: found <%s> in module %s [%s]\n", \
500
-						name, t->exports->VER.name, t->path); \
501
-					*mod_if_ver=mver; \
502
-					return cmd; \
503
-				} \
504
-			}
485
+	sr31_cmd_export_t* cmd;
505 486
 
506 487
 	for(t=modules;t;t=t->next){
507
-		if (mod!=0 && (strcmp(t->exports->c.name, mod) !=0))
488
+		if (mod!=0 && (strcmp(t->exports.name, mod) !=0))
508 489
 			continue;
509
-		mver=t->mod_interface_ver;
510
-		switch (mver){
511
-			case 0:
512
-				FIND_EXPORT_IN_MOD(v0);
513
-				break;
514
-			case 1:
515
-				FIND_EXPORT_IN_MOD(v1);
516
-				break;
517
-			default:
518
-				BUG("invalid module interface version %d for modules %s\n",
519
-						t->mod_interface_ver, t->path);
520
-		}
490
+		if (t->exports.cmds)
491
+			for(cmd=&t->exports.cmds[0]; cmd->name; cmd++) {
492
+				if((strcmp(name, cmd->name) == 0) &&
493
+					((cmd->param_no == param_no) ||
494
+					 (cmd->param_no==VAR_PARAM_NO)) &&
495
+					((cmd->flags & flags) == flags)
496
+				){
497
+					DBG("find_export_record: found <%s> in module %s [%s]\n",
498
+						name, t->exports.name, t->path);
499
+					*mod_if_ver=t->orig_mod_interface_ver;
500
+					return cmd;
501
+				}
502
+			}
521 503
 	}
522 504
 	DBG("find_export_record: <%s> not found \n", name);
523 505
 	return 0;
... ...
@@ -532,7 +634,7 @@ union cmd_export_u* find_mod_export_record(char* mod, char* name,
532 532
  * mod==0 is a wildcard matching all modules
533 533
  * flags parameter is OR value of all flags that must match
534 534
  */
535
-union cmd_export_u* find_export_record(char* name,
535
+sr31_cmd_export_t* find_export_record(char* name,
536 536
 											int param_no, int flags,
537 537
 											unsigned* mod_if_ver)
538 538
 {
... ...
@@ -543,11 +645,11 @@ union cmd_export_u* find_export_record(char* name,
543 543
 
544 544
 cmd_function find_export(char* name, int param_no, int flags)
545 545
 {
546
-	union cmd_export_u* cmd;
546
+	sr31_cmd_export_t* cmd;
547 547
 	unsigned mver;
548 548
 	
549 549
 	cmd = find_export_record(name, param_no, flags, &mver);
550
-	return cmd?cmd->c.function:0;
550
+	return cmd?cmd->function:0;
551 551
 }
552 552
 
553 553
 
... ...
@@ -565,12 +667,12 @@ rpc_export_t* find_rpc_export(char* name, int flags)
565 565
  */
566 566
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
567 567
 {
568
-	union cmd_export_u* cmd;
568
+	sr31_cmd_export_t* cmd;
569 569
 	unsigned mver;
570 570
 
571 571
 	cmd=find_mod_export_record(mod, name, param_no, flags, &mver);
572 572
 	if (cmd)
573
-		return cmd->c.function;
573
+		return cmd->function;
574 574
 	
575 575
 	DBG("find_mod_export: <%s> in module <%s> not found\n", name, mod);
576 576
 	return 0;
... ...
@@ -581,7 +683,7 @@ struct sr_module* find_module_by_name(char* mod) {
581 581
 	struct sr_module* t;
582 582
 
583 583
 	for(t = modules; t; t = t->next) {
584
-		if (strcmp(mod, t->exports->c.name) == 0) {
584
+		if (strcmp(mod, t->exports.name) == 0) {
585 585
 			return t;
586 586
 		}
587 587
 	}
... ...
@@ -597,30 +699,17 @@ void* find_param_export(struct sr_module* mod, char* name,
597 597
 
598 598
 	if (!mod)
599 599
 		return 0;
600
-	param=0;
601
-	switch(mod->mod_interface_ver){
602
-		case 0:
603
-			param=mod->exports->v0.params;
604
-			break;
605
-		case 1:
606
-			param=mod->exports->v1.params;
607
-			break;
608
-		default:
609
-			BUG("bad module interface version %d in module %s [%s]\n",
610
-					mod->mod_interface_ver, mod->exports->c.name, mod->path);
611
-			return 0;
612
-	}
613
-	for(;param && param->name ; param++) {
600
+	for(param = mod->exports.params ;param && param->name ; param++) {
614 601
 		if ((strcmp(name, param->name) == 0) &&
615 602
 			((param->type & PARAM_TYPE_MASK(type_mask)) != 0)) {
616 603
 			DBG("find_param_export: found <%s> in module %s [%s]\n",
617
-				name, mod->exports->c.name, mod->path);
604
+				name, mod->exports.name, mod->path);
618 605
 			*param_type = param->type;
619 606
 			return param->param_pointer;
620 607
 		}
621 608
 	}
622 609
 	DBG("find_param_export: parameter <%s> not found in module <%s>\n",
623
-			name, mod->exports->c.name);
610
+			name, mod->exports.name);
624 611
 	return 0;
625 612
 }
626 613
 
... ...
@@ -632,19 +721,8 @@ void destroy_modules()
632 632
 	t=modules;
633 633
 	while(t) {
634 634
 		foo=t->next;
635
-		if (t->exports){
636
-			switch(t->mod_interface_ver){
637
-				case 0:
638
-					if ((t->exports->v0.destroy_f)) t->exports->v0.destroy_f();
639
-					break;
640
-				case 1:
641
-					if ((t->exports->v1.destroy_f)) t->exports->v1.destroy_f();
642
-					break;
643
-				default:
644
-					BUG("bad module interface version %d in module %s [%s]\n",
645
-						t->mod_interface_ver, t->exports->c.name,
646
-						t->path);
647
-			}
635
+		if (t->exports.destroy_f){
636
+			t->exports.destroy_f();
648 637
 		}
649 638
 		pkg_free(t);
650 639
 		t=foo;
... ...
@@ -667,36 +745,14 @@ int init_modules(void)
667 667
 	struct sr_module* t;
668 668
 
669 669
 	for(t = modules; t; t = t->next) {
670
-		if (t->exports){
671
-			switch(t->mod_interface_ver){
672
-				case 0:
673
-					if (t->exports->v0.init_f)
674
-						if (t->exports->v0.init_f() != 0) {
675
-							LOG(L_ERR, "init_modules(): Error while"
676
-										" initializing module %s\n",
677
-										t->exports->v0.name);
678
-							return -1;
679
-						}
680
-					if (t->exports->v0.response_f)
681
-						mod_response_cbk_no++;
682
-					break;
683
-				case 1:
684
-					if (t->exports->v1.init_f)
685
-						if (t->exports->v1.init_f() != 0) {
686
-							LOG(L_ERR, "init_modules(): Error while"
687
-										" initializing module %s\n",
688
-										t->exports->v1.name);
689
-							return -1;
690
-						}
691
-					if (t->exports->v1.response_f)
692
-						mod_response_cbk_no++;
693
-					break;
694
-				default:
695
-					BUG("bad module interface version %d in module %s [%s]\n",
696
-						t->exports->c.name, t->path);
697
-					return -1;
670
+		if (t->exports.init_f)
671
+			if (t->exports.init_f() != 0) {
672
+				LOG(L_ERR, "init_modules(): Error while"
673
+						" initializing module %s\n", t->exports.name);
674
+				return -1;
698 675
 			}
699
-		}
676
+		if (t->exports.response_f)
677
+			mod_response_cbk_no++;
700 678
 	}
701 679
 	mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
702 680
 									sizeof(response_function));
... ...
@@ -705,27 +761,17 @@ int init_modules(void)
705 705
 					" for %d response_f callbacks\n", mod_response_cbk_no);
706 706
 		return -1;
707 707
 	}
708
-	for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
709
-		if (t->exports){
710
-			switch(t->mod_interface_ver){
711
-				case 0:
712
-					if (t->exports->v0.response_f){
713
-						mod_response_cbks[i]=t->exports->v0.response_f;
714
-						i++;
715
-					}
716
-					break;
717
-				case 1:
718
-					if (t->exports->v1.response_f){
719
-						mod_response_cbks[i]=t->exports->v1.response_f;
720
-						i++;
721
-					}
722
-					break;
723
-			}
708
+	for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next) {
709
+		if (t->exports.response_f) {
710
+			mod_response_cbks[i]=t->exports.response_f;
711
+			i++;
724 712
 		}
725 713
 	}
726 714
 	return 0;
727 715
 }
728 716
 
717
+
718
+
729 719
 /*
730 720
  * per-child initialization
731 721
  */
... ...
@@ -745,30 +791,12 @@ int init_child(int rank)
745 745
 
746 746
 
747 747
 	for(t = modules; t; t = t->next) {
748
-		switch(t->mod_interface_ver){
749
-			case 0:
750
-				if (t->exports->v0.init_child_f) {
751
-					if ((t->exports->v0.init_child_f(rank)) < 0) {
752
-						LOG(L_ERR, "init_child(): Initialization of child"
753
-									" %d failed\n", rank);
754
-						return -1;
755
-					}
756
-				}
757
-				break;
758
-			case 1:
759
-				if (t->exports->v1.init_child_f) {
760
-					if ((t->exports->v1.init_child_f(rank)) < 0) {
761
-						LOG(L_ERR, "init_child(): Initialization of child"
762
-									" %d failed\n", rank);
763
-						return -1;
764
-					}
765
-				}
766
-				break;
767
-			default:
768
-				BUG("bad module interface version %d in module %s [%s]\n",
769
-						t->mod_interface_ver, t->exports->c.name,
770
-						t->path);
748
+		if (t->exports.init_child_f) {
749
+			if ((t->exports.init_child_f(rank)) < 0) {
750
+				LOG(L_ERR, "init_child(): Initialization of child"
751
+							" %d failed\n", rank);
771 752
 				return -1;
753
+			}
772 754
 		}
773 755
 	}
774 756
 	return 0;
... ...
@@ -789,43 +817,19 @@ static int init_mod_child( struct sr_module* m, int rank )
789 789
 		   propagate it up the stack
790 790
 		 */
791 791
 		if (init_mod_child(m->next, rank)!=0) return -1;
792
-		if (m->exports){
793
-			switch(m->mod_interface_ver){
794
-				case 0:
795
-					if (m->exports->v0.init_child_f) {
796
-						DBG("DEBUG: init_mod_child (%d): %s\n",
797
-								rank, m->exports->v0.name);
798
-						if (m->exports->v0.init_child_f(rank)<0) {
799
-							LOG(L_ERR, "init_mod_child(): Error while"
800
-										" initializing module %s\n",
801
-										m->exports->v0.name);
802
-							return -1;
803
-						} else {
804
-							/* module correctly initialized */
805
-							return 0;
806
-						}
807
-					}
808
-					/* no init function -- proceed with success */
809
-					return 0;
810
-				case 1:
811
-					if (m->exports->v1.init_child_f) {
812
-						DBG("DEBUG: init_mod_child (%d): %s\n",
813
-								rank, m->exports->v1.name);
814
-						if (m->exports->v1.init_child_f(rank)<0) {
815
-							LOG(L_ERR, "init_mod_child(): Error while"
816
-										" initializing module %s\n",
817
-										m->exports->v1.name);
818
-							return -1;
819
-						} else {
820
-							/* module correctly initialized */
821
-							return 0;
822
-						}
823
-					}
824
-					/* no init function -- proceed with success */
825
-					return 0;
792
+		if (m->exports.init_child_f) {
793
+			DBG("DEBUG: init_mod_child (%d): %s\n", rank, m->exports.name);
794
+			if (m->exports.init_child_f(rank)<0) {
795
+				LOG(L_ERR, "init_mod_child(): Error while"
796
+							" initializing module %s (%s)\n",
797
+							m->exports.name, m->path);
798
+				return -1;
799
+			} else {
800
+				/* module correctly initialized */
801
+				return 0;
826 802
 			}
827 803
 		}
828
-		/* no exports -- proceed with success */
804
+		/* no init function -- proceed with success */
829 805
 		return 0;
830 806
 	} else {
831 807
 		/* end of list */
... ...
@@ -856,40 +860,20 @@ static int init_mod( struct sr_module* m )
856 856
 		   propagate it up the stack
857 857
 		 */
858 858
 		if (init_mod(m->next)!=0) return -1;
859
-		if (m->exports){
860
-			switch(m->mod_interface_ver){
861
-				case 0:
862
-					if ( m->exports->v0.init_f) {
863
-						DBG("DEBUG: init_mod: %s\n", m->exports->v0.name);
864
-						if (m->exports->v0.init_f()!=0) {
865
-							LOG(L_ERR, "init_mod(): Error while initializing"
866
-										" module %s\n", m->exports->v0.name);
867
-							return -1;
868
-						} else {
869
-							/* module correctly initialized */
870
-							return 0;
871
-						}
872
-					}
873
-					/* no init function -- proceed with success */
874
-					return 0;
875
-				case 1:
876
-					if ( m->exports->v1.init_f) {
877
-						DBG("DEBUG: init_mod: %s\n", m->exports->v1.name);
878
-						if (m->exports->v1.init_f()!=0) {
879
-							LOG(L_ERR, "init_mod(): Error while initializing"
880
-										" module %s\n", m->exports->v1.name);
881
-							return -1;
882
-						} else {
883
-							/* module correctly initialized */
884
-							return 0;
885
-						}
886
-					}
887
-					/* no init function -- proceed with success */
859
+			if (m->exports.init_f) {
860
+				DBG("DEBUG: init_mod: %s\n", m->exports.name);
861
+				if (m->exports.init_f()!=0) {
862
+					LOG(L_ERR, "init_mod(): Error while initializing"
863
+								" module %s (%s)\n",
864
+								m->exports.name, m->path);
865
+					return -1;
866
+				} else {
867
+					/* module correctly initialized */
888 868
 					return 0;
869
+				}
889 870
 			}
890
-		}
891
-		/* no exports -- proceed with success */
892
-		return 0;
871
+			/* no init function -- proceed with success */
872
+			return 0;
893 873
 	} else {
894 874
 		/* end of list */
895 875
 		return 0;
... ...
@@ -910,18 +894,8 @@ int init_modules(void)
910 910
 		return i;
911 911
 
912 912
 	for(t = modules; t; t = t->next)
913
-		if (t->exports){
914
-			switch(t->mod_interface_ver){
915
-				case 0:
916
-					if (t->exports->v0.response_f)
917
-						mod_response_cbk_no++;
918
-					break;
919
-				case 1:
920
-					if (t->exports->v1.response_f)
921
-						mod_response_cbk_no++;
922
-					break;
923
-			}
924
-		}
913
+		if (t->exports.response_f)
914
+			mod_response_cbk_no++;
925 915
 	mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
926 916
 									sizeof(response_function));
927 917
 	if (mod_response_cbks==0){
... ...
@@ -929,24 +903,11 @@ int init_modules(void)
929 929
 					" for %d response_f callbacks\n", mod_response_cbk_no);
930 930
 		return -1;
931 931
 	}
932
-	for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
933
-		if (t->exports){
934
-			switch(t->mod_interface_ver){
935
-				case 0:
936
-					if (t->exports->v0.response_f){
937
-						mod_response_cbks[i]=t->exports->v0.response_f;
938
-						i++;
939
-					}
940
-					break;
941
-				case 1:
942
-					if (t->exports->v1.response_f){
943
-						mod_response_cbks[i]=t->exports->v1.response_f;
944
-						i++;
945
-					}
946
-					break;
947
-			}
932
+	for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next)
933
+		if (t->exports.response_f) {
934
+			mod_response_cbks[i]=t->exports.response_f;
935
+			i++;
948 936
 		}
949
-	}
950 937
 	
951 938
 	return 0;
952 939
 }
... ...
@@ -153,12 +153,9 @@ typedef int (*param_func_t)( modparam_t type, void* val);
153 153
  * They are kept in the first 2 bits inside the pointer
154 154
  */
155 155
 #define FIXUP_F_FPARAM_RVE (unsigned long)1 /* fparam fixup, rve ready */
156
-#define FIXUP_F_RESERVED (unsigned long)2  /* not used for now */
157
-#define FIXUP_MASK (~((unsigned long)3)) /* mask for obtainin the pointer val*/
158 156
 
159 157
 #define call_fixup(fixup, param, param_no) \
160
-	(((long)(fixup) & FIXUP_MASK)? \
161
-		(((fixup_function)((long)(fixup) & FIXUP_MASK))(param, param_no)):0)
158
+	((fixup) ? (fixup)(param, param_no) : 0)
162 159
 
163 160
 /* Macros - used as rank in child_init function */
164 161
 #define PROC_MAIN      0  /* Main ser process */
... ...
@@ -223,6 +220,20 @@ struct kam_cmd_export_ {
223 223
 };
224 224
 
225 225
 
226
+struct sr31_cmd_export_ {
227
+	char* name;             /* null terminated command name */
228
+	cmd_function function;  /* pointer to the corresponding function */
229
+	int param_no;           /* number of parameters used by the function */
230
+	fixup_function fixup;   /* pointer to the function called to "fix" the
231
+							   parameters */
232
+	free_fixup_function free_fixup; /* function called to free the "fixed"
233
+									   parameters */
234
+	int flags;              /* Function flags */
235
+	int fixup_flags;
236
+	void* module_exports; /* pointer to module structure */
237
+};
238
+
239
+
226 240
 /* members situated at the same place in memory in both ser & kamailio
227 241
    cmd_export */
228 242
 struct cmd_export_common_ {
... ...
@@ -288,12 +299,15 @@ typedef struct param_export_ param_export_t;
288 288
 typedef struct ser_cmd_export_ ser_cmd_export_t;
289 289
 typedef struct kam_cmd_export_ kam_cmd_export_t;
290 290
 typedef struct cmd_export_common_ cmd_export_common_t;
291
+typedef struct sr31_cmd_export_ sr31_cmd_export_t;
291 292
 
293
+#if 0
292 294
 union cmd_export_u{
293 295
 	cmd_export_common_t c; /* common members for everybody */
294 296
 	ser_cmd_export_t v0;
295 297
 	kam_cmd_export_t v1;
296 298
 };
299
+#endif
297 300
 
298 301
 
299 302
 /* ser module exports version */
... ...
@@ -361,6 +375,47 @@ struct kam_module_exports {
361 361
 
362 362
 
363 363
 
364
+/** sr/ser 3.1+ module exports version.
365
+ * Includes ser and kamailio versions, re-arraranged + some extras.
366
+ * Note: some of the members will be obsoleted and are kept only for
367
+ * backward compatibility (avoid re-writing all the modules exports
368
+ * declarations).
369
+ */
370
+struct sr31_module_exports {
371
+	char* name;                     /* null terminated module name */
372
+	sr31_cmd_export_t* cmds;      /* null terminated array of the exported
373
+									   commands */
374
+	param_export_t* params;         /* null terminated array of the exported
375
+									   module parameters */
376
+	init_function init_f;           /* Initialization function */
377
+	response_function response_f;   /* function used for responses,
378
+									   returns yes or no; can be null */
379
+	destroy_function destroy_f;     /* function called when the module should
380
+									   be "destroyed", e.g: on ser exit;
381
+									   can be null */
382
+	onbreak_function onbreak_f;
383
+	child_init_function init_child_f;  /* function called by all processes
384
+										  after the fork */
385
+	unsigned int dlflags;           /**< flags for dlopen */
386
+	/* ser specific exports
387
+	   (to be obsoleted and replaced by register_...) */
388
+	rpc_export_t* rpc_methods;      /* null terminated array of exported
389
+									   rpc methods */
390
+	/* kamailio specific exports
391
+	   (to be obsoleted and replaced by register_...) */
392
+	stat_export_t* stats;			/*!< null terminated array of the exported
393
+									  module statistics */
394
+	mi_export_t* mi_cmds;			/*!< null terminated array of the exported
395
+									  MI functions */
396
+	pv_export_t* items;				/*!< null terminated array of the exported
397
+									   module items (pseudo-variables) */
398
+	proc_export_t* procs;			/*!< null terminated array of the
399
+									  additional processes required by the
400
+									  module */
401
+};
402
+
403
+
404
+
364 405
 /* module exports in the same place in memory in both ser & kamailio */
365 406
 struct module_exports_common{
366 407
 	char* name;
... ...
@@ -377,8 +432,8 @@ union module_exports_u {
377 377
 struct sr_module{
378 378
 	char* path;
379 379
 	void* handle;
380
-	unsigned int mod_interface_ver;
381
-	union module_exports_u* exports;
380
+	unsigned int orig_mod_interface_ver;
381
+	struct sr31_module_exports exports;
382 382
 	struct sr_module* next;
383 383
 };
384 384
 
... ...
@@ -388,9 +443,8 @@ extern response_function* mod_response_cbks;/* response callback array */
388 388
 extern int mod_response_cbk_no;    /* size of reponse callbacks array */
389 389
 
390 390
 int register_builtin_modules(void);
391
-/*int register_module(unsigned , struct module_exports*, char*,  void*);*/
392 391
 int load_module(char* path);
393
-union cmd_export_u* find_export_record(char* name, int param_no, int flags,
392
+sr31_cmd_export_t* find_export_record(char* name, int param_no, int flags,
394 393
 										unsigned *ver);
395 394
 cmd_function find_export(char* name, int param_no, int flags);
396 395
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags);