changeset 732:4a0b61061a6d

Added simple mechanism to declare dependencies between extensions
author Sebastien Decugis <sdecugis@nict.go.jp>
date Fri, 25 Feb 2011 15:46:40 +0900
parents ef199d6185df
children b2bc31410425
files extensions/app_diameap/diameap.c extensions/app_sip/app_sip.c extensions/dict_eap/dict_eap.c extensions/test_sip/test_sip.c include/freeDiameter/extension.h libfdcore/extensions.c
diffstat 6 files changed, 73 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/extensions/app_diameap/diameap.c	Fri Feb 25 14:33:37 2011 +0900
+++ b/extensions/app_diameap/diameap.c	Fri Feb 25 15:46:40 2011 +0900
@@ -83,5 +83,5 @@
 }
 
 /* Define the entry point */
-EXTENSION_ENTRY("DiamEAP", diameap_main)
+EXTENSION_ENTRY("DiamEAP", diameap_main, "dict_eap")
 ;
--- a/extensions/app_sip/app_sip.c	Fri Feb 25 14:33:37 2011 +0900
+++ b/extensions/app_sip/app_sip.c	Fri Feb 25 15:46:40 2011 +0900
@@ -249,4 +249,4 @@
 	return ;
 }
 
-EXTENSION_ENTRY("app_sip", as_entry);
+EXTENSION_ENTRY("app_sip", as_entry, "dict_sip");
--- a/extensions/dict_eap/dict_eap.c	Fri Feb 25 14:33:37 2011 +0900
+++ b/extensions/dict_eap/dict_eap.c	Fri Feb 25 15:46:40 2011 +0900
@@ -527,4 +527,4 @@
 	return 0;
 }
 
-EXTENSION_ENTRY("dict_eap", deap_entry);
+EXTENSION_ENTRY("dict_eap", deap_entry, "dict_nasreq");
--- a/extensions/test_sip/test_sip.c	Fri Feb 25 14:33:37 2011 +0900
+++ b/extensions/test_sip/test_sip.c	Fri Feb 25 15:46:40 2011 +0900
@@ -239,5 +239,5 @@
 	return ;
 }
 
-EXTENSION_ENTRY("test_sip", ts_entry);
+EXTENSION_ENTRY("test_sip", ts_entry, "dict_sip");
 
--- a/include/freeDiameter/extension.h	Fri Feb 25 14:33:37 2011 +0900
+++ b/include/freeDiameter/extension.h	Fri Feb 25 15:46:40 2011 +0900
@@ -41,7 +41,8 @@
 #include <freeDiameter/libfdcore.h>
 
 /* Macro that define the entry point of the extension */
-#define EXTENSION_ENTRY(_name, _function)						\
+#define EXTENSION_ENTRY(_name, _function, _depends...)					\
+const char *fd_ext_depends[] = { _name , ## _depends , NULL };				\
 static int extension_loaded = 0;							\
 int fd_ext_init(int major, int minor, char * conffile) {				\
 	if ((major != FD_PROJECT_VERSION_MAJOR)						\
--- a/libfdcore/extensions.c	Fri Feb 25 14:33:37 2011 +0900
+++ b/libfdcore/extensions.c	Fri Feb 25 15:46:40 2011 +0900
@@ -45,6 +45,9 @@
 	char 		*filename;	/* extension filename. must be a dynamic library with fd_ext_init symbol. */
 	char 		*conffile;	/* optional configuration file name for the extension */
 	void 		*handler;	/* object returned by dlopen() */
+	const char 	**depends;	/* names of the other extensions this one depends on (if provided) */
+	char		*ext_name;	/* points to the extension name, either inside depends, or basename(filename) */
+	int		free_ext_name;	/* must be freed if it was malloc'd */
 	void		(*fini)(void);	/* optional address of the fd_ext_fini callback */
 };
 
@@ -86,6 +89,53 @@
 	}
 }
 
+/* Check the dependencies. The object must have been dlopened already. */
+static int check_dependencies(struct fd_ext_info * ext) 
+{
+	int i = 1;
+	TRACE_ENTRY( "%p", ext );
+	
+	/* Attempt to resolve the dependency array */
+	ext->depends = dlsym( ext->handler, "fd_ext_depends" );
+	if (!ext->depends) {
+		/* Duplicate the filename */
+		char * tmp = strdup(ext->filename);
+		ext->ext_name = strdup(basename(tmp));
+		free(tmp);
+		ext->free_ext_name = 1;
+		TRACE_DEBUG(FULL, "Old extension's [%s] API: missing dependencies (ignored)", ext->ext_name);
+		return 0;
+	}
+	
+	ext->ext_name = (char *)ext->depends[0];
+	
+	TRACE_DEBUG(FULL, "Checking dependencies for '%s'...", ext->ext_name);
+	
+	while (ext->depends[i]) {
+		struct fd_list * li;
+		for (li = ext_list.next; li != &ext->chain; li = li->next)
+		{
+			struct fd_ext_info * e = (struct fd_ext_info *)li;
+			if (!strcasecmp(e->ext_name, ext->depends[i])) {
+				/* the dependency was already loaded */
+				break;
+			}
+		}
+		
+		if (li == &ext->chain) {
+			/* the dependency was not found */
+			TRACE_DEBUG(NONE, "Error: extension [%s] depends on [%s] which was not loaded first.\nPlease fix your configuration file.",
+				ext->ext_name, ext->depends[i]);
+			return ESRCH;
+		}
+		
+		i++;
+	}
+
+	/* All dependencies resolved successfully */
+	return 0;
+}
+
 /* Load all extensions in the list */
 int fd_ext_load()
 {
@@ -110,10 +160,21 @@
 #endif /* DEBUG */
 		if (ext->handler == NULL) {
 			/* An error occured */
-			TRACE_DEBUG( NONE, "Loading of extension %s failed:\n %s\n", ext->filename, dlerror());
+			TRACE_DEBUG( NONE, "Loading of extension %s failed:\n %s", ext->filename, dlerror());
+			#ifdef DEBUG
+			ext->handler = dlopen(ext->filename, RTLD_LAZY | RTLD_GLOBAL);
+			if (ext->handler) {
+				if (!check_dependencies(ext)) {
+					TRACE_DEBUG( NONE, "In addition, all declared dependencies are satisfied (Internal Error!)\n");
+				}
+			}
+			#endif /* DEBUG */
 			return EINVAL;
 		}
 		
+		/* Check if declared dependencies are satisfied. */
+		CHECK_FCT( check_dependencies(ext) );
+		
 		/* Resolve the entry point of the extension */
 		fd_ext_init = ( int (*) (int, int, char *) )dlsym( ext->handler, "fd_ext_init" );
 		
@@ -167,21 +228,23 @@
 		
 		/* Call the exit point of the extension, if it was resolved */
 		if (ext->fini != NULL) {
-			TRACE_DEBUG (FULL, "Calling [%s]->fd_ext_fini function.", ext->filename);
+			TRACE_DEBUG (FULL, "Calling [%s]->fd_ext_fini function.", ext->ext_name ?: ext->filename);
 			(*ext->fini)();
 		}
 		
 #ifndef SKIP_DLCLOSE
 		/* Now unload the extension */
 		if (ext->handler) {
-			TRACE_DEBUG (FULL, "Unloading %s", ext->filename);
+			TRACE_DEBUG (FULL, "Unloading %s", ext->ext_name ?: ext->filename);
 			if ( dlclose(ext->handler) != 0 ) {
-				TRACE_DEBUG (INFO, "Unloading [%s] failed : %s\n", ext->filename, dlerror());
+				TRACE_DEBUG (INFO, "Unloading [%s] failed : %s\n", ext->ext_name ?: ext->filename, dlerror());
 			}
 		}
 #endif /* SKIP_DLCLOSE */
 		
 		/* Free the object and continue */
+		if (ext->free_ext_name)
+			free(ext->ext_name);
 		free(ext->filename);
 		free(ext->conffile);
 		free(ext);
"Welcome to our mercurial repository"