Module: sip-router Branch: daniel/pv Commit: ea31876f3efd0d33fd86352299981dd16e3f7908 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ea31876f...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@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*);