aboutsummaryrefslogtreecommitdiffstats
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
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>
-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;
}