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 977
 	/* process module onbreak handlers if present */
977 978
 	if (h->rec_lev==0 && ret==0)
978 979
 		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);
980
+			if ((mod->mod_interface_ver==0) && mod->exports && 
981
+					mod->exports->v0.onbreak_f) {
982
+				mod->exports->v0.onbreak_f( msg );
983
+				DBG("DEBUG: %s onbreak handler called\n",
984
+						mod->exports->c.name);
982 985
 			}
983 986
 	return ret;
984 987
 
... ...
@@ -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 2360
 	}
2360 2361
 	| FORCE_SEND_SOCKET error {$$=0; yyerror("missing '(' or ')' ?"); }
2361 2362
 	| 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);
2363
+		mod_func_action->val[0].u.data = 
2364
+			find_export_record($1, mod_func_action->val[1].u.number, rt,
2365
+								&u_tmp);
2363 2366
 		if (mod_func_action->val[0].u.data == 0) {
2364
-			if (find_export_record($1, mod_func_action->val[1].u.number, 0) ) {
2367
+			if (find_export_record($1, mod_func_action->val[1].u.number, 0,
2368
+									&u_tmp) ) {
2365 2369
 					yyerror("Command cannot be used in the block\n");
2366 2370
 			} else {
2367 2371
 				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 233
 	}
233 234
 
234 235
 	for(t = modules; t; t = t->next) {
235
-		for(ptr = t->exports->rpc_methods; ptr && ptr->name; ptr++) {
236
+		if (t->mod_interface_ver!=0) continue;
237
+		for(ptr = t->exports->v0.rpc_methods; ptr && ptr->name; ptr++) {
236 238
 			if (strcmp(name, ptr->name) == 0) {
237 239
 				if (ptr->doc_str && ptr->doc_str[0]) {
238 240
 					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 101
 				} else {
101 102
 					val2 = val;
102 103
 				}
103
-				DBG("set_mod_param_regex: found <%s> in module %s [%s]\n", name, t->exports->name, t->path);
104
+				DBG("set_mod_param_regex: found <%s> in module %s [%s]\n",
105
+						name, t->exports->c.name, t->path);
104 106
 				if (param_type & PARAM_USE_FUNC) {
105 107
 					if ( ((param_func_t)(ptr))(param_type, val2) < 0) {
106 108
 						regfree(&preg);
... ...
@@ -137,8 +139,8 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
137 139
 				}
138 140
 			}
139 141
 			else {
140
-				LOG(L_ERR, "set_mod_param_regex: parameter <%s> not found in module <%s>\n",
141
-				    name, t->exports->name);
142
+				LOG(L_ERR, "set_mod_param_regex: parameter <%s> not found in"
143
+							" module <%s>\n", name, t->exports->c.name);
142 144
 				regfree(&preg);
143 145
 				pkg_free(reg);
144 146
 				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 64
 struct sr_module* modules=0;
64 65
 
65 66
 #ifdef STATIC_EXEC
66
-	extern struct module_exports* exec_exports();
67
+	extern struct module_exports exec_exports;
67 68
 #endif
68 69
 #ifdef STATIC_TM
69
-	extern struct module_exports* tm_exports();
70
+	extern struct module_exports tm_exports;
70 71
 #endif
71 72
 
72 73
 #ifdef STATIC_MAXFWD
73
-	extern struct module_exports* maxfwd_exports();
74
+	extern struct module_exports maxfwd_exports;
74 75
 #endif
75 76
 
76 77
 #ifdef STATIC_AUTH
77
-	extern struct module_exports* auth_exports();
78
+	extern struct module_exports auth_exports;
78 79
 #endif
79 80
 
80 81
 #ifdef STATIC_RR
81
-	extern struct module_exports* rr_exports();
82
+	extern struct module_exports rr_exports;
82 83
 #endif
83 84
 
84 85
 #ifdef STATIC_USRLOC
85
-	extern struct module_exports* usrloc_exports();
86
+	extern struct module_exports usrloc_exports;
86 87
 #endif
87 88
 
88 89
 #ifdef STATIC_SL
89
-	extern struct module_exports* sl_exports();
90
+	extern struct module_exports sl_exports;
90 91
 #endif
91 92
 
92 93
 
... ...
@@ -101,37 +102,37 @@ int register_builtin_modules()
101 102
 
102 103
 	ret=0;
103 104
 #ifdef STATIC_TM
104
-	ret=register_module(tm_exports,"built-in", 0);
105
+	ret=register_module(MODULE_INTERFACE_VER, &tm_exports,"built-in", 0);
105 106
 	if (ret<0) return ret;
106 107
 #endif
107 108
 
108 109
 #ifdef STATIC_EXEC
109
-	ret=register_module(exec_exports,"built-in", 0);
110
+	ret=register_module(MODULE_INTERFACE_VER, &exec_exports,"built-in", 0);
110 111
 	if (ret<0) return ret;
111 112
 #endif
112 113
 
113 114
 #ifdef STATIC_MAXFWD
114
-	ret=register_module(maxfwd_exports, "built-in", 0);
115
+	ret=register_module(MODULE_INTERFACE_VER, &maxfwd_exports, "built-in", 0);
115 116
 	if (ret<0) return ret;
116 117
 #endif
117 118
 
118 119
 #ifdef STATIC_AUTH
119
-	ret=register_module(auth_exports, "built-in", 0);
120
+	ret=register_module(MODULE_INTERFACE_VER, &auth_exports, "built-in", 0);
120 121
 	if (ret<0) return ret;
121 122
 #endif
122 123
 
123 124
 #ifdef STATIC_RR
124
-	ret=register_module(rr_exports, "built-in", 0);
125
+	ret=register_module(MODULE_INTERFACE_VER, &rr_exports, "built-in", 0);
125 126
 	if (ret<0) return ret;
126 127
 #endif
127 128
 
128 129
 #ifdef STATIC_USRLOC
129
-	ret=register_module(usrloc_exports, "built-in", 0);
130
+	ret=register_module(MODULE_INTERFACE_VER, &usrloc_exports, "built-in", 0);
130 131
 	if (ret<0) return ret;
131 132
 #endif
132 133
 
133 134
 #ifdef STATIC_SL
134
-	ret=register_module(sl_exports, "built-in", 0);
135
+	ret=register_module(MODULE_INTERFACE_VER, &sl_exports, "built-in", 0);
135 136
 	if (ret<0) return ret;
136 137
 #endif
137 138
 
... ...
@@ -142,7 +143,8 @@ int register_builtin_modules()
142 143
 
143 144
 /* registers a module,  register_f= module register  functions
144 145
  * returns <0 on error, 0 on success */
145
-int register_module(struct module_exports* e, char* path, void* handle)
146
+static int register_module(unsigned ver, union module_exports_u* e,
147
+					char* path, void* handle)
146 148
 {
147 149
 	int ret;
148 150
 	struct sr_module* mod;
... ...
@@ -158,6 +160,7 @@ int register_module(struct module_exports* e, char* path, void* handle)
158 160
 	memset(mod,0, sizeof(struct sr_module));
159 161
 	mod->path=path;
160 162
 	mod->handle=handle;
163
+	mod->mod_interface_ver=ver;
161 164
 	mod->exports=e;
162 165
 	mod->next=modules;
163 166
 	modules=mod;
... ...
@@ -218,7 +221,8 @@ int load_module(char* path)
218 221
 {
219 222
 	void* handle;
220 223
 	char* error;
221
-	struct module_exports* exp;
224
+	union module_exports_u* exp;
225
+	unsigned* mod_if_ver;
222 226
 	struct sr_module* t;
223 227
 	struct stat stat_buf;
224 228
 	char* modname;
... ...
@@ -302,13 +306,20 @@ int load_module(char* path)
302 306
 	if (!version_control(handle, path)) {
303 307
 		exit(0);
304 308
 	}
309
+	mod_if_ver = (unsigned *)dlsym(handle,
310
+									DLSYM_PREFIX "module_interface_ver");
311
+	if ( (error =(char*)dlerror())!=0 ){
312
+		LOG(L_ERR, "ERROR: no module interface version in module <%s>\n",
313
+					path );
314
+		goto error1;
315
+	}
305 316
 	/* launch register */
306
-	exp = (struct module_exports*)dlsym(handle, DLSYM_PREFIX "exports");
317
+	exp = (union module_exports_u*)dlsym(handle, DLSYM_PREFIX "exports");
307 318
 	if ( (error =(char*)dlerror())!=0 ){
308 319
 		LOG(L_ERR, "ERROR: load_module: %s\n", error);
309 320
 		goto error1;
310 321
 	}
311
-	if (register_module(exp, path, handle)<0) goto error1;
322
+	if (register_module(*mod_if_ver, exp, path, handle)<0) goto error1;
312 323
 	return 0;
313 324
 
314 325
 error1:
... ...
@@ -321,25 +332,51 @@ skip:
321 332
 
322 333
 
323 334
 
324
-/* searches the module list and returns pointer to the "name" function record or
325
- * 0 if not found
335
+/* searches the module list for function name in module mod and returns 
336
+ *  a pointer to the "name" function record union or 0 if not found
337
+ * sets also *mod_if_ver to the module interface version (needed to know
338
+ * which member of the union should be accessed v0 or v1)
339
+ * mod==0 is a wildcard matching all modules
326 340
  * flags parameter is OR value of all flags that must match
327 341
  */
328
-cmd_export_t* find_export_record(char* name, int param_no, int flags)
342
+union cmd_export_u* find_mod_export_record(char* mod, char* name,
343
+											int param_no, int flags,
344
+											unsigned* mod_if_ver)
329 345
 {
330 346
 	struct sr_module* t;
331
-	cmd_export_t* cmd;
347
+	union cmd_export_u* cmd;
348
+	int i;
349
+	unsigned mver;
350
+
351
+#define FIND_EXPORT_IN_MOD(VER) \
352
+		if (t->exports->VER.cmds) \
353
+			for(i=0, cmd=(void*)&t->exports->VER.cmds[0]; cmd->VER.name; \
354
+					i++, cmd=(void*)&t->exports->VER.cmds[i]){\
355
+				if((strcmp(name, cmd->VER.name)==0)&& \
356
+					(cmd->VER.param_no==param_no) &&  \
357
+					((cmd->VER.flags & flags) == flags) \
358
+				){ \
359
+					DBG("find_export_record: found <%s> in module %s [%s]\n", \
360
+						name, t->exports->VER.name, t->path); \
361
+					*mod_if_ver=mver; \
362
+					return cmd; \
363
+				} \
364
+			}
332 365
 
333 366
 	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
-			}
367
+		if (mod!=0 && (strcmp(t->exports->c.name, mod) !=0))
368
+			continue;
369
+		mver=t->mod_interface_ver;
370
+		switch (mver){
371
+			case 0:
372
+				FIND_EXPORT_IN_MOD(v0);
373
+				break;
374
+			case 1:
375
+				FIND_EXPORT_IN_MOD(v1);
376
+				break;
377
+			default:
378
+				BUG("invalid module interface version %d for modules %s\n",
379
+						t->mod_interface_ver, t->path);
343 380
 		}
344 381
 	}
345 382
 	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 384
 }
348 385
 
349 386
 
387
+
388
+/* searches the module list for function name and returns 
389
+ *  a pointer to the "name" function record union or 0 if not found
390
+ * sets also *mod_if_ver to the module interface version (needed to know
391
+ * which member of the union should be accessed v0 or v1)
392
+ * mod==0 is a wildcard matching all modules
393
+ * flags parameter is OR value of all flags that must match
394
+ */
395
+union cmd_export_u* find_export_record(char* name,
396
+											int param_no, int flags,
397
+											unsigned* mod_if_ver)
398
+{
399
+	return find_mod_export_record(0, name, param_no, flags, mod_if_ver);
400
+}
401
+
402
+
403
+
350 404
 cmd_function find_export(char* name, int param_no, int flags)
351 405
 {
352
-	cmd_export_t* cmd;
353
-	cmd = find_export_record(name, param_no, flags);
354
-	return cmd?cmd->function:0;
406
+	union cmd_export_u* cmd;
407
+	unsigned mver;
408
+	
409
+	cmd = find_export_record(name, param_no, flags, &mver);
410
+	return cmd?cmd->c.function:0;
355 411
 }
356 412
 
357 413
 
... ...
@@ -372,7 +428,8 @@ rpc_export_t* find_rpc_export(char* name, int flags)
372 428
 	}
373 429
 	     /* Continue with modules if not found */
374 430
 	for(t = modules; t; t = t->next) {
375
-		for(rpc = t->exports->rpc_methods; rpc && rpc->name; rpc++) {
431
+		if (t->mod_interface_ver!=0) continue;
432
+		for(rpc = t->exports->v0.rpc_methods; rpc && rpc->name; rpc++) {
376 433
 			if ((strcmp(name, rpc->name) == 0) &&
377 434
 			    ((rpc->flags & flags) == flags)
378 435
 			   ) {
... ...
@@ -385,30 +442,20 @@ rpc_export_t* find_rpc_export(char* name, int flags)
385 442
 
386 443
 
387 444
 /*
388
- * searches the module list and returns pointer to "name" function in module "mod"
445
+ * searches the module list and returns pointer to "name" function in module
446
+ * "mod"
389 447
  * 0 if not found
390 448
  * flags parameter is OR value of all flags that must match
391 449
  */
392 450
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags)
393 451
 {
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
-	}
452
+	union cmd_export_u* cmd;
453
+	unsigned mver;
411 454
 
455
+	cmd=find_mod_export_record(mod, name, param_no, flags, &mver);
456
+	if (cmd)
457
+		return cmd->c.function;
458
+	
412 459
 	DBG("find_mod_export: <%s> in module <%s> not found\n", name, mod);
413 460
 	return 0;
414 461
 }
... ...
@@ -418,7 +465,7 @@ struct sr_module* find_module_by_name(char* mod) {
418 465
 	struct sr_module* t;
419 466
 
420 467
 	for(t = modules; t; t = t->next) {
421
-		if (strcmp(mod, t->exports->name) == 0) {
468
+		if (strcmp(mod, t->exports->c.name) == 0) {
422 469
 			return t;
423 470
 		}
424 471
 	}
... ...
@@ -427,23 +474,37 @@ struct sr_module* find_module_by_name(char* mod) {
427 474
 }
428 475
 
429 476
 
430
-void* find_param_export(struct sr_module* mod, char* name, modparam_t type_mask, modparam_t *param_type)
477
+void* find_param_export(struct sr_module* mod, char* name,
478
+						modparam_t type_mask, modparam_t *param_type)
431 479
 {
432 480
 	param_export_t* param;
433 481
 
434 482
 	if (!mod)
435 483
 		return 0;
436
-	for(param=mod->exports->params;param && param->name ; param++) {
484
+	param=0;
485
+	switch(mod->mod_interface_ver){
486
+		case 0:
487
+			param=mod->exports->v0.params;
488
+			break;
489
+		case 1:
490
+			param=mod->exports->v1.params;
491
+			break;
492
+		default:
493
+			BUG("bad module interface version %d in module %s [%s]\n",
494
+					mod->mod_interface_ver, mod->exports->c.name, mod->path);
495
+			return 0;
496
+	}
497
+	for(;param && param->name ; param++) {
437 498
 		if ((strcmp(name, param->name) == 0) &&
438 499
 			((param->type & PARAM_TYPE_MASK(type_mask)) != 0)) {
439 500
 			DBG("find_param_export: found <%s> in module %s [%s]\n",
440
-				name, mod->exports->name, mod->path);
501
+				name, mod->exports->c.name, mod->path);
441 502
 			*param_type = param->type;
442 503
 			return param->param_pointer;
443 504
 		}
444 505
 	}
445 506
 	DBG("find_param_export: parameter <%s> not found in module <%s>\n",
446
-			name, mod->exports->name);
507
+			name, mod->exports->c.name);
447 508
 	return 0;
448 509
 }
449 510
 
... ...
@@ -455,7 +516,20 @@ void destroy_modules()
455 516
 	t=modules;
456 517
 	while(t) {
457 518
 		foo=t->next;
458
-		if ((t->exports)&&(t->exports->destroy_f)) t->exports->destroy_f();
519
+		if (t->exports){
520
+			switch(t->mod_interface_ver){
521
+				case 0:
522
+					if ((t->exports->v0.destroy_f)) t->exports->v0.destroy_f();
523
+					break;
524
+				case 1:
525
+					if ((t->exports->v1.destroy_f)) t->exports->v1.destroy_f();
526
+					break;
527
+				default:
528
+					BUG("bad module interface version %d in module %s [%s]\n",
529
+						t->mod_interface_ver, t->exports->c.name,
530
+						t->path);
531
+			}
532
+		}
459 533
 		pkg_free(t);
460 534
 		t=foo;
461 535
 	}
... ...
@@ -477,14 +551,36 @@ int init_modules(void)
477 551
 	struct sr_module* t;
478 552
 
479 553
 	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;
554
+		if (t->exports){
555
+			switch(t->mod_interface_ver){
556
+				case 0:
557
+					if (t->exports->v0.init_f)
558
+						if (t->exports->v0.init_f() != 0) {
559
+							LOG(L_ERR, "init_modules(): Error while"
560
+										" initializing module %s\n",
561
+										t->exports->v0.name);
562
+							return -1;
563
+						}
564
+					if (t->exports->v0.response_f)
565
+						mod_response_cbk_no++;
566
+					break;
567
+				case 1:
568
+					if (t->exports->v1.init_f)
569
+						if (t->exports->v1.init_f() != 0) {
570
+							LOG(L_ERR, "init_modules(): Error while"
571
+										" initializing module %s\n",
572
+										t->exports->v1.name);
573
+							return -1;
574
+						}
575
+					if (t->exports->v1.response_f)
576
+						mod_response_cbk_no++;
577
+					break;
578
+				default:
579
+					BUG("bad module interface version %d in module %s [%s]\n",
580
+						t->exports->c.name, t->path);
581
+					return -1;
485 582
 			}
486
-		if ( t->exports && t->exports->response_f)
487
-			mod_response_cbk_no++;
583
+		}
488 584
 	}
489 585
 	mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
490 586
 									sizeof(response_function));
... ...
@@ -494,9 +590,21 @@ int init_modules(void)
494 590
 		return -1;
495 591
 	}
496 592
 	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++;
593
+		if (t->exports){
594
+			switch(t->mod_interface_ver){
595
+				case 0:
596
+					if (t->exports->v0.response_f){
597
+						mod_response_cbks[i]=t->exports->v0.response_f;
598
+						i++;
599
+					}
600
+					break;
601
+				case 1:
602
+					if (t->exports->v1.response_f){
603
+						mod_response_cbks[i]=t->exports->v1.response_f;
604
+						i++;
605
+					}
606
+					break;
607
+			}
500 608
 		}
501 609
 	}
502 610
 	return 0;
... ...
@@ -521,12 +629,30 @@ int init_child(int rank)
521 629
 
522 630
 
523 631
 	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);
632
+		switch(t->mod_interface_ver){
633
+			case 0:
634
+				if (t->exports->v0.init_child_f) {
635
+					if ((t->exports->v0.init_child_f(rank)) < 0) {
636
+						LOG(L_ERR, "init_child(): Initialization of child"
637
+									" %d failed\n", rank);
638
+						return -1;
639
+					}
640
+				}
641
+				break;
642
+			case 1:
643
+				if (t->exports->v1.init_child_f) {
644
+					if ((t->exports->v1.init_child_f(rank)) < 0) {
645
+						LOG(L_ERR, "init_child(): Initialization of child"
646
+									" %d failed\n", rank);
647
+						return -1;
648
+					}
649
+				}
650
+				break;
651
+			default:
652
+				BUG("bad module interface version %d in module %s [%s]\n",
653
+						t->mod_interface_ver, t->exports->c.name,
654
+						t->path);
528 655
 				return -1;
529
-			}
530 656
 		}
531 657
 	}
532 658
 	return 0;
... ...
@@ -547,19 +673,43 @@ static int init_mod_child( struct sr_module* m, int rank )
547 673
 		   propagate it up the stack
548 674
 		 */
549 675
 		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;
676
+		if (m->exports){
677
+			switch(m->mod_interface_ver){
678
+				case 0:
679
+					if (m->exports->v0.init_child_f) {
680
+						DBG("DEBUG: init_mod_child (%d): %s\n",
681
+								rank, m->exports->v0.name);
682
+						if (m->exports->v0.init_child_f(rank)<0) {
683
+							LOG(L_ERR, "init_mod_child(): Error while"
684
+										" initializing module %s\n",
685
+										m->exports->v0.name);
686
+							return -1;
687
+						} else {
688
+							/* module correctly initialized */
689
+							return 0;
690
+						}
691
+					}
692
+					/* no init function -- proceed with success */
693
+					return 0;
694
+				case 1:
695
+					if (m->exports->v1.init_child_f) {
696
+						DBG("DEBUG: init_mod_child (%d): %s\n",
697
+								rank, m->exports->v1.name);
698
+						if (m->exports->v1.init_child_f(rank)<0) {
699
+							LOG(L_ERR, "init_mod_child(): Error while"
700
+										" initializing module %s\n",
701
+										m->exports->v1.name);
702
+							return -1;
703
+						} else {
704
+							/* module correctly initialized */
705
+							return 0;
706
+						}
707
+					}
708
+					/* no init function -- proceed with success */
709
+					return 0;
560 710
 			}
561 711
 		}
562
-		/* no init function -- proceed with success */
712
+		/* no exports -- proceed with success */
563 713
 		return 0;
564 714
 	} else {
565 715
 		/* end of list */
... ...
@@ -590,18 +740,39 @@ static int init_mod( struct sr_module* m )
590 740
 		   propagate it up the stack
591 741
 		 */
592 742
 		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;
743
+		if (m->exports){
744
+			switch(m->mod_interface_ver){
745
+				case 0:
746
+					if ( m->exports->v0.init_f) {
747
+						DBG("DEBUG: init_mod: %s\n", m->exports->v0.name);
748
+						if (m->exports->v0.init_f()!=0) {
749
+							LOG(L_ERR, "init_mod(): Error while initializing"
750
+										" module %s\n", m->exports->v0.name);
751
+							return -1;
752
+						} else {
753
+							/* module correctly initialized */
754
+							return 0;
755
+						}
756
+					}
757
+					/* no init function -- proceed with success */
758
+					return 0;
759
+				case 1:
760
+					if ( m->exports->v1.init_f) {
761
+						DBG("DEBUG: init_mod: %s\n", m->exports->v1.name);
762
+						if (m->exports->v1.init_f()!=0) {
763
+							LOG(L_ERR, "init_mod(): Error while initializing"
764
+										" module %s\n", m->exports->v1.name);
765
+							return -1;
766
+						} else {
767
+							/* module correctly initialized */
768
+							return 0;
769
+						}
770
+					}
771
+					/* no init function -- proceed with success */
772
+					return 0;
602 773
 			}
603 774
 		}
604
-		/* no init function -- proceed with success */
775
+		/* no exports -- proceed with success */
605 776
 		return 0;
606 777
 	} else {
607 778
 		/* end of list */
... ...
@@ -619,8 +790,18 @@ int init_modules(void)
619 790
 	int i;
620 791
 	
621 792
 	for(t = modules; t; t = t->next)
622
-		if ( t->exports && t->exports->response_f)
623
-			mod_response_cbk_no++;
793
+		if (t->exports){
794
+			switch(t->mod_interface_ver){
795
+				case 0:
796
+					if (t->exports->v0.response_f)
797
+						mod_response_cbk_no++;
798
+					break;
799
+				case 1:
800
+					if (t->exports->v1.response_f)
801
+						mod_response_cbk_no++;
802
+					break;
803
+			}
804
+		}
624 805
 	mod_response_cbks=pkg_malloc(mod_response_cbk_no * 
625 806
 									sizeof(response_function));
626 807
 	if (mod_response_cbks==0){
... ...
@@ -629,9 +810,21 @@ int init_modules(void)
629 810
 		return -1;
630 811
 	}
631 812
 	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++;
813
+		if (t->exports){
814
+			switch(t->mod_interface_ver){
815
+				case 0:
816
+					if (t->exports->v0.response_f){
817
+						mod_response_cbks[i]=t->exports->v0.response_f;
818
+						i++;
819
+					}
820
+					break;
821
+				case 1:
822
+					if (t->exports->v1.response_f){
823
+						mod_response_cbks[i]=t->exports->v1.response_f;
824
+						i++;
825
+					}
826
+					break;
827
+			}
635 828
 		}
636 829
 	}
637 830
 	
... ...
@@ -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 61
 #include "route_struct.h"
61 62
 #include "str.h"
62 63
 
64
+/* kamailio compat */
65
+#include "statistics.h"
66
+#include "mi/mi.h"
67
+#include "pvar.h"
68
+
69
+
70
+
71
+#if defined KAMAILIO_MOD_INTERFACE || defined OPENSER_MOD_INTERFACE || \
72
+	defined MOD_INTERFACE_V1
73
+
74
+#define MODULE_INTERFACE_VER 1
75
+#define cmd_export_t kam_cmd_export_t
76
+#define module_exports kam_module_exports
77
+
78
+#elif defined SER_MOD_INTERFACE || defined MOD_INTERFACE_V0
79
+
80
+#define MODULE_INTERFACE_VER 0
81
+#define cmd_export_t ser_cmd_export_t
82
+#define module_exports ser_module_exports
83
+
84
+#else
85
+
86
+/* do nothing for core */
87
+
88
+#endif
89
+
63 90
 typedef  struct module_exports* (*module_register)(void);
64 91
 typedef  int (*cmd_function)(struct sip_msg*, char*, char*);
65 92
 typedef  int (*fixup_function)(void** param, int param_no);
... ...
@@ -91,7 +118,8 @@ typedef int (*param_func_t)( modparam_t type, void* val);
91 118
 #define FAILURE_ROUTE 2  /* Function can be used in reply route blocks */
92 119
 #define ONREPLY_ROUTE 4  /* Function can be used in on_reply */
93 120
 #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 */
121
+#define ONSEND_ROUTE 16  /* Function can be used in onsend_route blocks */
122
+#define ERROR_ROUTE  32  /* Function can be used in an error route */ 
95 123
 
96 124
 /* Macros - used as rank in child_init function */
97 125
 #define PROC_MAIN      0  /* Main ser process */
... ...
@@ -116,11 +144,24 @@ typedef int (*param_func_t)( modparam_t type, void* val);
116 144
 
117 145
 #define PROC_MIN PROC_NOCHLDINIT /* Minimum process rank */
118 146
 
147
+
148
+#define DEFAULT_DLFLAGS	0 /* value that signals to module loader to
149
+							use default dlopen flags in Kamailio */
150
+#ifndef RTLD_NOW
151
+/* for openbsd */
152
+#define RTLD_NOW DL_LAZY
153
+#endif
154
+
155
+#define KAMAILIO_DLFLAGS	RTLD_NOW
156
+
157
+
119 158
 #define MODULE_VERSION \
120 159
 	char *module_version=SER_FULL_VERSION; \
121
-	char *module_flags=SER_COMPILE_FLAGS;
160
+	char *module_flags=SER_COMPILE_FLAGS; \
161
+	unsigned int module_interface_ver=MODULE_INTERFACE_VER; 
122 162
 
123
-struct cmd_export_ {
163
+/* ser version */
164
+struct ser_cmd_export_ {
124 165
 	char* name;             /* null terminated command name */
125 166
 	cmd_function function;  /* pointer to the corresponding function */
126 167
 	int param_no;           /* number of parameters used by the function */
... ...
@@ -130,6 +171,29 @@ struct cmd_export_ {
130 171
 };
131 172
 
132 173
 
174
+/* kamailo/openser version */
175
+struct kam_cmd_export_ {
176
+	char* name;             /* null terminated command name */
177
+	cmd_function function;  /* pointer to the corresponding function */
178
+	int param_no;           /* number of parameters used by the function */
179
+	fixup_function fixup;   /* pointer to the function called to "fix" the
180
+							   parameters */
181
+	free_fixup_function free_fixup; /* function called to free the "fixed"
182
+									   parameters */
183
+	int flags;              /* Function flags */
184
+};
185
+
186
+
187
+/* members situated at the same place in memory in both ser & kamailio
188
+   cmd_export */
189
+struct cmd_export_common_ {
190
+	char* name;
191
+	cmd_function function; 
192
+	int param_no;
193
+	fixup_function fixup;
194
+};
195
+
196
+
133 197
 struct param_export_ {
134 198
 	char* name;             /* null terminated param. name */
135 199
 	modparam_t type;        /* param. type */
... ...
@@ -166,18 +230,26 @@ typedef struct fparam {
166 230
 } fparam_t;
167 231
 
168 232
 
169
-typedef struct cmd_export_ cmd_export_t;
170
-typedef struct param_export_ param_export_t;
233
+typedef struct param_export_ param_export_t;  
234
+typedef struct ser_cmd_export_ ser_cmd_export_t;
235
+typedef struct kam_cmd_export_ kam_cmd_export_t;
236
+typedef struct cmd_export_common_ cmd_export_common_t;
237
+
238
+union cmd_export_u{
239
+	cmd_export_common_t c; /* common members for everybody */
240
+	ser_cmd_export_t v0;
241
+	kam_cmd_export_t v1;
242
+};
171 243
 
172
-struct module_exports {
173
-	char* name;                     /* null terminated module name */
174 244
 
175
-	cmd_export_t* cmds;             /* null terminated array of the exported
245
+/* ser module exports version */
246
+struct ser_module_exports {
247
+	char* name;                     /* null terminated module name */
248
+	ser_cmd_export_t* cmds;         /* null terminated array of the exported
176 249
 									   commands */
177 250
 	rpc_export_t* rpc_methods;      /* null terminated array of exported rpc methods */
178 251
 	param_export_t* params;         /* null terminated array of the exported
179 252
 									   module parameters */
180
-
181 253
 	init_function init_f;           /* Initialization function */
182 254
 	response_function response_f;   /* function used for responses,
183 255
 									   returns yes or no; can be null */
... ...
@@ -190,10 +262,69 @@ struct module_exports {
190 262
 };
191 263
 
192 264
 
265
+/* kamailio/openser proc_export (missing from ser) */
266
+typedef void (*mod_proc)(int no);
267
+
268
+typedef int (*mod_proc_wrapper)(void);
269
+
270
+struct proc_export_ {
271
+	char *name;
272
+	mod_proc_wrapper pre_fork_function;
273
+	mod_proc_wrapper post_fork_function;
274
+	mod_proc function;
275
+	unsigned int no;
276
+};
277
+
278
+typedef struct proc_export_ proc_export_t;
279
+
280
+
281
+/* kamailio/openser module exports version */
282
+struct kam_module_exports {
283
+	char* name;                     /* null terminated module name */
284
+	unsigned int dlflags;			/*!< flags for dlopen  */
285
+	kam_cmd_export_t* cmds;			/* null terminated array of the exported
286
+									   commands */
287
+	param_export_t* params;			/* null terminated array of the exported
288
+									   module parameters */
289
+	stat_export_t* stats;			/*!< null terminated array of the exported
290
+									  module statistics */
291
+	mi_export_t* mi_cmds;			/*!< null terminated array of the exported
292
+									  MI functions */
293
+	pv_export_t* items;				/*!< null terminated array of the exported
294
+									   module items (pseudo-variables) */
295
+	proc_export_t* procs;			/*!< null terminated array of the
296
+									  additional processes required by the
297
+									  module */
298
+	init_function init_f;           /* Initialization function */
299
+	response_function response_f;   /* function used for responses,
300
+									   returns yes or no; can be null */
301
+	destroy_function destroy_f;     /* function called when the module should
302
+									   be "destroyed", e.g: on ser exit;
303
+									   can be null */
304
+	child_init_function init_child_f;  /* function called by all processes
305
+										  after the fork */
306
+};
307
+
308
+
309
+
310
+/* module exports in the same place in memory in both ser & kamailio */
311
+struct module_exports_common{
312
+	char* name;
313
+};
314
+
315
+
316
+union module_exports_u {
317
+		struct module_exports_common c; /*common members for all the versions*/
318
+		struct ser_module_exports v0;
319
+		struct kam_module_exports v1;
320
+};
321
+
322
+
193 323
 struct sr_module{
194 324
 	char* path;
195 325
 	void* handle;
196
-	struct module_exports* exports;
326
+	unsigned int mod_interface_ver;
327
+	union module_exports_u* exports;
197 328
 	struct sr_module* next;
198 329
 };
199 330
 
... ...
@@ -203,9 +334,10 @@ extern response_function* mod_response_cbks;/* response callback array */
203 334
 extern int mod_response_cbk_no;    /* size of reponse callbacks array */
204 335
 
205 336
 int register_builtin_modules(void);
206
-int register_module(struct module_exports*, char*,  void*);
337
+/*int register_module(unsigned , struct module_exports*, char*,  void*);*/
207 338
 int load_module(char* path);
208
-cmd_export_t* find_export_record(char* name, int param_no, int flags);
339
+union cmd_export_u* find_export_record(char* name, int param_no, int flags,
340
+										unsigned *ver);
209 341
 cmd_function find_export(char* name, int param_no, int flags);
210 342
 cmd_function find_mod_export(char* mod, char* name, int param_no, int flags);
211 343
 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 470
  * @return: 0 for success, negative on error.
339 471
  */
340 472
 int get_regex_fparam(regex_t *dst, struct sip_msg* msg, fparam_t* param);
473
+
474
+
475
+/* functions needed for kamailio/openser compatibility */
476
+
477
+/*! \brief Check if module is loaded
478
+ * \return Returns 1 if the module with name 'name' is loaded, and zero otherwise. */
479
+int module_loaded(char *name);
480
+
481
+/*! \brief Counts the additional the number of processes
482
+ requested by modules */
483
+int count_module_procs(void);
484
+
485
+
486
+/*! \brief Forks and starts the additional processes required by modules */
487
+int start_module_procs(void);
488
+
341 489
 #endif /* sr_module_h */