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 3766
 					/* out of mem or bug ? */
3769 3767
 					rval_destroy(rv);
3770 3768
 					yyerror_at(&rve->fpos, "function %s: bad parameter %d"
3771
-									" expression\n", cmd_exp->c.name, r+1);
3769
+									" expression\n", cmd_exp->name, r+1);
3772 3770
 					return -1;
3773 3771
 				}
3774 3772
 				rval_destroy(rv);
... ...
@@ -3796,12 +3794,10 @@ static int mod_f_params_pre_fixup(struct action* a)
3796 3794
  */
3797 3795
 static void free_mod_func_action(struct action* a)
3798 3796
 {
3799
-	union cmd_export_u* cmd_exp;
3800 3797
 	action_u_t* params;
3801 3798
 	int param_no;
3802 3799
 	int r;
3803 3800
 	
3804
-	cmd_exp = a->val[0].u.data;
3805 3801
 	param_no = a->val[1].u.number;
3806 3802
 	params = &a->val[2];
3807 3803
 	
... ...
@@ -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 229
 	memset(mod,0, sizeof(struct sr_module));
170 230
 	mod->path=path;
171 231
 	mod->handle=handle;
172
-	mod->mod_interface_ver=ver;
173
-	mod->exports=e;
174
-	mod->next=modules;
175
-	modules=mod;
232
+	mod->orig_mod_interface_ver=ver;
233
+	/* convert exports to sr31 format */
234
+	if (ver == 0) {
235
+		/* ser <= 3.0 */
236
+		mod->exports.name = e->v0.name;
237
+		if (e->v0.cmds) {
238
+			mod->exports.cmds = sr_cmd_exports_convert(ver, e->v0.cmds, mod);
239
+			if (mod->exports.cmds == 0) {
240
+				ERR("failed to convert module command exports to 3.1 format"
241
+						" for module \"%s\" (%s), interface version %d\n",
242
+						mod->exports.name, mod->path, ver);
243
+				ret = E_UNSPEC;
244
+				goto error;
245
+			}
246
+		}
247
+		mod->exports.params = e->v0.params;
248
+		mod->exports.init_f = e->v0.init_f;
249
+		mod->exports.response_f = e->v0.response_f;
250
+		mod->exports.destroy_f = e->v0.destroy_f;
251
+		mod->exports.onbreak_f = e->v0.onbreak_f;
252
+		mod->exports.init_child_f = e->v0.init_child_f;
253
+		mod->exports.dlflags = 0; /* not used in ser <= 3.0 */
254
+		mod->exports.rpc_methods = e->v0.rpc_methods;
255
+		/* the rest are 0, not used in ser */
256
+	} else if (ver == 1) {
257
+		/* kamailio <= 3.0 */
258
+		mod->exports.name = e->v1.name;
259
+		if (e->v1.cmds) {
260
+			mod->exports.cmds = sr_cmd_exports_convert(ver, e->v1.cmds, mod);
261
+			if (mod->exports.cmds == 0) {
262
+				ERR("failed to convert module command exports to 3.1 format"
263
+						" for module \"%s\" (%s), interface version %d\n",
264
+						mod->exports.name, mod->path, ver);
265
+				ret = E_UNSPEC;
266
+				goto error;
267
+			}
268
+		}
269
+		mod->exports.params = e->v1.params;
270
+		mod->exports.init_f = e->v1.init_f;
271
+		mod->exports.response_f = e->v1.response_f;
272
+		mod->exports.destroy_f = e->v1.destroy_f;
273
+		mod->exports.onbreak_f = 0; /* not used in k <= 3.0 */
274
+		mod->exports.init_child_f = e->v1.init_child_f;
275
+		mod->exports.dlflags = e->v1.dlflags;
276
+		mod->exports.rpc_methods = 0; /* not used in k <= 3.0 */
277
+		mod->exports.stats = e->v1.stats;
278
+		mod->exports.mi_cmds = e->v1.mi_cmds;
279
+		mod->exports.items = e->v1.items;
280
+		mod->exports.procs = e->v1.procs;
281
+	} else {
282
+		ERR("unsupported module interface version %d\n", ver);
283
+		ret = E_UNSPEC;
284
+		goto error;
285
+	}
176 286
 
177
-	if (ver==1 && e->v1.items) {
287
+	if (mod->exports.items) {
178 288
 		/* 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;
289
+		LM_DBG("register PV from: %s\n", mod->exports.name);
290
+		if (register_pvars_mod(mod->exports.name, mod->exports.items)!=0) {
291
+			LM_ERR("failed to register pseudo-variables for module %s (%s)\n",
292
+				mod->exports.name, path);
293
+			ret = E_UNSPEC;
294
+			goto error;
185 295
 		}
186
-	}else if (ver==0 && e->v0.rpc_methods){
296
+	}
297
+	if (mod->exports.rpc_methods){
187 298
 		/* register rpcs for ser modules */
188
-		i=rpc_register_array(e->v0.rpc_methods);
299
+		i=rpc_register_array(mod->exports.rpc_methods);
189 300
 		if (i<0){
190
-			ERR("failed to register RPCs for module %s\n", e->c.name);
301
+			ERR("failed to register RPCs for module %s (%s)\n",
302
+					mod->exports.name, path);
303
+			ret = E_UNSPEC;
191 304
 			goto error;
192 305
 		}else if (i>0){
193 306
 			ERR("%d duplicate RPCs name detected while registering RPCs"
194
-					" declared in modules %s\n", i, e->c.name);
307
+					" declared in module %s (%s)\n",
308
+					i, mod->exports.name, path);
309
+			ret = E_UNSPEC;
195 310
 			goto error;
196 311
 		}
197 312
 		/* i==0 => success */
198 313
 	}
199 314
 
315
+	/* link module in the list */
316
+	mod->next=modules;
317
+	modules=mod;
200 318
 	return 0;
201 319
 error:
320
+	if (mod)
321
+		pkg_free(mod);
202 322
 	return ret;
203 323
 }
204 324
 
... ...
@@ -473,51 +593,33 @@ skip:
473 593
 
474 594
 /* searches the module list for function name in module mod and returns 
475 595
  *  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)
596
+ * sets also *mod_if_ver to the original module interface version.
478 597
  * mod==0 is a wildcard matching all modules
479 598
  * flags parameter is OR value of all flags that must match
480 599
  */
481
-union cmd_export_u* find_mod_export_record(char* mod, char* name,
600
+sr31_cmd_export_t* find_mod_export_record(char* mod, char* name,
482 601
 											int param_no, int flags,
483 602
 											unsigned* mod_if_ver)
484 603
 {
485 604
 	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
-			}
605
+	sr31_cmd_export_t* cmd;
505 606
 
506 607
 	for(t=modules;t;t=t->next){
507
-		if (mod!=0 && (strcmp(t->exports->c.name, mod) !=0))
608
+		if (mod!=0 && (strcmp(t->exports.name, mod) !=0))
508 609
 			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
-		}
610
+		if (t->exports.cmds)
611
+			for(cmd=&t->exports.cmds[0]; cmd->name; cmd++) {
612
+				if((strcmp(name, cmd->name) == 0) &&
613
+					((cmd->param_no == param_no) ||
614
+					 (cmd->param_no==VAR_PARAM_NO)) &&
615
+					((cmd->flags & flags) == flags)
616
+				){
617
+					DBG("find_export_record: found <%s> in module %s [%s]\n",
618
+						name, t->exports.name, t->path);
619
+					*mod_if_ver=t->orig_mod_interface_ver;
620
+					return cmd;
621
+				}
622
+			}
521 623
 	}
522 624
 	DBG("find_export_record: <%s> not found \n", name);
523 625
 	return 0;
... ...
@@ -532,7 +634,7 @@ union cmd_export_u* find_mod_export_record(char* mod, char* name,
532 634
  * mod==0 is a wildcard matching all modules
533 635
  * flags parameter is OR value of all flags that must match
534 636
  */
535
-union cmd_export_u* find_export_record(char* name,
637
+sr31_cmd_export_t* find_export_record(char* name,
536 638
 											int param_no, int flags,
537 639
 											unsigned* mod_if_ver)
538 640
 {
... ...
@@ -543,11 +645,11 @@ union cmd_export_u* find_export_record(char* name,
543 645
 
544 646
 cmd_function find_export(char* name, int param_no, int flags)
545 647
 {
546
-	union cmd_export_u* cmd;
648
+	sr31_cmd_export_t* cmd;
547 649
 	unsigned mver;
548 650
 	
549 651
 	cmd = find_export_record(name, param_no, flags, &mver);
550
-	return cmd?cmd->c.function:0;
652
+	return cmd?cmd->function:0;
551 653
 }
552 654
 
553 655
 
... ...
@@ -565,12 +667,12 @@ rpc_export_t* find_rpc_export(char* name, int flags)
565 667
  */
566 668
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
567 669
 {
568
-	union cmd_export_u* cmd;
670
+	sr31_cmd_export_t* cmd;
569 671
 	unsigned mver;
570 672
 
571 673
 	cmd=find_mod_export_record(mod, name, param_no, flags, &mver);
572 674
 	if (cmd)
573
-		return cmd->c.function;
675
+		return cmd->function;
574 676
 	
575 677
 	DBG("find_mod_export: <%s> in module <%s> not found\n", name, mod);
576 678
 	return 0;
... ...
@@ -581,7 +683,7 @@ struct sr_module* find_module_by_name(char* mod) {
581 683
 	struct sr_module* t;
582 684
 
583 685
 	for(t = modules; t; t = t->next) {
584
-		if (strcmp(mod, t->exports->c.name) == 0) {
686
+		if (strcmp(mod, t->exports.name) == 0) {
585 687
 			return t;
586 688
 		}
587 689
 	}
... ...
@@ -597,30 +699,17 @@ void* find_param_export(struct sr_module* mod, char* name,
597 699
 
598 700
 	if (!mod)
599 701
 		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++) {
702
+	for(param = mod->exports.params ;param && param->name ; param++) {
614 703
 		if ((strcmp(name, param->name) == 0) &&
615 704
 			((param->type & PARAM_TYPE_MASK(type_mask)) != 0)) {
616 705
 			DBG("find_param_export: found <%s> in module %s [%s]\n",
617
-				name, mod->exports->c.name, mod->path);
706
+				name, mod->exports.name, mod->path);
618 707
 			*param_type = param->type;
619 708
 			return param->param_pointer;
620 709
 		}
621 710
 	}
622 711
 	DBG("find_param_export: parameter <%s> not found in module <%s>\n",
623
-			name, mod->exports->c.name);
712
+			name, mod->exports.name);
624 713
 	return 0;
625 714
 }
626 715
 
... ...
@@ -632,19 +721,8 @@ void destroy_modules()
632 721
 	t=modules;
633 722
 	while(t) {
634 723
 		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
-			}
724
+		if (t->exports.destroy_f){
725
+			t->exports.destroy_f();
648 726
 		}
649 727
 		pkg_free(t);
650 728
 		t=foo;
... ...
@@ -667,36 +745,14 @@ int init_modules(void)
667 745
 	struct sr_module* t;
668 746
 
669 747
 	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;
748
+		if (t->exports.init_f)
749
+			if (t->exports.init_f() != 0) {
750
+				LOG(L_ERR, "init_modules(): Error while"
751
+						" initializing module %s\n", t->exports.name);
752
+				return -1;
698 753
 			}
699
-		}
754
+		if (t->exports.response_f)
755
+			mod_response_cbk_no++;
700 756
 	}
701 757
 	mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
702 758
 									sizeof(response_function));
... ...
@@ -705,27 +761,17 @@ int init_modules(void)
705 761
 					" for %d response_f callbacks\n", mod_response_cbk_no);
706 762
 		return -1;
707 763
 	}
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
-			}
764
+	for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next) {
765
+		if (t->exports.response_f) {
766
+			mod_response_cbks[i]=t->exports.response_f;
767
+			i++;
724 768
 		}
725 769
 	}
726 770
 	return 0;
727 771
 }
728 772
 
773
+
774
+
729 775
 /*
730 776
  * per-child initialization
731 777
  */
... ...
@@ -745,30 +791,12 @@ int init_child(int rank)
745 791
 
746 792
 
747 793
 	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);
794
+		if (t->exports.init_child_f) {
795
+			if ((t->exports.init_child_f(rank)) < 0) {
796
+				LOG(L_ERR, "init_child(): Initialization of child"
797
+							" %d failed\n", rank);
771 798
 				return -1;
799
+			}
772 800
 		}
773 801
 	}
774 802
 	return 0;
... ...
@@ -789,43 +817,19 @@ static int init_mod_child( struct sr_module* m, int rank )
789 817
 		   propagate it up the stack
790 818
 		 */
791 819
 		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;
820
+		if (m->exports.init_child_f) {
821
+			DBG("DEBUG: init_mod_child (%d): %s\n", rank, m->exports.name);
822
+			if (m->exports.init_child_f(rank)<0) {
823
+				LOG(L_ERR, "init_mod_child(): Error while"
824
+							" initializing module %s (%s)\n",
825
+							m->exports.name, m->path);
826
+				return -1;
827
+			} else {
828
+				/* module correctly initialized */
829
+				return 0;
826 830
 			}
827 831
 		}
828
-		/* no exports -- proceed with success */
832
+		/* no init function -- proceed with success */
829 833
 		return 0;
830 834
 	} else {
831 835
 		/* end of list */
... ...
@@ -856,40 +860,20 @@ static int init_mod( struct sr_module* m )
856 860
 		   propagate it up the stack
857 861
 		 */
858 862
 		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 */
863
+			if (m->exports.init_f) {
864
+				DBG("DEBUG: init_mod: %s\n", m->exports.name);
865
+				if (m->exports.init_f()!=0) {
866
+					LOG(L_ERR, "init_mod(): Error while initializing"
867
+								" module %s (%s)\n",
868
+								m->exports.name, m->path);
869
+					return -1;
870
+				} else {
871
+					/* module correctly initialized */
888 872
 					return 0;
873
+				}
889 874
 			}
890
-		}
891
-		/* no exports -- proceed with success */
892
-		return 0;
875
+			/* no init function -- proceed with success */
876
+			return 0;
893 877
 	} else {
894 878
 		/* end of list */
895 879
 		return 0;
... ...
@@ -910,18 +894,8 @@ int init_modules(void)
910 894
 		return i;
911 895
 
912 896
 	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
-		}
897
+		if (t->exports.response_f)
898
+			mod_response_cbk_no++;
925 899
 	mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
926 900
 									sizeof(response_function));
927 901
 	if (mod_response_cbks==0){
... ...
@@ -929,24 +903,11 @@ int init_modules(void)
929 903
 					" for %d response_f callbacks\n", mod_response_cbk_no);
930 904
 		return -1;
931 905
 	}
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
-			}
906
+	for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next)
907
+		if (t->exports.response_f) {
908
+			mod_response_cbks[i]=t->exports.response_f;
909
+			i++;
948 910
 		}
949
-	}
950 911
 	
951 912
 	return 0;
952 913
 }
... ...
@@ -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 220
 };
224 221
 
225 222
 
223
+struct sr31_cmd_export_ {
224
+	char* name;             /* null terminated command name */
225
+	cmd_function function;  /* pointer to the corresponding function */
226
+	int param_no;           /* number of parameters used by the function */
227
+	fixup_function fixup;   /* pointer to the function called to "fix" the
228
+							   parameters */
229
+	free_fixup_function free_fixup; /* function called to free the "fixed"
230
+									   parameters */
231
+	int flags;              /* Function flags */
232
+	int fixup_flags;
233
+	void* module_exports; /* pointer to module structure */
234
+};
235
+
236
+
226 237
 /* members situated at the same place in memory in both ser & kamailio
227 238
    cmd_export */
228 239
 struct cmd_export_common_ {
... ...
@@ -288,12 +299,15 @@ typedef struct param_export_ param_export_t;
288 299
 typedef struct ser_cmd_export_ ser_cmd_export_t;
289 300
 typedef struct kam_cmd_export_ kam_cmd_export_t;
290 301
 typedef struct cmd_export_common_ cmd_export_common_t;
302
+typedef struct sr31_cmd_export_ sr31_cmd_export_t;
291 303
 
304
+#if 0
292 305
 union cmd_export_u{
293 306
 	cmd_export_common_t c; /* common members for everybody */
294 307
 	ser_cmd_export_t v0;
295 308
 	kam_cmd_export_t v1;
296 309
 };
310
+#endif
297 311
 
298 312
 
299 313
 /* ser module exports version */
... ...
@@ -361,6 +375,47 @@ struct kam_module_exports {
361 375
 
362 376
 
363 377
 
378
+/** sr/ser 3.1+ module exports version.
379
+ * Includes ser and kamailio versions, re-arraranged + some extras.
380
+ * Note: some of the members will be obsoleted and are kept only for
381
+ * backward compatibility (avoid re-writing all the modules exports
382
+ * declarations).
383
+ */
384
+struct sr31_module_exports {
385
+	char* name;                     /* null terminated module name */
386
+	sr31_cmd_export_t* cmds;      /* null terminated array of the exported
387
+									   commands */
388
+	param_export_t* params;         /* null terminated array of the exported
389
+									   module parameters */
390
+	init_function init_f;           /* Initialization function */
391
+	response_function response_f;   /* function used for responses,
392
+									   returns yes or no; can be null */
393
+	destroy_function destroy_f;     /* function called when the module should
394
+									   be "destroyed", e.g: on ser exit;
395
+									   can be null */
396
+	onbreak_function onbreak_f;
397
+	child_init_function init_child_f;  /* function called by all processes
398
+										  after the fork */
399
+	unsigned int dlflags;           /**< flags for dlopen */
400
+	/* ser specific exports
401
+	   (to be obsoleted and replaced by register_...) */
402
+	rpc_export_t* rpc_methods;      /* null terminated array of exported
403
+									   rpc methods */
404
+	/* kamailio specific exports
405
+	   (to be obsoleted and replaced by register_...) */
406
+	stat_export_t* stats;			/*!< null terminated array of the exported
407
+									  module statistics */
408
+	mi_export_t* mi_cmds;			/*!< null terminated array of the exported
409
+									  MI functions */
410
+	pv_export_t* items;				/*!< null terminated array of the exported
411
+									   module items (pseudo-variables) */
412
+	proc_export_t* procs;			/*!< null terminated array of the
413
+									  additional processes required by the
414
+									  module */
415
+};
416
+
417
+
418
+
364 419
 /* module exports in the same place in memory in both ser & kamailio */
365 420
 struct module_exports_common{
366 421
 	char* name;
... ...
@@ -377,8 +432,8 @@ union module_exports_u {
377 432
 struct sr_module{
378 433
 	char* path;
379 434
 	void* handle;
380
-	unsigned int mod_interface_ver;
381
-	union module_exports_u* exports;
435
+	unsigned int orig_mod_interface_ver;
436
+	struct sr31_module_exports exports;
382 437
 	struct sr_module* next;
383 438
 };
384 439
 
... ...
@@ -388,9 +443,8 @@ extern response_function* mod_response_cbks;/* response callback array */
388 443
 extern int mod_response_cbk_no;    /* size of reponse callbacks array */
389 444
 
390 445
 int register_builtin_modules(void);
391
-/*int register_module(unsigned , struct module_exports*, char*,  void*);*/
392 446
 int load_module(char* path);
393
-union cmd_export_u* find_export_record(char* name, int param_no, int flags,
447
+sr31_cmd_export_t* find_export_record(char* name, int param_no, int flags,
394 448
 										unsigned *ver);
395 449
 cmd_function find_export(char* name, int param_no, int flags);
396 450
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags);