From f817ce67ff6344f181d221c859e1cb2231a3dac4 Mon Sep 17 00:00:00 2001 From: fulup Date: Tue, 8 Aug 2017 18:52:13 +0200 Subject: Early Draft of LUA integration --- Controler-afb/ctl-lua.c | 380 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 Controler-afb/ctl-lua.c (limited to 'Controler-afb/ctl-lua.c') diff --git a/Controler-afb/ctl-lua.c b/Controler-afb/ctl-lua.c new file mode 100644 index 0000000..0e44bc9 --- /dev/null +++ b/Controler-afb/ctl-lua.c @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ref: + * http://www.troubleshooters.com/codecorn/lua/lua_c_calls_lua.htm#_Anatomy_of_a_Lua_Call + * http://acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/ + */ + +#define _GNU_SOURCE +#include +#include +#include + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + +#include "ctl-binding.h" +#include "wrap-json.h" + + +static lua_State* luaState; + +typedef enum { + LUA_DOCALL, + LUA_DOSTRING, + LUA_DOSCRIPT, +} LuaDoActionT; + +// List Avaliable Configuration Files +PUBLIC json_object* ScanForConfig (char* searchPath, char *pre, char *ext) { + json_object *responseJ; + DIR *dirHandle; + char *dirPath; + char* dirList= strdup(searchPath); + size_t extLen = strlen(ext); + + responseJ = json_object_new_array(); + for (dirPath= strtok(dirList, ":"); dirPath && *dirPath; dirPath=strtok(NULL,":")) { + struct dirent *dirEnt; + + dirHandle = opendir (dirPath); + if (!dirHandle) { + AFB_NOTICE ("CONFIG-SCANNING dir=%s not readable", dirPath); + continue; + } + + AFB_NOTICE ("CONFIG-SCANNING:ctl_listconfig scanning: %s", dirPath); + while ((dirEnt = readdir(dirHandle)) != NULL) { + // Unknown type is accepted to support dump filesystems + if (dirEnt->d_type == DT_REG || dirEnt->d_type == DT_UNKNOWN) { + + // check prefix and extention + size_t extIdx=strlen(dirEnt->d_name) - extLen; + if (extIdx <= 0) continue; + if (pre && !strcasestr (dirEnt->d_name, pre)) continue; + if (ext && strcasecmp (ext, &dirEnt->d_name[extIdx])) continue; + + struct json_object *pathJ = json_object_new_object(); + json_object_object_add(pathJ, "dirpath", json_object_new_string(dirPath)); + json_object_object_add(pathJ, "filename", json_object_new_string(dirEnt->d_name)); + json_object_array_add(responseJ, pathJ); + } + } + } + + free (dirList); + return (responseJ); +} + +STATIC int LuaPrintNotice(lua_State* luaState) { + int count = lua_gettop(luaState); + + for (int idx=1; idx <= count; ++idx) { + const char *str = lua_tostring(luaState, idx); // Get string + + // Output string. + AFB_NOTICE (str); + } + + return 0; // no value return +} + +STATIC int LuaPushArgument (json_object *arg) { + + switch (json_object_get_type(arg)) { + case json_type_object: + lua_newtable (luaState); + json_object_object_foreach (arg, key, val) { + int done = LuaPushArgument (val); + if (done) { + lua_pushstring(luaState, key); // table.key = val + lua_settable(luaState, -3); + } + } + + break; + case json_type_int: + lua_pushinteger(luaState, json_object_get_int(arg)); + break; + case json_type_string: + lua_pushstring(luaState, json_object_get_string(arg)); + break; + case json_type_boolean: + lua_pushboolean(luaState, json_object_get_boolean(arg)); + break; + case json_type_double: + lua_pushnumber(luaState, json_object_get_double(arg)); + break; + default: + return 0; + } + + return 1; +} + +// Generated some fake event based on watchdog/counter +PUBLIC void LuaDoAction (LuaDoActionT action, afb_req request) { + + int err, count=0; + + json_object* queryJ = afb_req_json(request); + + switch (action) { + + case LUA_DOSTRING: { + const char *script = json_object_get_string(queryJ); + err=luaL_loadstring(luaState, script); + if (err) { + AFB_ERROR ("LUA-DO-COMPILE:FAIL String=%s err=%s", script, lua_tostring(luaState,-1) ); + goto OnErrorExit; + } + break; + } + + case LUA_DOCALL: { + const char *func; + json_object *args; + err= wrap_json_unpack (queryJ, "{s:s, s?o !}", "func", &func,"args", &args); + if (err) { + AFB_ERROR ("LUA-DOCALL-SYNTAX missing func|args args=%s", json_object_get_string(queryJ)); + goto OnErrorExit; + } + + // load function (should exist in CONTROL_PATH_LUA + lua_getglobal(luaState, func); + + // push arguments on the stack + if (json_object_get_type(args) != json_type_array) { + count= LuaPushArgument (args); + } else { + for (int idx=0; idx