sr_module.c
3bf76e49
 /* $Id$
7dd0b342
  *
  * Copyright (C) 2001-2003 Fhg Fokus
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
3bf76e49
  */
 
7dd0b342
 
3bf76e49
 #include "sr_module.h"
 #include "dprint.h"
404073d3
 #include "error.h"
3bf76e49
 
 #include <dlfcn.h>
 #include <strings.h>
 #include <stdlib.h>
e22bbdb8
 #include <string.h>
3bf76e49
 
 
031e278e
 struct sr_module* modules=0;
3bf76e49
 
30449150
 #ifdef STATIC_EXEC
 	extern struct module_exports* exec_exports();
 #endif
404073d3
 #ifdef STATIC_TM
57c9e572
 	extern struct module_exports* tm_exports();
404073d3
 #endif
57c9e572
 
6eb22d94
 #ifdef STATIC_MAXFWD
57c9e572
 	extern struct module_exports* maxfwd_exports();
6eb22d94
 #endif
57c9e572
 
192ac55b
 #ifdef STATIC_AUTH
57c9e572
         extern struct module_exports* auth_exports();
192ac55b
 #endif
57c9e572
 
192ac55b
 #ifdef STATIC_RR
57c9e572
         extern struct module_exports* rr_exports();
192ac55b
 #endif
57c9e572
 
192ac55b
 #ifdef STATIC_USRLOC
57c9e572
         extern struct module_exports* usrloc_exports();
192ac55b
 #endif
404073d3
 
a50f3f89
 #ifdef STATIC_SL
         extern struct module_exports* sl_exports();
 #endif
 
404073d3
 
 /* initializes statically built (compiled in) modules*/
31309a3a
 int register_builtin_modules()
404073d3
 {
e22bbdb8
 	int ret;
 
 	ret=0;
57c9e572
 #ifdef STATIC_TM
 	ret=register_module(tm_exports,"built-in", 0); 
 	if (ret<0) return ret;
 #endif
192ac55b
 
30449150
 #ifdef EXEC_TM
 	ret=register_module(exec_exports,"built-in", 0); 
 	if (ret<0) return ret;
 #endif
 
57c9e572
 #ifdef STATIC_MAXFWD
 	ret=register_module(maxfwd_exports, "built-in", 0);
 	if (ret<0) return ret;
192ac55b
 #endif
 
57c9e572
 #ifdef STATIC_AUTH
 	ret=register_module(auth_exports, "built-in", 0); 
 	if (ret<0) return ret;
 #endif
 	
192ac55b
 #ifdef STATIC_RR
57c9e572
 	ret=register_module(rr_exports, "built-in", 0);
 	if (ret<0) return ret;
192ac55b
 #endif
57c9e572
 	
192ac55b
 #ifdef STATIC_USRLOC
57c9e572
 	ret=register_module(usrloc_exports, "built-in", 0);
 	if (ret<0) return ret;
192ac55b
 #endif
a50f3f89
 
 #ifdef STATIC_SL
 	ret=register_module(sl_exports, "built-in", 0);
 	if (ret<0) return ret;
 #endif
e22bbdb8
 	
 	return ret;
404073d3
 }
 
 
 
 /* registers a module,  register_f= module register  functions
  * returns <0 on error, 0 on success */
31309a3a
 int register_module(struct module_exports* e, char* path, void* handle)
404073d3
 {
 	int ret;
e22bbdb8
 	struct sr_module* mod;
404073d3
 	
 	ret=-1;
31309a3a
 
404073d3
 	/* add module to the list */
 	if ((mod=malloc(sizeof(struct sr_module)))==0){
 		LOG(L_ERR, "load_module: memory allocation failure\n");
 		ret=E_OUT_OF_MEM;
 		goto error;
 	}
 	memset(mod,0, sizeof(struct sr_module));
 	mod->path=path;
 	mod->handle=handle;
 	mod->exports=e;
 	mod->next=modules;
 	modules=mod;
 	return 0;
 error:
 	return ret;
 }
 
192ac55b
 /*
  * per-child initialization
  */
 int init_child(int rank)
 {
 	struct sr_module* t;
 
 	for(t = modules; t; t = t->next) {
 		if (t->exports->init_child_f) {
 			if ((t->exports->init_child_f(rank)) < 0) {
e22bbdb8
 				LOG(L_ERR, "init_child(): Initialization of child %d failed\n",
 						rank);
192ac55b
 				return -1;
 			}
 		}
 	}
 	return 0;
 }
 
3bf76e49
 
 
 /* returns 0 on success , <0 on error */
 int load_module(char* path)
 {
 	void* handle;
 	char* error;
31309a3a
 	struct module_exports* exp;
404073d3
 	struct sr_module* t;
3bf76e49
 	
9148ad98
 	handle=dlopen(path, RTLD_NOW); /* resolve all symbols now */
3bf76e49
 	if (handle==0){
 		LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n",
 					path, dlerror() );
 		goto error;
 	}
 	
 	for(t=modules;t; t=t->next){
 		if (t->handle==handle){
 			LOG(L_WARN, "WARNING: load_module: attempting to load the same"
 						" module twice (%s)\n", path);
 			goto skip;
 		}
 	}
 	/* launch register */
31309a3a
 	exp = (struct module_exports*)dlsym(handle, "exports");
381659ac
 	if ( (error =(char*)dlerror())!=0 ){
3bf76e49
 		LOG(L_ERR, "ERROR: load_module: %s\n", error);
 		goto error1;
 	}
31309a3a
 	if (register_module(exp, path, handle)<0) goto error1;
3bf76e49
 	return 0;
 
 error1:
 	dlclose(handle);
 error:
 skip:
 	return -1;
 }
 
 
 
 /* searches the module list and returns a pointer to the "name" function or
  * 0 if not found */
34fd2612
 cmd_function find_export(char* name, int param_no)
3bf76e49
 {
 	struct sr_module* t;
 	int r;
 
 	for(t=modules;t;t=t->next){
 		for(r=0;r<t->exports->cmd_no;r++){
34fd2612
 			if((strcmp(name, t->exports->cmd_names[r])==0)&&
 				(t->exports->param_no[r]==param_no) ){
3bf76e49
 				DBG("find_export: found <%s> in module %s [%s]\n",
 						name, t->exports->name, t->path);
 				return t->exports->cmd_pointers[r];
 			}
 		}
 	}
 	DBG("find_export: <%s> not found \n", name);
 	return 0;
 }
 
34fd2612
 
31309a3a
 void* find_param_export(char* mod, char* name, modparam_t type)
 {
 	struct sr_module* t;
 	int r;
 
 	for(t = modules; t; t = t->next) {
 		if (strcmp(mod, t->exports->name) == 0) {
 			for(r = 0; r < t->exports->par_no; r++) {
 				if ((strcmp(name, t->exports->param_names[r]) == 0) &&
 				    (t->exports->param_types[r] == type)) {
 					DBG("find_param_export: found <%s> in module %s [%s]\n",
 					    name, t->exports->name, t->path);
 					return t->exports->param_pointers[r];
 				}
 			}
 		}
 	}
e3fc93f4
 	DBG("find_param_export: parameter <%s> or module <%s> not found\n",
 			name, mod);
31309a3a
 	return 0;
 }
 
 
34fd2612
 
 /* finds a module, given a pointer to a module function *
  * returns pointer to module, & if i i!=0, *i=the function index */
 struct sr_module* find_module(void* f, int *i)
 {
 	struct sr_module* t;
 	int r;
 	for (t=modules;t;t=t->next){
 		for(r=0;r<t->exports->cmd_no;r++) 
51eadd0c
 			if (f==(void*)t->exports->cmd_pointers[r]) {
34fd2612
 				if (i) *i=r;
 				return t;
 			}
 	}
 	return 0;
 }
bf08223a
 
 
 
 void destroy_modules()
 {
 	struct sr_module* t;
 
 	for(t=modules;t;t=t->next)
 		if  ((t->exports)&&(t->exports->destroy_f)) t->exports->destroy_f();
 }
31309a3a
 
 
 /*
  * Initialize all loaded modules, the initialization
  * is done *AFTER* the configuration file is parsed
  */
 int init_modules(void)
 {
 	struct sr_module* t;
 	
 	for(t = modules; t; t = t->next) {
 		if ((t->exports) && (t->exports->init_f))
 			if (t->exports->init_f() != 0) {
e3fc93f4
 				LOG(L_ERR, "init_modules(): Error while initializing"
 							" module %s\n", t->exports->name);
31309a3a
 				return -1;
 			}
 	}
 	return 0;
 }