summaryrefslogtreecommitdiffstats
path: root/ctl-lib/ctl-plugin.c
diff options
context:
space:
mode:
authorRomain Forlot <romain.forlot@iot.bzh>2018-05-06 14:24:42 +0200
committerRomain Forlot <romain.forlot@iot.bzh>2018-12-13 15:02:54 +0100
commit6fed20d35d556afa95537a2be0b0efc8a2dd24c7 (patch)
treeab073906b708cfb2fd7811de5e440e27515087da /ctl-lib/ctl-plugin.c
parentfc2e5bc18026460bddcfd84c74e880193079a5c9 (diff)
Upgrade config schema
Change the way to load LUA scripts. They are now considerate as Plugin and loads with them. This imply rework of how to search and find plugins as well as the way to load LUA. Also load an harcoded LUA scripts providing LUA helpers and managing global variables lock unlock mechanism Change-Id: I64e38aa27278d0cfdca787155db2d0c89953f905 Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'ctl-lib/ctl-plugin.c')
-rw-r--r--ctl-lib/ctl-plugin.c234
1 files changed, 163 insertions, 71 deletions
diff --git a/ctl-lib/ctl-plugin.c b/ctl-lib/ctl-plugin.c
index 2520d77..3e3e16e 100644
--- a/ctl-lib/ctl-plugin.c
+++ b/ctl-lib/ctl-plugin.c
@@ -84,77 +84,19 @@ STATIC int DispatchOneL2c(void* luaState, char *funcname, Lua2cFunctionT callbac
#endif
}
-STATIC int PluginLoadOne (AFB_ApiT apiHandle, CtlPluginT *ctlPlugin, json_object *pluginJ, void* handle) {
- json_object *lua2csJ = NULL, *pluginPathJ = NULL;
- const char*ldSearchPath = NULL, *basename = NULL;
- void *dlHandle;
+STATIC int PluginLoadCOne(AFB_ApiT apiHandle, const char *pluginpath, json_object *lua2csJ, void * handle, CtlPluginT *ctlPlugin)
+{
+ void *dlHandle = dlopen(pluginpath, RTLD_NOW);
-
- // plugin initialises at 1st load further init actions should be place into onload section
- if (!pluginJ) return 0;
-
- int err = wrap_json_unpack(pluginJ, "{ss,s?s,s?s,s?s,s?o !}",
- "uid", &ctlPlugin->uid,
- "info", &ctlPlugin->info,
- "ldpath", &ldSearchPath,
- "basename", &basename,
- "lua2c", &lua2csJ);
- if (err) {
- AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Plugin missing uid|[info]|basename|[ldpath]|[lua2c] in:\n-- %s", json_object_get_string(pluginJ));
- goto OnErrorExit;
- }
-
- // default basename equal uid
- if (!basename) basename=ctlPlugin->uid;
-
- // if search path not in Json config file, then try default
- if (!ldSearchPath)
- {
- char path[CONTROL_MAXPATH_LEN];
- memset(path, 0, sizeof(path));
- const char *envpath = getenv("CONTROL_PLUGIN_PATH");
- envpath ?
- strncat(path, envpath, strlen(envpath)):
- strncat(path, CONTROL_PLUGIN_PATH, strlen(CONTROL_PLUGIN_PATH));
- const char *bPath = GetBindingDirPath();
- strncat(path, ":", strlen(":"));
- strncat(path, bPath, strlen(bPath));
- ldSearchPath = path;
- }
-
- // search for default policy config file
- pluginPathJ = ScanForConfig(ldSearchPath, CTL_SCAN_RECURSIVE, basename, CTL_PLUGIN_EXT);
- if (!pluginPathJ || json_object_array_length(pluginPathJ) == 0) {
- AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Missing plugin=%s*%s (config ldpath?) search=\n-- %s", basename, CTL_PLUGIN_EXT, ldSearchPath);
- goto OnErrorExit;
- }
-
- char *filename;
- char*fullpath;
- err = wrap_json_unpack(json_object_array_get_idx(pluginPathJ, 0), "{s:s, s:s !}", "fullpath", &fullpath, "filename", &filename);
- if (err) {
- AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE HOOPs invalid plugin file path=\n-- %s", json_object_get_string(pluginPathJ));
- goto OnErrorExit;
- }
-
- if (json_object_array_length(pluginPathJ) > 1) {
- AFB_ApiWarning(apiHandle, "CTL-PLUGIN-LOADONE plugin multiple instances in searchpath will use %s/%s", fullpath, filename);
- }
-
- char pluginpath[CONTROL_MAXPATH_LEN];
- strncpy(pluginpath, fullpath, strlen (fullpath)+1);
- strncat(pluginpath, "/", strlen ("/"));
- strncat(pluginpath, filename, strlen (filename));
- dlHandle = dlopen(pluginpath, RTLD_NOW);
if (!dlHandle) {
AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Fail to load pluginpath=%s err= %s", pluginpath, dlerror());
- goto OnErrorExit;
+ return -1;
}
CtlPluginMagicT *ctlPluginMagic = (CtlPluginMagicT*) dlsym(dlHandle, "CtlPluginMagic");
if (!ctlPluginMagic || ctlPluginMagic->magic != CTL_PLUGIN_MAGIC) {
AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE symbol'CtlPluginMagic' missing or != CTL_PLUGIN_MAGIC plugin=%s", pluginpath);
- goto OnErrorExit;
+ return -1;
} else {
AFB_ApiNotice(apiHandle, "CTL-PLUGIN-LOADONE %s successfully registered", ctlPluginMagic->uid);
}
@@ -175,7 +117,7 @@ STATIC int PluginLoadOne (AFB_ApiT apiHandle, CtlPluginT *ctlPlugin, json_object
#else
// Lua2cWrapper is part of binder and not expose to dynamic link
if (lua2csJ && lua2cInPlug) {
- *lua2cInPlug = DispatchOneL2c;
+ *lua2cInPlug = (Lua2cWrapperT)DispatchOneL2c;
int Lua2cAddOne(luaL_Reg *l2cFunc, const char* l2cName, int index) {
if(ctlLua2cFunc->l2cCount)
@@ -219,7 +161,7 @@ STATIC int PluginLoadOne (AFB_ApiT apiHandle, CtlPluginT *ctlPlugin, json_object
}
if (errCount) {
AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE %d symbols not found in plugin='%s'", errCount, pluginpath);
- goto OnErrorExit;
+ return -1;
}
int total = ctlLua2cFunc->l2cCount + count;
if(ctlLua2cFunc->l2cCount) {
@@ -240,21 +182,171 @@ STATIC int PluginLoadOne (AFB_ApiT apiHandle, CtlPluginT *ctlPlugin, json_object
ctlPlugin->context = (*ctlPluginOnload) (ctlPlugin, handle);
}
+ return 0;
+}
+
+STATIC int LoadFoundPlugins(AFB_ApiT apiHandle, json_object *scanResult, json_object *lua2csJ, void *handle, CtlPluginT *ctlPlugin)
+{
+ char pluginpath[CONTROL_MAXPATH_LEN];
+ char *filename;
+ char *fullpath;
+ char *ext;
+ int i;
+ size_t len;
+ json_object *object = NULL;
+
+ if (!json_object_is_type(scanResult, json_type_array))
+ return -1;
+
+ len = json_object_array_length(scanResult);
+
+ for (i = 0; i < len; ++i) {
+ object = json_object_array_get_idx(scanResult, i);
+ int err = wrap_json_unpack(object, "{s:s, s:s !}",
+ "fullpath", &fullpath,
+ "filename", &filename);
+
+ if (err) {
+ AFB_ApiError(apiHandle, "HOOPs invalid plugin file path=\n-- %s", json_object_get_string(scanResult));
+ return -1;
+ }
+
+ /* Make sure you don't load two found libraries */
+ ext = strrchr(filename, '.');
+ strncpy(pluginpath, fullpath, strlen (fullpath)+1);
+ strncat(pluginpath, "/", strlen ("/"));
+ strncat(pluginpath, filename, strlen (filename));
+
+ if(!strcasecmp(ext, CONTROL_PLUGIN_EXT)) {
+ if(ext && !strcasecmp(ext, CONTROL_PLUGIN_EXT) && i > 0) {
+ AFB_ApiWarning(apiHandle, "Plugin multiple instances in searchpath will use %s/%s", fullpath, filename);
+ return 0;
+ }
+ PluginLoadCOne(apiHandle, pluginpath, lua2csJ, handle, ctlPlugin);
+ }
+ else if(!strcasecmp(ext, CONTROL_SCRIPT_EXT)) {
+ ctlPlugin->api = apiHandle;
+ ctlPlugin->context = handle;
+ luaLoadScript(pluginpath);
+ }
+ }
+
+ return 0;
+}
+
+STATIC char *GetDefaultSearchPath()
+{
+ char *searchPath;
+ const char *bPath;
+ const char *envPath;
+ size_t bPath_len, envPath_len, CTL_PLGN_len;
+
+ bPath = GetBindingDirPath();
+ envPath = getenv("CONTROL_PLUGIN_PATH");
+ bPath_len = strlen(bPath);
+ envPath_len = envPath ? strlen(envPath) : 0;
+ CTL_PLGN_len = envPath_len ? 0 : strlen(CONTROL_PLUGIN_PATH);
+
+ /* Allocating with the size of binding root dir path + environment if found
+ * + 2 for the NULL terminating character and the additionnal separator
+ * between bPath and envPath concatenation.
+ */
+ if(envPath) {
+ searchPath = calloc(1, sizeof(char) *((bPath_len + envPath_len) + 2));
+ strncat(searchPath, envPath, envPath_len);
+ }
+ else {
+ searchPath = calloc(1, sizeof(char) * ((bPath_len + CTL_PLGN_len) + 2));
+ strncat(searchPath, CONTROL_PLUGIN_PATH, CTL_PLGN_len);
+ }
+
+ strncat(searchPath, ":", 1);
+ strncat(searchPath, bPath, bPath_len);
+
+ return searchPath;
+}
+
+STATIC int FindPlugins(AFB_ApiT apiHandle, const char *searchPath, const char *file, json_object **pluginPathJ)
+{
+ *pluginPathJ = ScanForConfig(searchPath, CTL_SCAN_RECURSIVE, file, NULL);
+ if (!*pluginPathJ || json_object_array_length(*pluginPathJ) == 0) {
+ AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Missing plugin=%s* (config ldpath?) search=\n-- %s", file, searchPath);
+ return -1;
+ }
+
+ return 0;
+}
+
+STATIC int PluginLoad (AFB_ApiT apiHandle, CtlPluginT *ctlPlugin, json_object *pluginJ, void *handle)
+{
+ int err = 0, i = 0;
+ char *searchPath;
+ const char *sPath = NULL, *file = NULL;
+ json_object *lua2csJ = NULL, *fileJ = NULL, *pluginPathJ = NULL;
+
+ // plugin initialises at 1st load further init actions should be place into onload section
+ if (!pluginJ) return 0;
+
+ err = wrap_json_unpack(pluginJ, "{ss,s?s,s?s,s?o,s?o !}",
+ "uid", &ctlPlugin->uid,
+ "info", &ctlPlugin->info,
+ "spath", &sPath,
+ "file", &fileJ,
+ "lua2c", &lua2csJ);
+ if (err) {
+ AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Plugin missing uid|[info]|file|[ldpath]|[lua2c] in:\n-- %s", json_object_get_string(pluginJ));
+ goto OnErrorExit;
+ }
+
+ // if search path not in Json config file, then try default
+ if(sPath)
+ searchPath = strdup(sPath);
+ else
+ searchPath = GetDefaultSearchPath();
+
+ // default file equal uid
+ if (!fileJ) {
+ file = ctlPlugin->uid;
+ if(FindPlugins(apiHandle, searchPath, file, &pluginPathJ))
+ goto OnErrorExit;
+ LoadFoundPlugins(apiHandle, pluginPathJ, lua2csJ, handle, ctlPlugin);
+ }
+ else if(json_object_is_type(fileJ, json_type_string)) {
+ file = json_object_get_string(fileJ);
+ if(FindPlugins(apiHandle, searchPath, file, &pluginPathJ))
+ goto OnErrorExit;
+ LoadFoundPlugins(apiHandle, pluginPathJ, lua2csJ, handle, ctlPlugin);
+ }
+ else if(json_object_is_type(fileJ, json_type_array)) {
+ for(i = 0; i < json_object_array_length(fileJ);++i) {
+ file = json_object_get_string(json_object_array_get_idx(fileJ, i));
+ if(FindPlugins(apiHandle, searchPath, file, &pluginPathJ))
+ goto OnErrorExit;
+ LoadFoundPlugins(apiHandle, pluginPathJ, lua2csJ, handle, ctlPlugin);
+ }
+ }
+
+ if(err)
+ goto OnErrorExit;
+
+ free(searchPath);
json_object_put(pluginPathJ); // No more needs for that json_object.
return 0;
OnErrorExit:
+ free(searchPath);
json_object_put(pluginPathJ); // No more needs for that json_object.
return 1;
}
PUBLIC int PluginConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *pluginsJ) {
- int err=0;
+ int err = 0;
+ int idx = 0;
+ size_t length = 0;
if (ctlPlugins)
{
- int idx = 0;
while(ctlPlugins[idx].uid != NULL)
{
// Jose hack to make verbosity visible from sharedlib and
@@ -267,15 +359,15 @@ PUBLIC int PluginConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *p
else
{
if (json_object_get_type(pluginsJ) == json_type_array) {
- size_t length = json_object_array_length(pluginsJ);
+ length = json_object_array_length(pluginsJ);
ctlPlugins = calloc (length+1, sizeof(CtlPluginT));
- for (int idx=0; idx < length; idx++) {
+ for (idx=0; idx < length; idx++) {
json_object *pluginJ = json_object_array_get_idx(pluginsJ, idx);
- err += PluginLoadOne(apiHandle, &ctlPlugins[idx], pluginJ, section->handle);
+ err += PluginLoad(apiHandle, &ctlPlugins[idx], pluginJ, section->handle);
}
} else {
ctlPlugins = calloc (2, sizeof(CtlPluginT));
- err += PluginLoadOne(apiHandle, &ctlPlugins[0], pluginsJ, section->handle);
+ err += PluginLoad(apiHandle, &ctlPlugins[0], pluginsJ, section->handle);
}
}