[SR-Dev] git:sip-router: modules: support for mod_register

Daniel-Constantin Mierla miconda at gmail.com
Thu Nov 20 22:20:53 CET 2008


Module: sip-router
Branch: daniel/pv
Commit: ea31876f3efd0d33fd86352299981dd16e3f7908
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ea31876f3efd0d33fd86352299981dd16e3f7908

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Thu Nov 20 17:33:44 2008 +0100

modules: support for mod_register

- new mod_register function added to the module interface
 (separate from exports structure):
    If a module exports a mod_register function it will be called
    immediately after loading the module and checking the module
    version and module interface (this means way before calling
    mod_init).
    The mod_register function prototype is:
    int mod_register(char* path, int* dlflags, void* r1, void* r2)
    where path is the module path including the filename, dlflags
    is a pointer to the dlflags used when loading the module (If
    the value is changed to a different and non-zero value, the
    module will be reloaded with the new flags), and r1 and r2 are
    parameters reserved for future use.
    A 0 return means success and -1 means error (the module will not
    be loaded).
    This new function can be used to register new parsing functions,
    alter dynamically the mod_exports structure contents a.s.o.
- kamailio compatible mod exports dlflags handling (but a warning
  will be printed saying this is deprecated and the preferred way
  is using mod_register().

---

 sr_module.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 sr_module.h |   14 ++++++++++++++
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/sr_module.c b/sr_module.c
index 21d89ac..491e971 100644
--- a/sr_module.c
+++ b/sr_module.c
@@ -216,17 +216,29 @@ static inline int version_control(void *handle, char *path)
 	return 0;
 }
 
-/* returns 0 on success , <0 on error */
+/** load a sr module.
+ * tries to load the module specified by path.
+ * If modname does contain a '/' or a '.' it would be assumed to contain a 
+ * path to the module and it will be used as give.
+ * else <MODS_DIR>/<modname>.so will be tried and if this fails
+ *  <MODS_DIR>/<modname>/<modname>.so
+ * @param modname - path or module name
+ * @return 0 on success , <0 on error
+ */
 int load_module(char* path)
 {
 	void* handle;
 	char* error;
+	mod_register_function mr;
 	union module_exports_u* exp;
 	unsigned* mod_if_ver;
 	struct sr_module* t;
 	struct stat stat_buf;
 	char* modname;
 	int len;
+	int dlflags;
+	int new_dlflags;
+	int retries;
 
 #ifndef RTLD_NOW
 /* for openbsd */
@@ -287,7 +299,9 @@ int load_module(char* path)
 		}
 #endif /* !EXTRA_DEBUG */
 	}
-
+	retries=2;
+	dlflags=RTLD_NOW;
+reload:
 	handle=dlopen(path, RTLD_NOW); /* resolve all symbols now */
 	if (handle==0){
 		LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n",
@@ -314,11 +328,47 @@ int load_module(char* path)
 		goto error1;
 	}
 	/* launch register */
+	mr = (mod_register_function)dlsym(handle, DLSYM_PREFIX "mod_register");
+	if (((error =(char*)dlerror())==0) && mr) {
+		/* no error call it */
+		new_dlflags=dlflags;
+		if (mr(path, &dlflags, 0, 0)!=0) {
+			LOG(L_ERR, "ERROR: load_module: %s: mod_register failed\n", path);
+			goto error1;
+		}
+		if (new_dlflags!=dlflags && new_dlflags!=0) {
+			/* we have to reload the module */
+			dlclose(handle);
+			dlflags=new_dlflags;
+			retries--;
+			if (retries>0) goto reload;
+			LOG(L_ERR, "ERROR: load_module: %s: cannot agree"
+					" on the dlflags\n", path);
+			goto error;
+		}
+	}
 	exp = (union module_exports_u*)dlsym(handle, DLSYM_PREFIX "exports");
 	if ( (error =(char*)dlerror())!=0 ){
 		LOG(L_ERR, "ERROR: load_module: %s\n", error);
 		goto error1;
 	}
+	/* hack to allow for kamailio style dlflags inside exports */
+	if (*mod_if_ver == 1) {
+		new_dlflags = exp->v1.dlflags;
+		if (new_dlflags!=dlflags && new_dlflags!=DEFAULT_DLFLAGS) {
+			/* we have to reload the module */
+			dlclose(handle);
+			WARN("%s: exports dlflags interface is deprecated and it will not"
+					"be supported in newer versions; consider using"
+					" mod_register() instead", path);
+			dlflags=new_dlflags;
+			retries--;
+			if (retries>0) goto reload;
+			LOG(L_ERR, "ERROR: load_module: %s: cannot agree"
+					" on the dlflags\n", path);
+			goto error;
+		}
+	}
 	if (register_module(*mod_if_ver, exp, path, handle)<0) goto error1;
 	return 0;
 
diff --git a/sr_module.h b/sr_module.h
index f2aea0e..13474cd 100644
--- a/sr_module.h
+++ b/sr_module.h
@@ -89,6 +89,20 @@
 
 #endif
 
+/** type used for the mod_register function export.
+ *  mod_register is a function called when loading a module
+ *  (if present), prior to registering the module exports.
+ *  @param path - path to the module, including file name
+ *  @param dlflags - pointer to the dlflags used when loading the module.
+ *                   If the value is changed to a different and non-zero
+ *                   value, the module will be reloaded with the new flags.
+ *  @param reserved1 - reserved for future use.
+ *  @param reserved2 - reserver for future use
+ *  @return 0 on success, -1 on error, all the other values are reserved
+ *                      for future use (<0 meaning error and >0 success)
+ */
+typedef  int (*mod_register_function)(char*, int*, void*, void*);
+
 typedef  struct module_exports* (*module_register)(void);
 typedef  int (*cmd_function)(struct sip_msg*, char*, char*);
 typedef  int (*cmd_function3)(struct sip_msg*, char*, char*, char*);




More information about the sr-dev mailing list