view waaad/extensions.c @ 405:c7ea4e86870a

Allow subextensions symbols lookup
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 10 Jun 2009 15:33:06 +0900
parents d40bbfcd07ef
children
line wrap: on
line source

/*********************************************************************************************************
* Software License Agreement (BSD License)                                                               *
* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
*													 *
* Copyright (c) 2008, WIDE Project and NICT								 *
* All rights reserved.											 *
* 													 *
* Redistribution and use of this software in source and binary forms, with or without modification, are  *
* permitted provided that the following conditions are met:						 *
* 													 *
* * Redistributions of source code must retain the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer.										 *
*    													 *
* * Redistributions in binary form must reproduce the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer in the documentation and/or other						 *
*   materials provided with the distribution.								 *
* 													 *
* * Neither the name of the WIDE Project or NICT nor the 						 *
*   names of its contributors may be used to endorse or 						 *
*   promote products derived from this software without 						 *
*   specific prior written permission of WIDE Project and 						 *
*   NICT.												 *
* 													 *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
*********************************************************************************************************/

/* Dynamic extensions loading.
 *
 * See extensions.h for more information.
 *
 * Note : This module is NOT thread-safe. All processing must be done from one thread only.
 */
#include "waaad-internal.h"
#include <waaad/waaad.h>

#include <dlfcn.h>	/* We may use libtool's <ltdl.h> later for better portability.... */

/* Structure to store the list of extensions from the configuration file */
typedef struct _ext_t {
	uti_list_t 	chain;
	char 		*filename;
	char 		*conffile;
	void 		*handler;
	void		(*waaad_ext_fini)(void);
} ext_t;

/* Variables to manage the list of extensions */
static uti_list_t	ext_list;

/* The API structure that is passed to all extensions */
static waaad_api_t exported_api;

/* Simple security to not forgot this part */
#define MY_WAAAD_API_VER 1
#if MY_WAAAD_API_VER != WAAAD_API_VER
# error "You must update the API init here"
#endif
/* Initialize the API that is passed to extensions */
static void api_init(void)
{
	TRACE_ENTRY("");
	exported_api.version = WAAAD_API_VER;
	API_INIT_LOG        ( exported_api.log        );
	API_INIT_DICTIONARY ( exported_api.dictionary );
	API_INIT_CONF       ( exported_api.conf       );
	API_INIT_PEER       ( exported_api.peer       );
	API_INIT_MSG        ( exported_api.msg        );
	API_INIT_RT         ( exported_api.rt         );
	API_INIT_SESSION    ( exported_api.session    );
	API_INIT_DISP       ( exported_api.dispatch   );
	API_INIT_SEC        ( exported_api.security   );
}

/* Initialize the extensions module */
int ext_init( void ) 
{
	TRACE_ENTRY("");
	uti_list_init( &ext_list, NULL );
	api_init();
	return 0;
}
	
/* Add a new extension in the list, for loading later */
int ext_register( char * filename, char * conffile )
{
	ext_t * new;
	
	TRACE_ENTRY("%p(%s) %p(%s)", filename, filename?filename:"", conffile, conffile?conffile:"");
	
	/* Check the filename is valid */
	CHECK_PARAMS( filename );
	
	/* Create a new object in the list */
	CHECK_MALLOC(  new = malloc( sizeof(ext_t) )  );
	memset(new, 0, sizeof(ext_t));
	uti_list_init(&new->chain, new);
	
	/* Copy the filename in the object */
	CHECK_MALLOC(  new->filename = strdup(filename)  );
	
	if (conffile) {
		CHECK_MALLOC(  new->conffile = strdup(conffile)  );
	}
		
	/* we are done */
	uti_list_insert_before( &ext_list, (void *)new );
	
	TRACE_DEBUG (FULL, "%s added.", filename);
	
	return 0;
}

/* Actually load all the registered extensions */
int ext_load(void)
{
	int ret, (*waaad_ext_init)(waaad_api_t *, char *) = NULL;
	uti_list_t * li;
	
	TRACE_ENTRY();
	
	/* Loop on all extensions, in FIFO order */
	for (li = ext_list.next; li != &ext_list; li = li->next)
	{
		ext_t * ext = (ext_t *)(li->o);
		TRACE_DEBUG (INFO, "Loading extension: %s", ext->filename);
		
		/* Load the extension */
		ext->handler = dlopen(ext->filename, RTLD_LAZY | RTLD_GLOBAL);
		
		if (ext->handler == NULL) {
			/* An error occured */
			log_error("Loading of extension %s failed:\n %s\n", ext->filename, dlerror());
			TRACE_DEBUG (INFO, "Error occurred, message logged -- dlopen.");
			return EINVAL;
		}
		
		/* Resolve the entry point of the extension */
		waaad_ext_init = ( int (*) (waaad_api_t *, char *) )dlsym( ext->handler, "waaad_ext_init" );
		
		if (waaad_ext_init == NULL) {
			/* An error occured */
			log_error("Unable to resolve entry point 'waaad_ext_init' for extension %s:\n %s\n", ext->filename, dlerror());
			TRACE_DEBUG (INFO, "Error occurred, message logged -- dlsym.");
			return EINVAL;
		}
		
		/* Resolve the exit point of the extension, which is optional for extensions */
		ext->waaad_ext_fini = ( void (*) (void) )dlsym( ext->handler, "waaad_ext_fini" );
		
		if (ext->waaad_ext_fini == NULL) {
			/* Not provided */
			TRACE_DEBUG (FULL, "Extension [%s] has no waaad_ext_fini function.", ext->filename);
		} else {
			/* Provided */
			TRACE_DEBUG (FULL, "Extension [%s] waaad_ext_fini has been resolved successfully.", ext->filename);
		}
		
		/* Now call the entry point to initialize the extension */
		ret = (*waaad_ext_init)( &exported_api, ext->conffile );
		
		if (ret != 0) {
			/* The extension was unable to load cleanly */
			log_error("Extension %s returned an error during initialization: %s\n", ext->filename, strerror(ret));
			TRACE_DEBUG (INFO, "Error occurred, message logged -- waaad_ext_init.");
			return ret;
		}
		
		/* Proceed to the next extension */
	}
	
	/* We have finished. */
	return 0;
}


/* Now unload the extensions and free the memory */
int ext_fini( void ) 
{
	TRACE_ENTRY();
	
	/* Loop on all extensions, in FIFO order */
	while (!IS_LIST_EMPTY(&ext_list))
	{
		uti_list_t * li = ext_list.next;
		ext_t * ext = (ext_t *)(li->o);
	
		/* Unlink this element from the list */
		uti_list_unlink(li);
		
		/* Call the exit point of the extension, if it was resolved */
		if (ext->waaad_ext_fini != NULL) {
			TRACE_DEBUG (FULL, "Calling [%s]->waaad_ext_fini function.", ext->filename);
			(*ext->waaad_ext_fini)();
		}
		
		/* Now unload the extension */
		if (ext->handler) {
			TRACE_DEBUG (FULL, "Unloading %s", ext->filename);
			if ( dlclose(ext->handler) != 0 ) {
				TRACE_DEBUG (INFO, "Unloading [%s] failed : %s\n", ext->filename, dlerror());
			}
		}
		
		/* Free the object and continue */
		free(ext->filename);
		free(ext->conffile);
		free(ext);
	}
	
	/* We always return 0 since we would not handle an error anyway... */
	return 0;
}
			
			

		
		
		
		
		
		
		
			
"Welcome to our mercurial repository"