Browse code

dual module interface support: ser and kamailio

Added support for both ser and kamailio module interfaces: a module
just needs to define its module interface prior to including sr_module.h
(e.g. by adding EXTRA_DEFS+=-DSER_MOD_INTERFACE for a ser module or
EXTRA_DEFS+=-DKAMAILIO_MOD_INTERFACE to the module Makefile).
This way ser and kamailio modules can be mixed at will with only one
Makefile change.
Under the hood, now each module declares its interface version (by
exporting a global symbol named module_interface_ver) and the internal
module loader and module export finder were updated to take the interface
version into account.
Internally the core works now with a generic module_export_u union.

Andrei Pelinescu-Onciul authored on 17/11/2008 23:48:59
Showing 7 changed files
... ...
@@ -716,8 +716,9 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
716 716
 				}
717 717
 			break;
718 718
 		case MODULE_T:
719
-			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && ((cmd_export_t*)a->val[0].u.data)->function ){
720
-				ret=((cmd_export_t*)a->val[0].u.data)->function(msg,
719
+			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
720
+					((union cmd_export_u*)a->val[0].u.data)->c.function){
721
+				ret=((union cmd_export_u*)a->val[0].u.data)->c.function(msg,
721 722
 					(char*)a->val[2].u.data,
722 723
 					(char*)a->val[3].u.data
723 724
 				);
... ...
@@ -976,9 +977,11 @@ end:
976 976
 	/* process module onbreak handlers if present */
977 977
 	if (h->rec_lev==0 && ret==0)
978 978
 		for (mod=modules;mod;mod=mod->next)
979
-			if (mod->exports && mod->exports->onbreak_f) {
980
-				mod->exports->onbreak_f( msg );
981
-				DBG("DEBUG: %s onbreak handler called\n", mod->exports->name);
979
+			if ((mod->mod_interface_ver==0) && mod->exports && 
980
+					mod->exports->v0.onbreak_f) {
981
+				mod->exports->v0.onbreak_f( msg );
982
+				DBG("DEBUG: %s onbreak handler called\n",
983
+						mod->exports->c.name);
982 984
 			}
983 985
 	return ret;
984 986
 
... ...
@@ -174,6 +174,7 @@ extern int yylex();
174 174
 static void yyerror(char* s);
175 175
 static char* tmp;
176 176
 static int i_tmp;
177
+static unsigned u_tmp;
177 178
 static struct socket_id* lst_tmp;
178 179
 static struct name_lst*  nl_tmp;
179 180
 static int rt;  /* Type of route block for find_export */
... ...
@@ -2359,9 +2360,12 @@ cmd:
2359 2359
 	}
2360 2360
 	| FORCE_SEND_SOCKET error {$$=0; yyerror("missing '(' or ')' ?"); }
2361 2361
 	| ID {mod_func_action = mk_action(MODULE_T, 2, MODEXP_ST, NULL, NUMBER_ST, 0); } LPAREN func_params RPAREN	{
2362
-		mod_func_action->val[0].u.data = find_export_record($1, mod_func_action->val[1].u.number, rt);
2362
+		mod_func_action->val[0].u.data = 
2363
+			find_export_record($1, mod_func_action->val[1].u.number, rt,
2364
+								&u_tmp);
2363 2365
 		if (mod_func_action->val[0].u.data == 0) {
2364
-			if (find_export_record($1, mod_func_action->val[1].u.number, 0) ) {
2366
+			if (find_export_record($1, mod_func_action->val[1].u.number, 0,
2367
+									&u_tmp) ) {
2365 2368
 					yyerror("Command cannot be used in the block\n");
2366 2369
 			} else {
2367 2370
 				yyerror("unknown command, missing loadmodule?\n");
... ...
@@ -198,7 +198,8 @@ static void system_listMethods(rpc_t* rpc, void* c)
198 198
 	}
199 199
 
200 200
 	for(t = modules; t; t = t->next) {
201
-		for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
201
+		if (t->mod_interface_ver!=0) continue;
202
+		for(ptr = t->exports->v0.rpc_methods; ptr && ptr->name; ptr++) {
202 203
 			if (rpc->add(c, "s", ptr->name) < 0) return;
203 204
 		}
204 205
 	}
... ...
@@ -232,7 +233,8 @@ static void system_methodHelp(rpc_t* rpc, void* c)
232 232
 	}
233 233
 
234 234
 	for(t = modules; t; t = t->next) {
235
-		for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
235
+		if (t->mod_interface_ver!=0) continue;
236
+		for(ptr = t->exports->v0.rpc_methods; ptr && ptr->name; ptr++) {
236 237
 			if (strcmp(name, ptr->name) == 0) {
237 238
 				if (ptr->doc_str && ptr->doc_str[0]) {
238 239
 					rpc->add(c, "s", ptr->doc_str[0]);
... ...
@@ -84,8 +84,9 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
84 84
 
85 85
 	mod_found = 0;
86 86
 	for(t = modules; t; t = t->next) {
87
-		if (regexec(&preg, t->exports->name, 0, 0, 0) == 0) {
88
-			DBG("set_mod_param_regex: '%s' matches module '%s'\n", regex, t->exports->name);
87
+		if (regexec(&preg, t->exports->c.name, 0, 0, 0) == 0) {
88
+			DBG("set_mod_param_regex: '%s' matches module '%s'\n",
89
+					regex, t->exports->c.name);
89 90
 			mod_found = 1;
90 91
 			/* PARAM_STR (PARAM_STRING) may be assigned also to PARAM_STRING(PARAM_STR) so let get both module param */
91 92
 			ptr = find_param_export(t, name, type | ((type & (PARAM_STR|PARAM_STRING))?PARAM_STR|PARAM_STRING:0), &param_type);
... ...
@@ -100,7 +101,8 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
100 100
 				} else {
101 101
 					val2 = val;
102 102
 				}
103
-				DBG("set_mod_param_regex: found <%s> in module %s [%s]\n", name, t->exports->name, t->path);
103
+				DBG("set_mod_param_regex: found <%s> in module %s [%s]\n",
104
+						name, t->exports->c.name, t->path);
104 105
 				if (param_type & PARAM_USE_FUNC) {
105 106
 					if ( ((param_func_t)(ptr))(param_type, val2) < 0) {
106 107
 						regfree(&preg);
... ...
@@ -137,8 +139,8 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
137 137
 				}
138 138
 			}
139 139
 			else {
140
-				LOG(L_ERR, "set_mod_param_regex: parameter <%s> not found in module <%s>\n",
141
-				    name, t->exports->name);
140
+				LOG(L_ERR, "set_mod_param_regex: parameter <%s> not found in"
141
+							" module <%s>\n", name, t->exports->c.name);
142 142
 				regfree(&preg);
143 143
 				pkg_free(reg);
144 144
 				return -3;
... ...
@@ -386,7 +386,7 @@ static int fix_actions(struct action* a)
386 386
 	struct proxy_l* p;
387 387
 	char *tmp;
388 388
 	int ret;
389
-	cmd_export_t* cmd;
389
+	union cmd_export_u* cmd;
390 390
 	str s;
391 391
 	struct hostent* he;
392 392
 	struct ip_addr ip;
... ...
@@ -504,9 +504,9 @@ static int fix_actions(struct action* a)
504 504
 
505 505
 			case MODULE_T:
506 506
 				cmd = t->val[0].u.data;
507
-				if (cmd && cmd->fixup) {
507
+				if (cmd && cmd->c.fixup) {
508 508
 					int i;
509
-					DBG("fixing %s()\n", cmd->name);
509
+					DBG("fixing %s()\n", cmd->c.name);
510 510
 					/* type cast NUMBER to STRING, old modules may expect
511 511
 					 * all STRING params during fixup */
512 512
 					for (i=0; i<t->val[1].u.number; i++) {
... ...
@@ -527,7 +527,7 @@ static int fix_actions(struct action* a)
527 527
 					for (i=0; i<t->val[1].u.number; i++) {
528 528
 						void *p;
529 529
 						p = t->val[i+2].u.data;
530
-						ret = cmd->fixup(&t->val[i+2].u.data, i+1);
530
+						ret = cmd->c.fixup(&t->val[i+2].u.data, i+1);
531 531
 						if (t->val[i+2].u.data != p)
532 532
 							t->val[i+2].type = MODFIXUP_ST;
533 533
 						if (ret < 0)
... ...
@@ -37,6 +37,7 @@
37 37
  *               find_export_record
38 38
  *  2006-02-07  added fix_flag (andrei)
39 39
  *  2008-02-29  store all the reponse callbacks in their own array (andrei)
40
+ *  2008-11-17  support dual module interface: ser & kamailio (andrei)
40 41
  */
41 42
 
42 43
 
... ...
@@ -63,30 +64,30 @@
63 63
 struct sr_module* modules=0;
64 64
 
65 65
 #ifdef STATIC_EXEC
66
-	extern struct module_exports* exec_exports();
66
+	extern struct module_exports exec_exports;
67 67
 #endif
68 68
 #ifdef STATIC_TM
69
-	extern struct module_exports* tm_exports();
69
+	extern struct module_exports tm_exports;
70 70
 #endif
71 71
 
72 72
 #ifdef STATIC_MAXFWD
73
-	extern struct module_exports* maxfwd_exports();
73
+	extern struct module_exports maxfwd_exports;
74 74
 #endif
75 75
 
76 76
 #ifdef STATIC_AUTH
77
-	extern struct module_exports* auth_exports();
77
+	extern struct module_exports auth_exports;
78 78
 #endif
79 79
 
80 80
 #ifdef STATIC_RR
81
-	extern struct module_exports* rr_exports();
81
+	extern struct module_exports rr_exports;
82 82
 #endif
83 83
 
84 84
 #ifdef STATIC_USRLOC
85
-	extern struct module_exports* usrloc_exports();
85
+	extern struct module_exports usrloc_exports;
86 86
 #endif
87 87
 
88 88
 #ifdef STATIC_SL
89
-	extern struct module_exports* sl_exports();
89
+	extern struct module_exports sl_exports;
90 90
 #endif
91 91
 
92 92
 
... ...
@@ -101,37 +102,37 @@ int register_builtin_modules()
101 101
 
102 102
 	ret=0;
103 103
 #ifdef STATIC_TM
104
-	ret=register_module(tm_exports,"built-in", 0);
104
+	ret=register_module(MODULE_INTERFACE_VER, &tm_exports,"built-in", 0);
105 105
 	if (ret<0) return ret;
106 106
 #endif
107 107
 
108 108
 #ifdef STATIC_EXEC
109
-	ret=register_module(exec_exports,"built-in", 0);
109
+	ret=register_module(MODULE_INTERFACE_VER, &exec_exports,"built-in", 0);
110 110
 	if (ret<0) return ret;
111 111
 #endif
112 112
 
113 113
 #ifdef STATIC_MAXFWD
114
-	ret=register_module(maxfwd_exports, "built-in", 0);
114
+	ret=register_module(MODULE_INTERFACE_VER, &maxfwd_exports, "built-in", 0);
115 115
 	if (ret<0) return ret;
116 116
 #endif
117 117
 
118 118
 #ifdef STATIC_AUTH
119
-	ret=register_module(auth_exports, "built-in", 0);
119
+	ret=register_module(MODULE_INTERFACE_VER, &auth_exports, "built-in", 0);
120 120
 	if (ret<0) return ret;
121 121
 #endif
122 122
 
123 123
 #ifdef STATIC_RR
124
-	ret=register_module(rr_exports, "built-in", 0);
124
+	ret=register_module(MODULE_INTERFACE_VER, &rr_exports, "built-in", 0);
125 125
 	if (ret<0) return ret;
126 126
 #endif
127 127
 
128 128
 #ifdef STATIC_USRLOC
129
-	ret=register_module(usrloc_exports, "built-in", 0);
129
+	ret=register_module(MODULE_INTERFACE_VER, &usrloc_exports, "built-in", 0);
130 130
 	if (ret<0) return ret;
131 131
 #endif
132 132
 
133 133
 #ifdef STATIC_SL
134
-	ret=register_module(sl_exports, "built-in", 0);
134
+	ret=register_module(MODULE_INTERFACE_VER, &sl_exports, "built-in", 0);
135 135
 	if (ret<0) return ret;
136 136
 #endif
137 137
 
... ...
@@ -142,7 +143,8 @@ int register_builtin_modules()
142 142
 
143 143
 /* registers a module,  register_f= module register  functions
144 144
  * returns <0 on error, 0 on success */
145
-int register_module(struct module_exports* e, char* path, void* handle)
145
+static int register_module(unsigned ver, union module_exports_u* e,
146
+					char* path, void* handle)
146 147
 {
147 148
 	int ret;
148 149
 	struct sr_module* mod;
... ...
@@ -158,6 +160,7 @@ int register_module(struct module_exports* e, char* path, void* handle)
158 158
 	memset(mod,0, sizeof(struct sr_module));
159 159
 	mod->path=path;
160 160
 	mod->handle=handle;
161
+	mod->mod_interface_ver=ver;
161 162
 	mod->exports=e;
162 163
 	mod->next=modules;
163 164
 	modules=mod;
... ...
@@ -218,7 +221,8 @@ int load_module(char* path)
218 218
 {
219 219
 	void* handle;
220 220
 	char* error;
221
-	struct module_exports* exp;
221
+	union module_exports_u* exp;
222
+	unsigned* mod_if_ver;
222 223
 	struct sr_module* t;
223 224
 	struct stat stat_buf;
224 225
 	char* modname;
... ...
@@ -302,13 +306,20 @@ int load_module(char* path)
302 302
 	if (!version_control(handle, path)) {
303 303
 		exit(0);
304 304
 	}
305
+	mod_if_ver = (unsigned *)dlsym(handle,
306
+									DLSYM_PREFIX "module_interface_ver");
307
+	if ( (error =(char*)dlerror())!=0 ){
308
+		LOG(L_ERR, "ERROR: no module interface version in module <%s>\n",
309
+					path );
310
+		goto error1;
311
+	}
305 312
 	/* launch register */
306
-	exp = (struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");
313
+	exp = (union module_exports_u*)dlsym(handle, DLSYM_PREFIX "exports");
307 314
 	if ( (error =(char*)dlerror())!=0 ){
308 315
 		LOG(L_ERR, "ERROR: load_module: %s\n", error);
309 316
 		goto error1;
310 317
 	}
311
-	if (register_module(exp, path, handle)<0) goto error1;
318
+	if (register_module(*mod_if_ver, exp, path, handle)<0) goto error1;
312 319
 	return 0;
313 320
 
314 321
 error1:
... ...
@@ -321,25 +332,51 @@ skip:
321 321
 
322 322
 
323 323
 
324
-/* searches the module list and returns pointer to the "name" function record or
325
- * 0 if not found
324
+/* searches the module list for function name in module mod and returns 
325
+ *  a pointer to the "name" function record union or 0 if not found
326
+ * sets also *mod_if_ver to the module interface version (needed to know
327
+ * which member of the union should be accessed v0 or v1)
328
+ * mod==0 is a wildcard matching all modules
326 329
  * flags parameter is OR value of all flags that must match
327 330
  */
328
-cmd_export_t* find_export_record(char* name, int param_no, int flags)
331
+union cmd_export_u* find_mod_export_record(char* mod, char* name,
332
+											int param_no, int flags,
333
+											unsigned* mod_if_ver)
329 334
 {
330 335
 	struct sr_module* t;
331
-	cmd_export_t* cmd;
336
+	union cmd_export_u* cmd;
337
+	int i;
338
+	unsigned mver;
339
+
340
+#define FIND_EXPORT_IN_MOD(VER) \
341
+		if (t->exports->VER.cmds) \
342
+			for(i=0, cmd=(void*)&t->exports->VER.cmds[0]; cmd->VER.name; \
343
+					i++, cmd=(void*)&t->exports->VER.cmds[i]){\
344
+				if((strcmp(name, cmd->VER.name)==0)&& \
345
+					(cmd->VER.param_no==param_no) &&  \
346
+					((cmd->VER.flags & flags) == flags) \
347
+				){ \
348
+					DBG("find_export_record: found <%s> in module %s [%s]\n", \
349
+						name, t->exports->VER.name, t->path); \
350
+					*mod_if_ver=mver; \
351
+					return cmd; \
352
+				} \
353
+			}
332 354
 
333 355
 	for(t=modules;t;t=t->next){
334
-		for(cmd=t->exports->cmds; cmd && cmd->name; cmd++){
335
-			if((strcmp(name, cmd->name)==0)&&
336
-			   (cmd->param_no==param_no) &&
337
-			   ((cmd->flags & flags) == flags)
338
-			  ){
339
-				DBG("find_export_record: found <%s> in module %s [%s]\n",
340
-				    name, t->exports->name, t->path);
341
-				return cmd;
342
-			}
356
+		if (mod!=0 && (strcmp(t->exports->c.name, mod) !=0))
357
+			continue;
358
+		mver=t->mod_interface_ver;
359
+		switch (mver){
360
+			case 0:
361
+				FIND_EXPORT_IN_MOD(v0);
362
+				break;
363
+			case 1:
364
+				FIND_EXPORT_IN_MOD(v1);
365
+				break;
366
+			default:
367
+				BUG("invalid module interface version %d for modules %s\n",
368
+						t->mod_interface_ver, t->path);
343 369
 		}
344 370
 	}
345 371
 	DBG("find_export_record: <%s> not found \n", name);
... ...
@@ -347,11 +384,30 @@ cmd_export_t* find_export_record(char* name, int param_no, int flags)
347 347
 }
348 348
 
349 349
 
350
+
351
+/* searches the module list for function name and returns 
352
+ *  a pointer to the "name" function record union or 0 if not found
353
+ * sets also *mod_if_ver to the module interface version (needed to know
354
+ * which member of the union should be accessed v0 or v1)
355
+ * mod==0 is a wildcard matching all modules
356
+ * flags parameter is OR value of all flags that must match
357
+ */
358
+union cmd_export_u* find_export_record(char* name,
359
+											int param_no, int flags,
360
+											unsigned* mod_if_ver)
361
+{
362
+	return find_mod_export_record(0, name, param_no, flags, mod_if_ver);
363
+}
364
+
365
+
366
+
350 367
 cmd_function find_export(char* name, int param_no, int flags)
351 368
 {
352
-	cmd_export_t* cmd;
353
-	cmd = find_export_record(name, param_no, flags);
354
-	return cmd?cmd->function:0;
369
+	union cmd_export_u* cmd;
370
+	unsigned mver;
371
+	
372
+	cmd = find_export_record(name, param_no, flags, &mver);
373
+	return cmd?cmd->c.function:0;
355 374
 }
356 375
 
357 376
 
... ...
@@ -372,7 +428,8 @@ rpc_export_t* find_rpc_export(char* name, int flags)
372 372
 	}
373 373
 	     /* Continue with modules if not found */
374 374
 	for(t = modules; t; t = t->next) {
375
-		for(rpc = t->exports->rpc_methods; rpc && rpc->name; rpc++) {
375
+		if (t->mod_interface_ver!=0) continue;
376
+		for(rpc = t->exports->v0.rpc_methods; rpc && rpc->name; rpc++) {
376 377
 			if ((strcmp(name, rpc->name) == 0) &&
377 378
 			    ((rpc->flags & flags) == flags)
378 379
 			   ) {
... ...
@@ -385,30 +442,20 @@ rpc_export_t* find_rpc_export(char* name, int flags)
385 385
 
386 386
 
387 387
 /*
388
- * searches the module list and returns pointer to "name" function in module "mod"
388
+ * searches the module list and returns pointer to "name" function in module
389
+ * "mod"
389 390
  * 0 if not found
390 391
  * flags parameter is OR value of all flags that must match
391 392
  */
392 393
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
393 394
 {
394
-	struct sr_module* t;
395
-	cmd_export_t* cmd;
396
-
397
-	for (t = modules; t; t = t->next) {
398
-		if (strcmp(t->exports->name, mod) == 0) {
399
-			for (cmd = t->exports->cmds;  cmd && cmd->name; cmd++) {
400
-				if ((strcmp(name, cmd->name) == 0) &&
401
-				    (cmd->param_no == param_no) &&
402
-				    ((cmd->flags & flags) == flags)
403
-				   ){
404
-					DBG("find_mod_export: found <%s> in module %s [%s]\n",
405
-					    name, t->exports->name, t->path);
406
-					return cmd->function;
407
-				}
408
-			}
409
-		}
410
-	}
395
+	union cmd_export_u* cmd;
396
+	unsigned mver;
411 397
 
398
+	cmd=find_mod_export_record(mod, name, param_no, flags, &mver);
399
+	if (cmd)
400
+		return cmd->c.function;
401
+	
412 402
 	DBG("find_mod_export: <%s> in module <%s> not found\n", name, mod);
413 403
 	return 0;
414 404
 }
... ...
@@ -418,7 +465,7 @@ struct sr_module* find_module_by_name(char* mod) {
418 418
 	struct sr_module* t;
419 419
 
420 420
 	for(t = modules; t; t = t->next) {
421
-		if (strcmp(mod, t->exports->name) == 0) {
421
+		if (strcmp(mod, t->exports->c.name) == 0) {
422 422
 			return t;
423 423
 		}
424 424
 	}
... ...
@@ -427,23 +474,37 @@ struct sr_module* find_module_by_name(char* mod) {
427 427
 }
428 428
 
429 429
 
430
-void* find_param_export(struct sr_module* mod, char* name, modparam_t type_mask, modparam_t *param_type)
430
+void* find_param_export(struct sr_module* mod, char* name,
431
+						modparam_t type_mask, modparam_t *param_type)
431 432
 {
432 433
 	param_export_t* param;
433 434
 
434 435
 	if (!mod)
435 436
 		return 0;
436
-	for(param=mod->exports->params;param && param->name ; param++) {
437
+	param=0;
438
+	switch(mod->mod_interface_ver){
439
+		case 0:
440
+			param=mod->exports->v0.params;
441
+			break;
442
+		case 1:
443
+			param=mod->exports->v1.params;
444
+			break;
445
+		default:
446
+			BUG("bad module interface version %d in module %s [%s]\n",
447
+					mod->mod_interface_ver, mod->exports->c.name, mod->path);
448
+			return 0;
449
+	}
450
+	for(;param && param->name ; param++) {
437 451
 		if ((strcmp(name, param->name) == 0) &&
438 452
 			((param->type & PARAM_TYPE_MASK(type_mask)) != 0)) {
439 453
 			DBG("find_param_export: found <%s> in module %s [%s]\n",
440
-				name, mod->exports->name, mod->path);
454
+				name, mod->exports->c.name, mod->path);
441 455
 			*param_type = param->type;
442 456
 			return param->param_pointer;
443 457
 		}
444 458
 	}
445 459
 	DBG("find_param_export: parameter <%s> not found in module <%s>\n",
446
-			name, mod->exports->name);
460
+			name, mod->exports->c.name);
447 461
 	return 0;
448 462
 }
449 463
 
... ...
@@ -455,7 +516,20 @@ void destroy_modules()
455 455
 	t=modules;
456 456
 	while(t) {
457 457
 		foo=t->next;
458
-		if ((t->exports)&&(t->exports->destroy_f)) t->exports->destroy_f();
458
+		if (t->exports){
459
+			switch(t->mod_interface_ver){
460
+				case 0:
461
+					if ((t->exports->v0.destroy_f)) t->exports->v0.destroy_f();
462
+					break;
463
+				case 1:
464
+					if ((t->exports->v1.destroy_f)) t->exports->v1.destroy_f();
465
+					break;
466
+				default:
467
+					BUG("bad module interface version %d in module %s [%s]\n",
468
+						t->mod_interface_ver, t->exports->c.name,
469
+						t->path);
470
+			}
471
+		}
459 472
 		pkg_free(t);
460 473
 		t=foo;
461 474
 	}
... ...
@@ -477,14 +551,36 @@ int init_modules(void)
477 477
 	struct sr_module* t;
478 478
 
479 479
 	for(t = modules; t; t = t->next) {
480
-		if ((t->exports) && (t->exports->init_f))
481
-			if (t->exports->init_f() != 0) {
482
-				LOG(L_ERR, "init_modules(): Error while initializing"
483
-							" module %s\n", t->exports->name);
484
-				return -1;
480
+		if (t->exports){
481
+			switch(t->mod_interface_ver){
482
+				case 0:
483
+					if (t->exports->v0.init_f)
484
+						if (t->exports->v0.init_f() != 0) {
485
+							LOG(L_ERR, "init_modules(): Error while"
486
+										" initializing module %s\n",
487
+										t->exports->v0.name);
488
+							return -1;
489
+						}
490
+					if (t->exports->v0.response_f)
491
+						mod_response_cbk_no++;
492
+					break;
493
+				case 1:
494
+					if (t->exports->v1.init_f)
495
+						if (t->exports->v1.init_f() != 0) {
496
+							LOG(L_ERR, "init_modules(): Error while"
497
+										" initializing module %s\n",
498
+										t->exports->v1.name);
499
+							return -1;
500
+						}
501
+					if (t->exports->v1.response_f)
502
+						mod_response_cbk_no++;
503
+					break;
504
+				default:
505
+					BUG("bad module interface version %d in module %s [%s]\n",
506
+						t->exports->c.name, t->path);
507
+					return -1;
485 508
 			}
486
-		if ( t->exports && t->exports->response_f)
487
-			mod_response_cbk_no++;
509
+		}
488 510
 	}
489 511
 	mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
490 512
 									sizeof(response_function));
... ...
@@ -494,9 +590,21 @@ int init_modules(void)
494 494
 		return -1;
495 495
 	}
496 496
 	for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
497
-		if (t->exports && t->exports->response_f){
498
-			mod_response_cbks[i]=t->exports->response_f;
499
-			i++;
497
+		if (t->exports){
498
+			switch(t->mod_interface_ver){
499
+				case 0:
500
+					if (t->exports->v0.response_f){
501
+						mod_response_cbks[i]=t->exports->v0.response_f;
502
+						i++;
503
+					}
504
+					break;
505
+				case 1:
506
+					if (t->exports->v1.response_f){
507
+						mod_response_cbks[i]=t->exports->v1.response_f;
508
+						i++;
509
+					}
510
+					break;
511
+			}
500 512
 		}
501 513
 	}
502 514
 	return 0;
... ...
@@ -521,12 +629,30 @@ int init_child(int rank)
521 521
 
522 522
 
523 523
 	for(t = modules; t; t = t->next) {
524
-		if (t->exports->init_child_f) {
525
-			if ((t->exports->init_child_f(rank)) < 0) {
526
-				LOG(L_ERR, "init_child(): Initialization of child %d failed\n",
527
-						rank);
524
+		switch(t->mod_interface_ver){
525
+			case 0:
526
+				if (t->exports->v0.init_child_f) {
527
+					if ((t->exports->v0.init_child_f(rank)) < 0) {
528
+						LOG(L_ERR, "init_child(): Initialization of child"
529
+									" %d failed\n", rank);
530
+						return -1;
531
+					}
532
+				}
533
+				break;
534
+			case 1:
535
+				if (t->exports->v1.init_child_f) {
536
+					if ((t->exports->v1.init_child_f(rank)) < 0) {
537
+						LOG(L_ERR, "init_child(): Initialization of child"
538
+									" %d failed\n", rank);
539
+						return -1;
540
+					}
541
+				}
542
+				break;
543
+			default:
544
+				BUG("bad module interface version %d in module %s [%s]\n",
545
+						t->mod_interface_ver, t->exports->c.name,
546
+						t->path);
528 547
 				return -1;
529
-			}
530 548
 		}
531 549
 	}
532 550
 	return 0;
... ...
@@ -547,19 +673,43 @@ static int init_mod_child( struct sr_module* m, int rank )
547 547
 		   propagate it up the stack
548 548
 		 */
549 549
 		if (init_mod_child(m->next, rank)!=0) return -1;
550
-		if (m->exports && m->exports->init_child_f) {
551
-			DBG("DEBUG: init_mod_child (%d): %s\n",
552
-					rank, m->exports->name);
553
-			if (m->exports->init_child_f(rank)<0) {
554
-				LOG(L_ERR, "init_mod_child(): Error while initializing"
555
-							" module %s\n", m->exports->name);
556
-				return -1;
557
-			} else {
558
-				/* module correctly initialized */
559
-				return 0;
550
+		if (m->exports){
551
+			switch(m->mod_interface_ver){
552
+				case 0:
553
+					if (m->exports->v0.init_child_f) {
554
+						DBG("DEBUG: init_mod_child (%d): %s\n",
555
+								rank, m->exports->v0.name);
556
+						if (m->exports->v0.init_child_f(rank)<0) {
557
+							LOG(L_ERR, "init_mod_child(): Error while"
558
+										" initializing module %s\n",
559
+										m->exports->v0.name);
560
+							return -1;
561
+						} else {
562
+							/* module correctly initialized */
563
+							return 0;
564
+						}
565
+					}
566
+					/* no init function -- proceed with success */
567
+					return 0;
568
+				case 1:
569
+					if (m->exports->v1.init_child_f) {
570
+						DBG("DEBUG: init_mod_child (%d): %s\n",
571
+								rank, m->exports->v1.name);
572
+						if (m->exports->v1.init_child_f(rank)<0) {
573
+							LOG(L_ERR, "init_mod_child(): Error while"
574
+										" initializing module %s\n",
575
+										m->exports->v1.name);
576
+							return -1;
577
+						} else {
578
+							/* module correctly initialized */
579
+							return 0;
580
+						}
581
+					}
582
+					/* no init function -- proceed with success */
583
+					return 0;
560 584
 			}
561 585
 		}
562
-		/* no init function -- proceed with success */
586
+		/* no exports -- proceed with success */
563 587
 		return 0;
564 588
 	} else {
565 589
 		/* end of list */
... ...
@@ -590,18 +740,39 @@ static int init_mod( struct sr_module* m )
590 590
 		   propagate it up the stack
591 591
 		 */
592 592
 		if (init_mod(m->next)!=0) return -1;
593
-		if (m->exports && m->exports->init_f) {
594
-			DBG("DEBUG: init_mod: %s\n", m->exports->name);
595
-			if (m->exports->init_f()!=0) {
596
-				LOG(L_ERR, "init_mod(): Error while initializing"
597
-							" module %s\n", m->exports->name);
598
-				return -1;
599
-			} else {
600
-				/* module correctly initialized */
601
-				return 0;
593
+		if (m->exports){
594
+			switch(m->mod_interface_ver){
595
+				case 0:
596
+					if ( m->exports->v0.init_f) {
597
+						DBG("DEBUG: init_mod: %s\n", m->exports->v0.name);
598
+						if (m->exports->v0.init_f()!=0) {
599
+							LOG(L_ERR, "init_mod(): Error while initializing"
600
+										" module %s\n", m->exports->v0.name);
601
+							return -1;
602
+						} else {
603
+							/* module correctly initialized */
604
+							return 0;
605
+						}
606
+					}
607
+					/* no init function -- proceed with success */
608
+					return 0;
609
+				case 1:
610
+					if ( m->exports->v1.init_f) {
611
+						DBG("DEBUG: init_mod: %s\n", m->exports->v1.name);
612
+						if (m->exports->v1.init_f()!=0) {
613
+							LOG(L_ERR, "init_mod(): Error while initializing"
614
+										" module %s\n", m->exports->v1.name);
615
+							return -1;
616
+						} else {
617
+							/* module correctly initialized */
618
+							return 0;
619
+						}
620
+					}
621
+					/* no init function -- proceed with success */
622
+					return 0;
602 623
 			}
603 624
 		}
604
-		/* no init function -- proceed with success */
625
+		/* no exports -- proceed with success */
605 626
 		return 0;
606 627
 	} else {
607 628
 		/* end of list */
... ...
@@ -619,8 +790,18 @@ int init_modules(void)
619 619
 	int i;
620 620
 	
621 621
 	for(t = modules; t; t = t->next)
622
-		if ( t->exports && t->exports->response_f)
623
-			mod_response_cbk_no++;
622
+		if (t->exports){
623
+			switch(t->mod_interface_ver){
624
+				case 0:
625
+					if (t->exports->v0.response_f)
626
+						mod_response_cbk_no++;
627
+					break;
628
+				case 1:
629
+					if (t->exports->v1.response_f)
630
+						mod_response_cbk_no++;
631
+					break;
632
+			}
633
+		}
624 634
 	mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
625 635
 									sizeof(response_function));
626 636
 	if (mod_response_cbks==0){
... ...
@@ -629,9 +810,21 @@ int init_modules(void)
629 629
 		return -1;
630 630
 	}
631 631
 	for (t=modules, i=0; t && (i<mod_response_cbk_no); t=t->next){
632
-		if (t->exports && t->exports->response_f){
633
-			mod_response_cbks[i]=t->exports->response_f;
634
-			i++;
632
+		if (t->exports){
633
+			switch(t->mod_interface_ver){
634
+				case 0:
635
+					if (t->exports->v0.response_f){
636
+						mod_response_cbks[i]=t->exports->v0.response_f;
637
+						i++;
638
+					}
639
+					break;
640
+				case 1:
641
+					if (t->exports->v1.response_f){
642
+						mod_response_cbks[i]=t->exports->v1.response_f;
643
+						i++;
644
+					}
645
+					break;
646
+			}
635 647
 		}
636 648
 	}
637 649
 	
... ...
@@ -43,6 +43,7 @@
43 43
  *               any other process is forked (andrei)
44 44
  *  2008-11-17  sip-router version: includes some of the openser/kamailio
45 45
  *               changes: f(void) instead of f(), free_fixup_function()
46
+ *              dual module interface support: ser & kamailio (andrei)
46 47
  */
47 48
 
48 49
 /*!
... ...
@@ -60,6 +61,32 @@
60 60
 #include "route_struct.h"
61 61
 #include "str.h"
62 62
 
63
+/* kamailio compat */
64
+#include "statistics.h"
65
+#include "mi/mi.h"
66
+#include "pvar.h"
67
+
68
+
69
+
70
+#if defined KAMAILIO_MOD_INTERFACE || defined OPENSER_MOD_INTERFACE || \
71
+	defined MOD_INTERFACE_V1
72
+
73
+#define MODULE_INTERFACE_VER 1
74
+#define cmd_export_t kam_cmd_export_t
75
+#define module_exports kam_module_exports
76
+
77
+#elif defined SER_MOD_INTERFACE || defined MOD_INTERFACE_V0
78
+
79
+#define MODULE_INTERFACE_VER 0
80
+#define cmd_export_t ser_cmd_export_t
81
+#define module_exports ser_module_exports
82
+
83
+#else
84
+
85
+/* do nothing for core */
86
+
87
+#endif
88
+
63 89
 typedef  struct module_exports* (*module_register)(void);
64 90
 typedef  int (*cmd_function)(struct sip_msg*, char*, char*);
65 91
 typedef  int (*fixup_function)(void** param, int param_no);
... ...
@@ -91,7 +118,8 @@ typedef int (*param_func_t)( modparam_t type, void* val);
91 91
 #define FAILURE_ROUTE 2  /* Function can be used in reply route blocks */
92 92
 #define ONREPLY_ROUTE 4  /* Function can be used in on_reply */
93 93
 #define BRANCH_ROUTE  8  /* Function can be used in branch_route blocks */
94
-#define ONSEND_ROUTE   16  /* Function can be used in onsend_route blocks */
94
+#define ONSEND_ROUTE 16  /* Function can be used in onsend_route blocks */
95
+#define ERROR_ROUTE  32  /* Function can be used in an error route */ 
95 96
 
96 97
 /* Macros - used as rank in child_init function */
97 98
 #define PROC_MAIN      0  /* Main ser process */
... ...
@@ -116,11 +144,24 @@ typedef int (*param_func_t)( modparam_t type, void* val);
116 116
 
117 117
 #define PROC_MIN PROC_NOCHLDINIT /* Minimum process rank */
118 118
 
119
+
120
+#define DEFAULT_DLFLAGS	0 /* value that signals to module loader to
121
+							use default dlopen flags in Kamailio */
122
+#ifndef RTLD_NOW
123
+/* for openbsd */
124
+#define RTLD_NOW DL_LAZY
125
+#endif
126
+
127
+#define KAMAILIO_DLFLAGS	RTLD_NOW
128
+
129
+
119 130
 #define MODULE_VERSION \
120 131
 	char *module_version=SER_FULL_VERSION; \
121
-	char *module_flags=SER_COMPILE_FLAGS;
132
+	char *module_flags=SER_COMPILE_FLAGS; \
133
+	unsigned int module_interface_ver=MODULE_INTERFACE_VER; 
122 134
 
123
-struct cmd_export_ {
135
+/* ser version */
136
+struct ser_cmd_export_ {
124 137
 	char* name;             /* null terminated command name */
125 138
 	cmd_function function;  /* pointer to the corresponding function */
126 139
 	int param_no;           /* number of parameters used by the function */
... ...
@@ -130,6 +171,29 @@ struct cmd_export_ {
130 130
 };
131 131
 
132 132
 
133
+/* kamailo/openser version */
134
+struct kam_cmd_export_ {
135
+	char* name;             /* null terminated command name */
136
+	cmd_function function;  /* pointer to the corresponding function */
137
+	int param_no;           /* number of parameters used by the function */
138
+	fixup_function fixup;   /* pointer to the function called to "fix" the
139
+							   parameters */
140
+	free_fixup_function free_fixup; /* function called to free the "fixed"
141
+									   parameters */
142
+	int flags;              /* Function flags */
143
+};
144
+
145
+
146
+/* members situated at the same place in memory in both ser & kamailio
147
+   cmd_export */
148
+struct cmd_export_common_ {
149
+	char* name;
150
+	cmd_function function; 
151
+	int param_no;
152
+	fixup_function fixup;
153
+};
154
+
155
+
133 156
 struct param_export_ {
134 157
 	char* name;             /* null terminated param. name */
135 158
 	modparam_t type;        /* param. type */
... ...
@@ -166,18 +230,26 @@ typedef struct fparam {
166 166
 } fparam_t;
167 167
 
168 168
 
169
-typedef struct cmd_export_ cmd_export_t;
170
-typedef struct param_export_ param_export_t;
169
+typedef struct param_export_ param_export_t;  
170
+typedef struct ser_cmd_export_ ser_cmd_export_t;
171
+typedef struct kam_cmd_export_ kam_cmd_export_t;
172
+typedef struct cmd_export_common_ cmd_export_common_t;
173
+
174
+union cmd_export_u{
175
+	cmd_export_common_t c; /* common members for everybody */
176
+	ser_cmd_export_t v0;
177
+	kam_cmd_export_t v1;
178
+};
171 179
 
172
-struct module_exports {
173
-	char* name;                     /* null terminated module name */
174 180
 
175
-	cmd_export_t* cmds;             /* null terminated array of the exported
181
+/* ser module exports version */
182
+struct ser_module_exports {
183
+	char* name;                     /* null terminated module name */
184
+	ser_cmd_export_t* cmds;         /* null terminated array of the exported
176 185
 									   commands */
177 186
 	rpc_export_t* rpc_methods;      /* null terminated array of exported rpc methods */
178 187
 	param_export_t* params;         /* null terminated array of the exported
179 188
 									   module parameters */
180
-
181 189
 	init_function init_f;           /* Initialization function */
182 190
 	response_function response_f;   /* function used for responses,
183 191
 									   returns yes or no; can be null */
... ...
@@ -190,10 +262,69 @@ struct module_exports {
190 190
 };
191 191
 
192 192
 
193
+/* kamailio/openser proc_export (missing from ser) */
194
+typedef void (*mod_proc)(int no);
195
+
196
+typedef int (*mod_proc_wrapper)(void);
197
+
198
+struct proc_export_ {
199
+	char *name;
200
+	mod_proc_wrapper pre_fork_function;
201
+	mod_proc_wrapper post_fork_function;
202
+	mod_proc function;
203
+	unsigned int no;
204
+};
205
+
206
+typedef struct proc_export_ proc_export_t;
207
+
208
+
209
+/* kamailio/openser module exports version */
210
+struct kam_module_exports {
211
+	char* name;                     /* null terminated module name */
212
+	unsigned int dlflags;			/*!< flags for dlopen  */
213
+	kam_cmd_export_t* cmds;			/* null terminated array of the exported
214
+									   commands */
215
+	param_export_t* params;			/* null terminated array of the exported
216
+									   module parameters */
217
+	stat_export_t* stats;			/*!< null terminated array of the exported
218
+									  module statistics */
219
+	mi_export_t* mi_cmds;			/*!< null terminated array of the exported
220
+									  MI functions */
221
+	pv_export_t* items;				/*!< null terminated array of the exported
222
+									   module items (pseudo-variables) */
223
+	proc_export_t* procs;			/*!< null terminated array of the
224
+									  additional processes required by the
225
+									  module */
226
+	init_function init_f;           /* Initialization function */
227
+	response_function response_f;   /* function used for responses,
228
+									   returns yes or no; can be null */
229
+	destroy_function destroy_f;     /* function called when the module should
230
+									   be "destroyed", e.g: on ser exit;
231
+									   can be null */
232
+	child_init_function init_child_f;  /* function called by all processes
233
+										  after the fork */
234
+};
235
+
236
+
237
+
238
+/* module exports in the same place in memory in both ser & kamailio */
239
+struct module_exports_common{
240
+	char* name;
241
+};
242
+
243
+
244
+union module_exports_u {
245
+		struct module_exports_common c; /*common members for all the versions*/
246
+		struct ser_module_exports v0;
247
+		struct kam_module_exports v1;
248
+};
249
+
250
+
193 251
 struct sr_module{
194 252
 	char* path;
195 253
 	void* handle;
196
-	struct module_exports* exports;
254
+	unsigned int mod_interface_ver;
255
+	union module_exports_u* exports;
197 256
 	struct sr_module* next;
198 257
 };
199 258
 
... ...
@@ -203,9 +334,10 @@ extern response_function* mod_response_cbks;/* response callback array */
203 203
 extern int mod_response_cbk_no;    /* size of reponse callbacks array */
204 204
 
205 205
 int register_builtin_modules(void);
206
-int register_module(struct module_exports*, char*,  void*);
206
+/*int register_module(unsigned , struct module_exports*, char*,  void*);*/
207 207
 int load_module(char* path);
208
-cmd_export_t* find_export_record(char* name, int param_no, int flags);
208
+union cmd_export_u* find_export_record(char* name, int param_no, int flags,
209
+										unsigned *ver);
209 210
 cmd_function find_export(char* name, int param_no, int flags);
210 211
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags);
211 212
 rpc_export_t* find_rpc_export(char* name, int flags);
... ...
@@ -338,4 +470,20 @@ int get_int_fparam(int* dst, struct sip_msg* msg, fparam_t* param);
338 338
  * @return: 0 for success, negative on error.
339 339
  */
340 340
 int get_regex_fparam(regex_t *dst, struct sip_msg* msg, fparam_t* param);
341
+
342
+
343
+/* functions needed for kamailio/openser compatibility */
344
+
345
+/*! \brief Check if module is loaded
346
+ * \return Returns 1 if the module with name 'name' is loaded, and zero otherwise. */
347
+int module_loaded(char *name);
348
+
349
+/*! \brief Counts the additional the number of processes
350
+ requested by modules */
351
+int count_module_procs(void);
352
+
353
+
354
+/*! \brief Forks and starts the additional processes required by modules */
355
+int start_module_procs(void);
356
+
341 357
 #endif /* sr_module_h */