summaryrefslogtreecommitdiffstats
path: root/ctl-lib
diff options
context:
space:
mode:
authorRomain Forlot <romain.forlot@iot.bzh>2018-04-30 12:09:41 +0200
committerRomain Forlot <romain.forlot@iot.bzh>2018-05-11 11:33:25 +0200
commit641001d1d02790dbadea7db9e7d9e1638fe8c9ef (patch)
tree7093fea14c8fb8130de205e5d5c32b4117192c4b /ctl-lib
parent2fa16f981f6e5d86ac5938821e0c533786b60fc7 (diff)
Improve way to loading an action
Split and cleaner function that load from JSON object an object CtlActionT that could be used by the controller. Also use a new syntax that reduce the number of JSON fields to parse based on a URI syntax. Change-Id: Iabc447368ca56e3a4279fb728ba2f546e11c961b Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'ctl-lib')
-rw-r--r--ctl-lib/ctl-action.c201
-rw-r--r--ctl-lib/ctl-config.h4
-rw-r--r--ctl-lib/ctl-lua.c108
3 files changed, 153 insertions, 160 deletions
diff --git a/ctl-lib/ctl-action.c b/ctl-lib/ctl-action.c
index da2eef1..acad15d 100644
--- a/ctl-lib/ctl-action.c
+++ b/ctl-lib/ctl-action.c
@@ -137,23 +137,124 @@ STATIC void ActionDynRequest (AFB_ReqT request) {
}
#endif
+/*** This function will fill the CtlActionT pointer given in parameters for a
+ * given api using an 'uri' that specify the C plugin to use and the name of
+ * the function
+ *
+ */
+static int BuildPluginAction(AFB_ApiT apiHandle, const char *uri, const char *function, CtlActionT *action)
+{
+ json_object *callbackJ = NULL;
+
+ if(!action) {
+ AFB_ApiError(apiHandle, "Action not valid");
+ return -1;
+ }
+
+ action->type = CTL_TYPE_CB;
+
+ if(uri && function) {
+ if(wrap_json_pack(&callbackJ, "{ss,ss,s?o*}",
+ "plugin", uri,
+ "function", function,
+ "args", action->argsJ)) {
+ AFB_ApiError(apiHandle, "Error packing Callback JSON object for plugin %s and function %s", uri, function);
+ return -1;
+ }
+ else {
+ return PluginGetCB(apiHandle, action, callbackJ);
+ }
+ }
+ else {
+ AFB_ApiError(apiHandle, "Miss something uri or function.");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*** This function will fill the CtlActionT pointer given in parameters for a
+ * given api using an 'uri' that specify the API to use and the name of the
+ * verb
+ *
+ * Be aware that 'uri' and 'function' could be null but will result in
+ * unexpected result.
+ *
+ */
+static int BuildApiAction(AFB_ApiT apiHandle, const char *uri, const char *function, CtlActionT *action)
+{
+ if(!action) {
+ AFB_ApiError(apiHandle, "Action not valid");
+ return -1;
+ }
+
+ action->type = CTL_TYPE_API;
+ action->exec.subcall.api = uri;
+ action->exec.subcall.verb = function;
+
+ return 0;
+}
+
+/*** This function will fill the CtlActionT pointer given in parameters for a
+ * given api using an 'uri' that specify the Lua plugin to use and the name of
+ * the function.
+ *
+ * Be aware that 'uri' and 'function' could be null but will result in
+ * unexpected result.
+ *
+ */
+#ifdef CONTROL_SUPPORT_LUA
+static int BuildLuaAction(AFB_ApiT apiHandle, const char *uri, const char *function, CtlActionT *action)
+{
+ if(!action) {
+ AFB_ApiError(apiHandle, "Action not valid");
+ return -1;
+ }
+
+ action->type = CTL_TYPE_LUA;
+ action->exec.lua.plugin = uri;
+ action->exec.lua.funcname = function;
+
+ return 0;
+}
+#endif
+
+static int BuildOneAction(AFB_ApiT apiHandle, CtlActionT *action, const char *uri, const char *function) {
+ size_t lua_pre_len = strlen(LUA_ACTION_PREFIX);
+ size_t api_pre_len = strlen(API_ACTION_PREFIX);
+ size_t plugin_pre_len = strlen(PLUGIN_ACTION_PREFIX);
+
+ if(uri && function && action) {
+ if(! strncasecmp(uri, LUA_ACTION_PREFIX, lua_pre_len)) {
+#ifdef CONTROL_SUPPORT_LUA
+ return BuildLuaAction(apiHandle, &uri[lua_pre_len], function, action);
+#else
+ AFB_ApiError(apiHandle, "LUA support not selected at build. Feature disabled");
+ return -1;
+#endif
+ }
+ else if(! strncasecmp(uri, API_ACTION_PREFIX, api_pre_len)) {
+ return BuildApiAction(apiHandle, &uri[api_pre_len], function, action);
+ }
+ else if(! strncasecmp(uri, PLUGIN_ACTION_PREFIX, plugin_pre_len)) {
+ return BuildPluginAction(apiHandle, &uri[plugin_pre_len], function, action);
+ }
+ else {
+ AFB_ApiError(apiHandle, "Wrong uri specified. You have to specified 'lua://', 'plugin://' or 'api://'. (%s)", function);
+ return -1;
+ }
+ }
+
+ AFB_ApiError(apiHandle, "Uri, Action or function not valid");
+ return -1;
+}
+
// unpack individual action object
PUBLIC int ActionLoadOne(AFB_ApiT apiHandle, CtlActionT *action, json_object *actionJ, int exportApi) {
- int err, modeCount = 0;
- json_object *callbackJ=NULL, *luaJ=NULL, *subcallJ=NULL;
-
- err = wrap_json_unpack(actionJ, "{ss,s?s,s?s,s?o,s?o,s?o,s?o !}",
- "uid", &action->uid,
- "info", &action->info,
- "privileges", &action->privileges,
- "callback", &callbackJ,
- "lua", &luaJ,
- "subcall", &subcallJ,
- "args", &action->argsJ);
- if (err) {
- AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Action missing uid|[info]|[callback]|[lua]|[subcall]|[args] in:\n-- %s", json_object_get_string(actionJ));
- goto OnErrorExit;
- }
+ int err = 0;
+ const char *uri = NULL, *function = NULL;
+
+ memset(action, 0, sizeof(CtlActionT));
// save per action api handle
action->api = apiHandle;
@@ -170,67 +271,36 @@ PUBLIC int ActionLoadOne(AFB_ApiT apiHandle, CtlActionT *action, json_object *ac
}
#endif
- if (luaJ) {
- modeCount++;
-
- action->type = CTL_TYPE_LUA;
- switch (json_object_get_type(luaJ)) {
- case json_type_object:
- err = wrap_json_unpack(luaJ, "{s?s,s:s !}", "load", &action->exec.lua.load, "func", &action->exec.lua.funcname);
- if (err) {
- AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Lua action missing [load]|func in:\n-- %s", json_object_get_string(luaJ));
- goto OnErrorExit;
- }
- break;
- case json_type_string:
- action->exec.lua.funcname = json_object_get_string(luaJ);
- break;
- default:
- AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Lua action invalid syntax in:\n-- %s", json_object_get_string(luaJ));
- goto OnErrorExit;
+ if(actionJ) {
+ err = wrap_json_unpack(actionJ, "{ss,s?s,ss,ss,s?s,s?o !}",
+ "uid", &action->uid,
+ "info", &action->info,
+ "uri", &uri,
+ "function", &function,
+ "privileges", &action->privileges,
+ "args", &action->argsJ);
+ if(!err) {
+ err = BuildOneAction(apiHandle, action, uri, function);
}
- }
-
- if (subcallJ) {
- modeCount++;
- action->type = CTL_TYPE_API;
-
- err = wrap_json_unpack(subcallJ, "{s?s,s:s !}", "api", &action->exec.subcall.api, "verb", &action->exec.subcall.verb);
- if (err) {
- AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Subcall missing [load]|func in:\n-- %s", json_object_get_string(subcallJ));
- goto OnErrorExit;
+ else {
+ AFB_ApiError(apiHandle, "Wrong action JSON object parameter: (%s)", json_object_to_json_string(actionJ));
+ err = -1;
}
}
-
- if (callbackJ) {
- modeCount++;
- action->type = CTL_TYPE_CB;
- err = PluginGetCB (apiHandle, action, callbackJ);
- if (err) goto OnErrorExit;
+ else {
+ AFB_ApiError(apiHandle, "Wrong action JSON object parameter: (%s)", json_object_to_json_string(actionJ));
+ err = -1;
}
- // make sure at least one mode is selected
- if (modeCount == 0) {
- AFB_ApiError(apiHandle,"ACTION-LOAD-ONE No Action Selected lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
- goto OnErrorExit;
- }
-
- if (modeCount > 1) {
- AFB_ApiError(apiHandle,"ACTION-LOAD-ONE:ToMany arguments lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
- goto OnErrorExit;
- }
- return 0;
-
-OnErrorExit:
- return 1;
-};
+ return err;
+}
PUBLIC CtlActionT *ActionConfig(AFB_ApiT apiHandle, json_object *actionsJ, int exportApi) {
int err;
CtlActionT *actions;
// action array is close with a nullvalue;
- if (json_object_get_type(actionsJ) == json_type_array) {
+ if (json_object_is_type(actionsJ, json_type_array)) {
size_t count = json_object_array_length(actionsJ);
actions = calloc(count + 1, sizeof (CtlActionT));
@@ -251,5 +321,4 @@ PUBLIC CtlActionT *ActionConfig(AFB_ApiT apiHandle, json_object *actionsJ, int e
OnErrorExit:
return NULL;
-
}
diff --git a/ctl-lib/ctl-config.h b/ctl-lib/ctl-config.h
index 432d86c..d36b5f5 100644
--- a/ctl-lib/ctl-config.h
+++ b/ctl-lib/ctl-config.h
@@ -45,6 +45,10 @@ extern "C" {
#define CTL_PLUGIN_EXT ".ctlso"
#endif
+#define LUA_ACTION_PREFIX "lua://"
+#define API_ACTION_PREFIX "api://"
+#define PLUGIN_ACTION_PREFIX "plugin://"
+
typedef struct ConfigSectionS {
const char *key;
const char *uid;
diff --git a/ctl-lib/ctl-lua.c b/ctl-lib/ctl-lua.c
index d5c2975..89c10b9 100644
--- a/ctl-lib/ctl-lua.c
+++ b/ctl-lib/ctl-lua.c
@@ -35,9 +35,8 @@
#define LUA_MSG_MAX_LENGTH 512
#define JSON_ERROR (json_object*)-1
-
-extern CtlLua2cFuncT *ctlLua2cFunc;
static lua_State* luaState;
+CtlPluginT *ctlPlugins = NULL;
#ifndef CTX_MAGIC
static int CTX_MAGIC;
@@ -740,18 +739,17 @@ PUBLIC int LuaCallFunc (CtlSourceT *source, CtlActionT *action, json_object *que
PUBLIC int luaLoadScript(const char *luaScriptPath)
{
- int err = luaL_loadfile(luaState, luaScriptPath);
- if (err) {
- AFB_ApiError(source->api, "LUA-DOSCRIPT HOOPs Error in LUA loading scripts=%s err=%s", luaScriptPath, lua_tostring(luaState,-1));
+ int err = 0;
+
+ if(!luaScriptPath)
+ return -1;
+
+ err = luaL_loadfile(luaState, luaScriptPath);
+ if (err)
return err;
- }
// Script was loaded we need to parse to make it executable
err = lua_pcall(luaState, 0, 0, 0);
- if (err) {
- AFB_ApiError(source->api, "LUA-DOSCRIPT:FAIL to load %s", luaScriptPath);
- return err;
- }
return err;
}
@@ -804,9 +802,11 @@ STATIC int LuaDoScript(json_object *queryJ, CtlSourceT *source)
}
}
- err = luaLoadScript(luaScriptPath);
- if(err)
+ err = LuaLoadScript(luaScriptPath);
+ if(err) {
+ AFB_ApiError(source->api, "LUA-DOSCRIPT HOOPs Error in LUA loading scripts=%s err=%s", luaScriptPath, lua_tostring(luaState,-1));
return err;
+ }
// if no func name given try to deduct from filename
if (!func && (func=(char*)GetMidleName(filename))!=NULL) {
@@ -1243,12 +1243,12 @@ OnErrorExit:
// Register a new L2c list of LUA user plugin commands
-PUBLIC void LuaL2cNewLib(luaL_Reg *l2cFunc, int count) {
+void LuaL2cNewLib(luaL_Reg *l2cFunc, int count, const char *prefix) {
// luaL_newlib(luaState, l2cFunc); macro does not work with pointer :(
luaL_checkversion(luaState);
lua_createtable(luaState, 0, count+1);
luaL_setfuncs(luaState,l2cFunc,0);
- lua_setglobal(luaState, "L2C");
+ lua_setglobal(luaState, prefix);
}
static const luaL_Reg afbFunction[] = {
@@ -1314,84 +1314,4 @@ PUBLIC int LuaConfigLoad (AFB_ApiT apiHandle) {
}
return 0;
-
- OnErrorExit:
- free(luaState);
- return 1;
-}
-
-// Create Binding Event at Init Exec Time
-PUBLIC int LuaConfigExec (AFB_ApiT apiHandle, const char* prefix) {
-
- int err, index;
-
- // create L2C mapping before any LUA script is loaded
- if (ctlLua2cFunc && ctlLua2cFunc->l2cCount) {
- LuaL2cNewLib (ctlLua2cFunc->l2cFunc, ctlLua2cFunc->l2cCount);
- }
-
- // search for default policy config files
- char fullprefix[CONTROL_MAXPATH_LEN] = "";
- if(prefix)
- strncpy (fullprefix, prefix, strlen(prefix)+1);
- else
- strncat (fullprefix, GetBinderName(), strlen(GetBinderName()));
-
- strncat (fullprefix, "-", strlen("-"));
-
- const char *dirList= getenv("CONTROL_LUA_PATH");
- //if (!dirList) dirList=CONTROL_LUA_PATH;
-
- // special case for no lua even when avaliable
- if (!strcasecmp ("/dev/null", dirList)) {
- return 0;
- }
-
- json_object *luaScriptPathJ = ScanForConfig(dirList , CTL_SCAN_RECURSIVE, fullprefix, "lua");
-
- // load+exec any file found in LUA search path
- if(luaScriptPathJ) {
- for (index=0; index < json_object_array_length(luaScriptPathJ); index++) {
- json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index);
-
- char *filename; char*fullpath;
- err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename);
- if (err) {
- AFB_ApiError(apiHandle, "LUA-INIT HOOPs invalid config file path = %s", json_object_get_string(entryJ));
- goto OnErrorExit;
- }
-
- char filepath[CONTROL_MAXPATH_LEN];
- strncpy(filepath, fullpath, strlen(fullpath)+1);
- strncat(filepath, "/", strlen("/"));
- strncat(filepath, filename, strlen(filename));
- err= luaL_loadfile(luaState, filepath);
- if (err) {
- AFB_ApiError(apiHandle, "LUA-LOAD HOOPs Error in LUA loading scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
- goto OnErrorExit;
- }
-
- // exec/compil script
- err = lua_pcall(luaState, 0, 0, 0);
- if (err) {
- AFB_ApiError(apiHandle, "LUA-LOAD HOOPs Error in LUA exec scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
- goto OnErrorExit;
- } else {
- AFB_ApiNotice(apiHandle, "LUA-LOAD '%s'", filepath);
- }
- }
-
- json_object_put(luaScriptPathJ);
- // no policy config found remove control API from binder
- if (index == 0) {
- AFB_ApiWarning (apiHandle, "POLICY-INIT:WARNING (setenv CONTROL_LUA_PATH) No LUA '%s*.lua' in '%s'", fullprefix, dirList);
- }
- }
- else AFB_ApiWarning (apiHandle, "POLICY-INIT:WARNING (setenv CONTROL_LUA_PATH) No LUA '%s*.lua' in '%s'", fullprefix, dirList);
-
- AFB_ApiDebug (apiHandle, "Control: LUA Init Done");
- return 0;
-
- OnErrorExit:
- return 1;
}