diff options
Diffstat (limited to 'controller')
-rw-r--r-- | controller/CMakeLists.txt | 43 | ||||
-rw-r--r-- | controller/ctl-action.c | 180 | ||||
-rw-r--r-- | controller/ctl-config.c | 225 | ||||
-rw-r--r-- | controller/ctl-config.h | 120 | ||||
-rw-r--r-- | controller/ctl-lua.c | 1080 | ||||
-rw-r--r-- | controller/ctl-lua.h | 90 | ||||
-rw-r--r-- | controller/ctl-onload.c | 57 | ||||
-rw-r--r-- | controller/ctl-plugin.c | 248 | ||||
-rw-r--r-- | controller/ctl-plugin.h | 84 | ||||
-rw-r--r-- | controller/ctl-timer.c | 101 | ||||
-rw-r--r-- | controller/ctl-timer.h | 42 |
11 files changed, 0 insertions, 2270 deletions
diff --git a/controller/CMakeLists.txt b/controller/CMakeLists.txt deleted file mode 100644 index 5269bcc..0000000 --- a/controller/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -########################################################################### -# Copyright 2015, 2016, 2017 IoT.bzh -# -# author: Fulup Ar Foll <fulup@iot.bzh> -# -# 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. -########################################################################### - -# Include LUA only when requested -get_property(COMPDEF DIRECTORY PROPERTY COMPILE_DEFINITIONS) -if("CONTROL_SUPPORT_LUA=1" IN_LIST COMPDEF) - message(STATUS "Notice: LUA Controler Support Selected") - set(CTL_LUA_SOURCE ctl-lua.c ctl-timer.c) - ADD_COMPILE_OPTIONS(-DCONTROL_SUPPORT_LUA) -else() - message(STATUS "Warning: LUA Without Support ") -endif() - -# Add target to project dependency list -PROJECT_TARGET_ADD(afb-controller) - - # Define project Targets - ADD_LIBRARY(${TARGET_NAME} STATIC ctl-action.c ctl-config.c ctl-onload.c ctl-plugin.c ${CTL_LUA_SOURCE}) - - # Library dependencies (include updates automatically) - TARGET_LINK_LIBRARIES(${TARGET_NAME} - ${link_libraries} - ) - - # Define target includes for this target client - TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - ) diff --git a/controller/ctl-action.c b/controller/ctl-action.c deleted file mode 100644 index ff618d6..0000000 --- a/controller/ctl-action.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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, something express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Reference: - * Json load using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <string.h> - -#include "ctl-config.h" -#ifdef CONTROL_SUPPORT_LUA -#include "ctl-lua.h" -#endif - -int ActionExecOne(CtlActionT* action, json_object *queryJ) { - int err; - - switch (action->type) { - case CTL_TYPE_API: - { - json_object *returnJ; - - // if query is empty increment usage count and pass args else - // create new JSON object - if (!queryJ || json_object_get_type(queryJ) != json_type_object) { - if(action->argsJ) { - json_object_get(action->argsJ); - queryJ = action->argsJ; - } - else { - queryJ = json_object_new_object(); - } - } else if (action->argsJ) { - - // Merge queryJ and argsJ before sending request - if (json_object_get_type(action->argsJ) == json_type_object) { - - json_object_object_foreach(action->argsJ, key, val) { - json_object_object_add(queryJ, key, val); - } - } else { - json_object_object_add(queryJ, "args", action->argsJ); - } - } - json_object_object_add(queryJ, "label", json_object_new_string(action->source.label)); - - int err = afb_service_call_sync(action->api, action->call, queryJ, &returnJ); - if (err) { - static const char*format = "ActionExecOne(Api) api=%s verb=%s args=%s"; - AFB_ERROR(format, action->api, action->call, action->source.label); - goto OnErrorExit; - } - break; - } - -#ifdef CONTROL_SUPPORT_LUA - case CTL_TYPE_LUA: - err = LuaCallFunc(action, queryJ); - if (err) { - AFB_ERROR("ActionExecOne(Lua) label=%s func=%s args=%s", action->source.label, action->call, json_object_get_string(action->argsJ)); - goto OnErrorExit; - } - break; -#endif - - case CTL_TYPE_CB: - err = (*action->actionCB) (&action->source, action->argsJ, queryJ); - if (err) { - AFB_ERROR("ActionExecOne(Callback) label%s func=%s args=%s", action->source.label, action->call, json_object_get_string(action->argsJ)); - goto OnErrorExit; - } - break; - - default: - { - AFB_ERROR("ActionExecOne(unknown) API type label=%s", action->source.label); - goto OnErrorExit; - } - } - - return 0; - -OnErrorExit: - return -1; -} - - -// unpack individual action object - -int ActionLoadOne(CtlActionT *action, json_object *actionJ) { - char *api = NULL, *verb = NULL, *lua = NULL; - int err, modeCount = 0; - json_object *callbackJ=NULL; - - err = wrap_json_unpack(actionJ, "{ss,s?s,s?o,s?s,s?s,s?s,s?o !}" - , "label", &action->source.label, "info", &action->source.info, "callback", &callbackJ, "lua", &lua, "api", &api, "verb", &verb, "args", &action->argsJ); - if (err) { - AFB_ERROR("ACTION-LOAD-ONE Missing something label|info|callback|lua|(api+verb)|args in:\n-- %s", json_object_get_string(actionJ)); - goto OnErrorExit; - } - - if (lua) { - action->type = CTL_TYPE_LUA; - action->call = lua; - modeCount++; - } - - if (api && verb) { - action->type = CTL_TYPE_API; - action->api = api; - action->call = verb; - modeCount++; - } - - if (callbackJ) { - action->type = CTL_TYPE_CB; - modeCount++; - err = PluginGetCB (action, callbackJ); - if (err) goto OnErrorExit; - - } - - // make sure at least one mode is selected - if (modeCount == 0) { - AFB_ERROR("ACTION-LOAD-ONE No Action Selected lua|callback|(api+verb) in %s", json_object_get_string(actionJ)); - goto OnErrorExit; - } - - if (modeCount > 1) { - AFB_ERROR("ACTION-LOAD-ONE:ToMany arguments lua|callback|(api+verb) in %s", json_object_get_string(actionJ)); - goto OnErrorExit; - } - return 0; - -OnErrorExit: - return 1; -}; - -CtlActionT *ActionLoad(json_object *actionsJ) { - int err = 0; - CtlActionT *actions; - - // action array is close with a nullvalue; - if (json_object_get_type(actionsJ) == json_type_array) { - int count = json_object_array_length(actionsJ); - actions = calloc(count + 1, sizeof (CtlActionT)); - - for (int idx = 0; idx < count; idx++) { - json_object *actionJ = json_object_array_get_idx(actionsJ, idx); - err = ActionLoadOne(&actions[idx], actionJ); - if (err) goto OnErrorExit; - } - - } else { - actions = calloc(2, sizeof (CtlActionT)); - err = ActionLoadOne(&actions[0], actionsJ); - if (err) goto OnErrorExit; - } - - return actions; - -OnErrorExit: - return NULL; - -} diff --git a/controller/ctl-config.c b/controller/ctl-config.c deleted file mode 100644 index cf24057..0000000 --- a/controller/ctl-config.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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, something express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Reference: - * Json load using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <string.h> - -#include "filescan-utils.h" -#include "ctl-config.h" - -// Load control config file - -char* CtlConfigSearch(const char *dirList, const char* fileName) { - int index; - char controlFile [CONTROL_MAXPATH_LEN]; - - if(fileName) { - strncpy(controlFile, fileName, CONTROL_MAXPATH_LEN); - } else { - strncpy(controlFile, CONTROL_CONFIG_PRE "-", CONTROL_MAXPATH_LEN); - strncat(controlFile, GetBinderName(), strlen(GetBinderName())); // Only possible because returned GetBinderName value is a static variable. - } - - // search for default dispatch config file - json_object* responseJ = ScanForConfig(dirList, CTL_SCAN_RECURSIVE, controlFile, ".json"); - - // We load 1st file others are just warnings - for (index = 0; index < json_object_array_length(responseJ); index++) { - json_object *entryJ = json_object_array_get_idx(responseJ, index); - - char *filename; - char*fullpath; - int err = wrap_json_unpack(entryJ, "{s:s, s:s !}", "fullpath", &fullpath, "filename", &filename); - if (err) { - AFB_ERROR("CTL-INIT HOOPs invalid JSON entry= %s", json_object_get_string(entryJ)); - return NULL; - } - - if (index == 0) { - if (strcasestr(filename, controlFile)) { - char filepath[CONTROL_MAXPATH_LEN]; - strncpy(filepath, fullpath, strlen(fullpath)); - strncat(filepath, "/", strlen("/")); - strncat(filepath, filename, strlen(filename)); - return (strdup(filepath)); - } - } - } - - // no config found - return NULL; -} - -json_object* loadJSON(const char* filepath, const char* fileName) -{ - // Search for config in filepath - const char* filepathFound = CtlConfigSearch(filepath, fileName); - if(!filepathFound) - { - AFB_ERROR("CTL-LOAD-CONFIG No JSON Config found in %s", filepath); - return NULL; - } - return json_object_from_file(filepathFound); -} - -int browseAdditionnalFiles(CtlConfigT* ctlConfig, const char* filepath, int sectionIdx){ - int err = 0; - int done = 0; - const char* fileName; - json_object* configJ = NULL, *sectionJ = NULL; - CtlSectionT* sections = ctlConfig->sections; - - if (json_object_get_type(ctlConfig->filesJ) == json_type_array) { - int filesEnd = json_object_array_length(ctlConfig->filesJ); - for (int jdx = 0; jdx < filesEnd; jdx++) { - fileName = json_object_get_string(json_object_array_get_idx(ctlConfig->filesJ, jdx)); - configJ = loadJSON(filepath, fileName); - if(json_object_object_get_ex(configJ, sections[sectionIdx].key, §ionJ)) - { - err += sections[sectionIdx].loadCB(§ions[sectionIdx], sectionJ); - done++; - } - } - if(!done) { - AFB_ERROR("CtlConfigLoad: fail to find '%s' section in config '%s' with '%s' in its name", sections[sectionIdx].key, filepath, fileName); - err++; - } - if(err) {goto OnErrorExit;} - } else { - fileName = json_object_get_string(ctlConfig->filesJ); - configJ = loadJSON(filepath, fileName); - if(json_object_object_get_ex(configJ, sections[sectionIdx].key, §ionJ)) { - err += sections[sectionIdx].loadCB(§ions[sectionIdx], sectionJ); - done++; - } - else { - AFB_ERROR("CtlConfigLoad: fail to find '%s' section in config '%s' with '%s' in its name", sections[sectionIdx].key, filepath, fileName); - err++; - } - if(err) {goto OnErrorExit;} - } - - return err; - - OnErrorExit: - return err; -} - -int CtlConfigExec(CtlConfigT *ctlConfig) { - // best effort to initialise everything before starting - if (ctlConfig->requireJ) { - - void DispatchRequireOneApi(json_object * bindindJ) { - const char* requireBinding = json_object_get_string(bindindJ); - int err = afb_daemon_require_api(requireBinding, 1); - if (err) { - AFB_WARNING("CTL-LOAD-CONFIG:REQUIRE Fail to get=%s", requireBinding); - } - } - - if (json_object_get_type(ctlConfig->requireJ) == json_type_array) { - for (int idx = 0; idx < json_object_array_length(ctlConfig->requireJ); idx++) { - DispatchRequireOneApi(json_object_array_get_idx(ctlConfig->requireJ, idx)); - } - } else { - DispatchRequireOneApi(ctlConfig->requireJ); - } - } - -#ifdef CONTROL_SUPPORT_LUA - int err= LuaConfigExec(); - if (err) goto OnErrorExit; -#endif - - // Loop on every section and process config - int errcount=0; - for (int idx = 0; ctlConfig->sections[idx].key != NULL; idx++) { - errcount += ctlConfig->sections[idx].loadCB(&ctlConfig->sections[idx], NULL); - } - return errcount; - - OnErrorExit: - return 1; -} - -CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections) { - json_object *ctlConfigJ; - CtlConfigT *ctlConfig = calloc(1, sizeof (CtlConfigT)); - int err; - -#ifdef CONTROL_SUPPORT_LUA - err = LuaConfigLoad(); - if (err) goto OnErrorExit; -#endif - - // Load JSON file - ctlConfigJ = loadJSON(filepath, NULL); - if (!ctlConfigJ) { - AFB_ERROR("CTL-LOAD-CONFIG Invalid JSON %s ", filepath); - goto OnErrorExit; - } - - AFB_INFO("CTL-LOAD-CONFIG: loading config filepath=%s", filepath); - - json_object *metadataJ; - int done = json_object_object_get_ex(ctlConfigJ, "metadata", &metadataJ); - if (done) { - err = wrap_json_unpack(metadataJ, "{ss,ss,ss,s?s,s?o,s?o !}", - "label", &ctlConfig->label, - "version", &ctlConfig->version, - "api", &ctlConfig->api, - "info", &ctlConfig->info, - "require", &ctlConfig->requireJ, - "files",&ctlConfig->filesJ); - if (err) { - AFB_ERROR("CTL-LOAD-CONFIG:METADATA Missing something label|api|version|[info]|[require] in:\n-- %s", json_object_get_string(metadataJ)); - goto OnErrorExit; - } - - // Should replace this with API name change - if (ctlConfig->api) { - err = afb_daemon_rename_api(ctlConfig->api); - if (err) AFB_WARNING("Fail to rename api to:%s", ctlConfig->api); - } - } - - //load config sections - err = 0; - ctlConfig->sections = sections; - - for (int idx = 0; sections[idx].key != NULL; idx++) { - json_object * sectionJ = NULL; - int done = json_object_object_get_ex(ctlConfigJ, sections[idx].key, §ionJ); - if (!done) { - AFB_DEBUG("CtlConfigLoad: fail to find '%s' section in config '%s'. Searching deeper", sections[idx].key, filepath); - err += browseAdditionnalFiles(ctlConfig, filepath, idx); - } else { - err += sections[idx].loadCB(§ions[idx], sectionJ); - } - } - if (err) goto OnErrorExit; - - return (ctlConfig); - -OnErrorExit: - free(ctlConfig); - return NULL; -} diff --git a/controller/ctl-config.h b/controller/ctl-config.h deleted file mode 100644 index 25a066c..0000000 --- a/controller/ctl-config.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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, something express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Reference: - * Json load using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values - */ - -#ifndef _CTL_CONFIG_INCLUDE_ -#define _CTL_CONFIG_INCLUDE_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#define AFB_BINDING_VERSION 2 -#include <afb/afb-binding.h> -#include <json-c/json.h> -#include <filescan-utils.h> -#include <wrap-json.h> - -#include "ctl-plugin.h" - -#ifndef CONTROL_MAXPATH_LEN - #define CONTROL_MAXPATH_LEN 255 -#endif - -#ifndef CONTROL_CONFIG_PRE - #define CONTROL_CONFIG_PRE "init" -#endif - -#ifndef CTL_PLUGIN_EXT - #define CTL_PLUGIN_EXT ".ctlso" -#endif - -typedef enum { - CTL_TYPE_NONE=0, - CTL_TYPE_API, - CTL_TYPE_CB, - CTL_TYPE_LUA, -} CtlActionTypeT; - -typedef struct { - CtlActionTypeT type; - const char* api; - const char* call; - json_object *argsJ; - int (*actionCB)(CtlSourceT *source, json_object *argsJ, json_object *queryJ); - CtlSourceT source; -} CtlActionT; - -typedef struct { - const char* label; - const char *info; - CtlActionT *actions; -} DispatchHandleT; - -typedef struct ConfigSectionS { - const char *key; - const char *label; - const char *info; - int (*loadCB)(struct ConfigSectionS *section, json_object *sectionJ); - void *handle; -} CtlSectionT; - -typedef struct { - const char* api; - const char* label; - const char *info; - const char *version; - json_object *requireJ; - json_object *filesJ; - CtlSectionT *sections; -} CtlConfigT; - -#ifdef CONTROL_SUPPORT_LUA - #include "ctl-lua.h" -#else - typedef struct lua_State lua_State; - typedef void *Lua2cFunctionT; - typedef void* Lua2cWrapperT; -#endif - -// ctl-action.c -CtlActionT *ActionLoad(json_object *actionsJ); -int ActionExecOne(CtlActionT* action, json_object *queryJ); -int ActionLoadOne(CtlActionT *action, json_object *actionJ); - -// ctl-config.c -CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections); -int CtlConfigExec(CtlConfigT *ctlConfig); - -// ctl-onload.c -int OnloadConfig(CtlSectionT *section, json_object *actionsJ); - -// ctl-plugin.c -int PluginConfig(CtlSectionT *section, json_object *pluginsJ); -int PluginGetCB (CtlActionT *action , json_object *callbackJ); - -#ifdef __cplusplus -} -#endif - -#endif /* _CTL_CONFIG_INCLUDE_ */ diff --git a/controller/ctl-lua.c b/controller/ctl-lua.c deleted file mode 100644 index 76faed6..0000000 --- a/controller/ctl-lua.c +++ /dev/null @@ -1,1080 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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: - * (manual) https://www.lua.org/manual/5.3/manual.html - * (lua->C) http://www.troubleshooters.com/codecorn/lua/lua_c_calls_lua.htm#_Anatomy_of_a_Lua_Call - * (lua/C Var) http://acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/ - * (Lua/C Lib)https://john.nachtimwald.com/2014/07/12/wrapping-a-c-library-in-lua/ - * (Lua/C Table) https://gist.github.com/SONIC3D/10388137 - * (Lua/C Nested table) https://stackoverflow.com/questions/45699144/lua-nested-table-from-lua-to-c - * (Lua/C Wrapper) https://stackoverflow.com/questions/45699950/lua-passing-handle-to-function-created-with-newlib - * - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <string.h> - -#include "ctl-config.h" - -#define LUA_FIST_ARG 2 // when using luaL_newlib calllback receive libtable as 1st arg -#define LUA_MSG_MAX_LENGTH 512 -#define JSON_ERROR (json_object*)-1 -static afb_req NULL_AFBREQ = {}; - - -static lua_State* luaState; - -#define CTX_MAGIC 123456789 -#define CTX_TOKEN "AFB_ctx" - -typedef struct { - char *name; - int count; - afb_event event; -} LuaAfbEvent; -static LuaAfbEvent *luaDefaultEvt; - -typedef struct { - int ctxMagic; - afb_req request; - void *handle; - char *info; -} LuaAfbContextT; - -typedef struct { - const char *callback; - json_object *context; - void *handle; -} LuaCallServiceT; - -typedef enum { - AFB_MSG_INFO, - AFB_MSG_WARNING, - AFB_MSG_NOTICE, - AFB_MSG_DEBUG, - AFB_MSG_ERROR, -} LuaAfbMessageT; - -/* - * Note(Fulup): I fail to use luaL_setmetatable and replaced it with a simple opaque - * handle while waiting for someone smarter than me to find a better solution - * https://stackoverflow.com/questions/45596493/lua-using-lua-newuserdata-from-lua-pcall - */ - -STATIC LuaAfbContextT *LuaCtxCheck (lua_State *luaState, int index) { - LuaAfbContextT *afbContext; - //luaL_checktype(luaState, index, LUA_TUSERDATA); - //afbContext = (LuaAfbContextT *)luaL_checkudata(luaState, index, CTX_TOKEN); - luaL_checktype(luaState, index, LUA_TLIGHTUSERDATA); - afbContext = (LuaAfbContextT *) lua_touserdata(luaState, index); - if (afbContext == NULL && afbContext->ctxMagic != CTX_MAGIC) { - luaL_error(luaState, "Fail to retrieve user data context=%s", CTX_TOKEN); - AFB_ERROR ("afbContextCheck error retrieving afbContext"); - return NULL; - } - return afbContext; -} - -STATIC LuaAfbContextT *LuaCtxPush (lua_State *luaState, afb_req request, void *handle, const char* info) { - // LuaAfbContextT *afbContext = (LuaAfbContextT *)lua_newuserdata(luaState, sizeof(LuaAfbContextT)); - // luaL_setmetatable(luaState, CTX_TOKEN); - LuaAfbContextT *afbContext = (LuaAfbContextT *)calloc(1, sizeof(LuaAfbContextT)); - lua_pushlightuserdata(luaState, afbContext); - if (!afbContext) { - AFB_ERROR ("LuaCtxPush fail to allocate user data context"); - return NULL; - } - afbContext->ctxMagic=CTX_MAGIC; - afbContext->info=strdup(info); - afbContext->request= request; - afbContext->handle= handle; - return afbContext; -} - -STATIC void LuaCtxFree (LuaAfbContextT *afbContext) { - free(afbContext->info); - free(afbContext); -} - -// Push a json structure on the stack as a LUA table -STATIC int LuaPushArgument (json_object *argsJ) { - - //AFB_NOTICE("LuaPushArgument argsJ=%s", json_object_get_string(argsJ)); - - json_type jtype= json_object_get_type(argsJ); - switch (jtype) { - case json_type_object: { - lua_newtable (luaState); - json_object_object_foreach (argsJ, key, val) { - int done = LuaPushArgument (val); - if (done) { - lua_setfield(luaState,-2, key); - } - } - break; - } - case json_type_array: { - int length= json_object_array_length(argsJ); - lua_newtable (luaState); - for (int idx=0; idx < length; idx ++) { - json_object *val=json_object_array_get_idx(argsJ, idx); - LuaPushArgument (val); - lua_seti (luaState,-2, idx); - } - break; - } - case json_type_int: - lua_pushinteger(luaState, json_object_get_int(argsJ)); - break; - case json_type_string: - lua_pushstring(luaState, json_object_get_string(argsJ)); - break; - case json_type_boolean: - lua_pushboolean(luaState, json_object_get_boolean(argsJ)); - break; - case json_type_double: - lua_pushnumber(luaState, json_object_get_double(argsJ)); - break; - case json_type_null: - AFB_WARNING("LuaPushArgument: NULL object type %s", json_object_get_string(argsJ)); - return 0; - break; - - default: - AFB_ERROR("LuaPushArgument: unsupported Json object type %s", json_object_get_string(argsJ)); - return 0; - } - return 1; -} - -STATIC json_object *LuaPopOneArg (lua_State* luaState, int idx); - -// Move a table from Internal Lua representation to Json one -// Numeric table are transformed in json array, string one in object -// Mix numeric/string key are not supported -STATIC json_object *LuaTableToJson (lua_State* luaState, int index) { - #define LUA_KEY_INDEX -2 - #define LUA_VALUE_INDEX -1 - - int idx; - int tableType; - json_object *tableJ= NULL; - - lua_pushnil(luaState); // 1st key - if (index < 0) index--; - for (idx=1; lua_next(luaState, index) != 0; idx++) { - - // uses 'key' (at index -2) and 'value' (at index -1) - if (lua_type(luaState,LUA_KEY_INDEX) == LUA_TSTRING) { - - if (!tableJ) { - tableJ= json_object_new_object(); - tableType=LUA_TSTRING; - } else if (tableType != LUA_TSTRING){ - AFB_ERROR("MIX Lua Table with key string/numeric not supported"); - return NULL; - } - - const char *key= lua_tostring(luaState, LUA_KEY_INDEX); - json_object *argJ= LuaPopOneArg(luaState, LUA_VALUE_INDEX); - json_object_object_add(tableJ, key, argJ); - - } else { - if (!tableJ) { - tableJ= json_object_new_array(); - tableType=LUA_TNUMBER; - } else if(tableType != LUA_TNUMBER) { - AFB_ERROR("MIX Lua Table with key numeric/string not supported"); - return NULL; - } - - json_object *argJ= LuaPopOneArg(luaState, LUA_VALUE_INDEX); - json_object_array_add(tableJ, argJ); - } - - - lua_pop(luaState, 1); // removes 'value'; keeps 'key' for next iteration - } - - // Query is empty free empty json object - if (idx == 1) { - json_object_put(tableJ); - return NULL; - } - return tableJ; -} - -STATIC json_object *LuaPopOneArg (lua_State* luaState, int idx) { - json_object *value=NULL; - - int luaType = lua_type(luaState, idx); - switch(luaType) { - case LUA_TNUMBER: { - lua_Number number= lua_tonumber(luaState, idx);; - int nombre = (int)number; // evil trick to determine wether n fits in an integer. (stolen from ltcl.c) - if (number == nombre) { - value= json_object_new_int((int)number); - } else { - value= json_object_new_double(number); - } - break; - } - case LUA_TBOOLEAN: - value= json_object_new_boolean(lua_toboolean(luaState, idx)); - break; - case LUA_TSTRING: - value= json_object_new_string(lua_tostring(luaState, idx)); - break; - case LUA_TTABLE: - value= LuaTableToJson(luaState, idx); - break; - case LUA_TNIL: - value=json_object_new_string("nil") ; - break; - case LUA_TUSERDATA: - value=json_object_new_int64((int64_t)lua_touserdata(luaState, idx)); // store userdata as int !!! - break; - - default: - AFB_NOTICE ("LuaPopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType)); - value=NULL; - } - - return value; -} - -static json_object *LuaPopArgs (lua_State* luaState, int start) { - json_object *responseJ; - - int stop = lua_gettop(luaState); - if(stop-start <0) return NULL; - - // start at 2 because we are using a function array lib - if (start == stop) { - responseJ=LuaPopOneArg (luaState, start); - } else { - // loop on remaining return arguments - responseJ= json_object_new_array(); - for (int idx=start; idx <= stop; idx++) { - json_object *argJ=LuaPopOneArg (luaState, idx); - if (!argJ) goto OnErrorExit; - json_object_array_add(responseJ, argJ); - } - } - - return responseJ; - - OnErrorExit: - return NULL; -} - -STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) { - char *message; - - json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG); - - if (!responseJ) { - luaL_error(luaState,"LuaFormatMessage empty message"); - goto OnErrorExit; - } - - // if we have only on argument just return the value. - if (json_object_get_type(responseJ)!=json_type_array || json_object_array_length(responseJ) <2) { - message= (char*)json_object_get_string(responseJ); - goto PrintMessage; - } - - // extract format and push all other parameter on the stack - message = alloca (LUA_MSG_MAX_LENGTH); - const char *format = json_object_get_string(json_object_array_get_idx(responseJ, 0)); - - int arrayIdx=1; - int targetIdx=0; - - for (int idx=0; format[idx] !='\0'; idx++) { - - if (format[idx]=='%' && format[idx] !='\0') { - json_object *slotJ= json_object_array_get_idx(responseJ, arrayIdx); - //if (slotJ) AFB_NOTICE("**** idx=%d slotJ=%s", arrayIdx, json_object_get_string(slotJ)); - - - switch (format[++idx]) { - case 'd': - if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%d", json_object_get_int(slotJ)); - else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"nil"); - arrayIdx++; - break; - case 'f': - if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%f", json_object_get_double(slotJ)); - else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"nil"); - arrayIdx++; - break; - - case'%': - message[targetIdx]='%'; - targetIdx++; - break; - - case 's': - default: - if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%s", json_object_get_string(slotJ)); - else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"nil"); - arrayIdx++; - } - - } else { - if (targetIdx >= LUA_MSG_MAX_LENGTH) { - AFB_WARNING ("LuaFormatMessage: message[%s] owerverflow LUA_MSG_MAX_LENGTH=%d", format, LUA_MSG_MAX_LENGTH); - targetIdx --; // move backward for EOL - break; - } else { - message[targetIdx++] = format[idx]; - } - } - } - message[targetIdx]='\0'; - -PrintMessage: - switch (action) { - case AFB_MSG_WARNING: - AFB_WARNING ("%s", message); - break; - case AFB_MSG_NOTICE: - AFB_NOTICE ("%s", message); - break; - case AFB_MSG_DEBUG: - AFB_DEBUG ("%s", message); - break; - case AFB_MSG_INFO: - AFB_INFO ("%s", message); - break; - case AFB_MSG_ERROR: - default: - AFB_ERROR ("%s", message); - } - return 0; // nothing return to lua - - OnErrorExit: // on argument to return (the error message) - return 1; -} - -STATIC int LuaPrintInfo(lua_State* luaState) { - int err=LuaFormatMessage (luaState, AFB_MSG_INFO); - return err; -} - -STATIC int LuaPrintError(lua_State* luaState) { - int err=LuaFormatMessage (luaState, AFB_MSG_ERROR); - return err; // no value return -} - -STATIC int LuaPrintWarning(lua_State* luaState) { - int err=LuaFormatMessage (luaState, AFB_MSG_WARNING); - return err; -} - -STATIC int LuaPrintNotice(lua_State* luaState) { - int err=LuaFormatMessage (luaState, AFB_MSG_NOTICE); - return err; -} - -STATIC int LuaPrintDebug(lua_State* luaState) { - int err=LuaFormatMessage (luaState, AFB_MSG_DEBUG); - return err; -} - -STATIC int LuaAfbSuccess(lua_State* luaState) { - LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG); - if (!afbContext) goto OnErrorExit; - - // ignore context argument - json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1); - if (responseJ == JSON_ERROR) return 1; - - afb_req_success(afbContext->request, responseJ, NULL); - - LuaCtxFree(afbContext); - return 0; - - OnErrorExit: - lua_error(luaState); - return 1; -} - -STATIC int LuaAfbFail(lua_State* luaState) { - LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG); - if (!afbContext) goto OnErrorExit; - - json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1); - if (responseJ == JSON_ERROR) return 1; - - afb_req_fail(afbContext->request, afbContext->info, json_object_get_string(responseJ)); - - LuaCtxFree(afbContext); - return 0; - - OnErrorExit: - lua_error(luaState); - return 1; -} - -STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ) { - LuaCallServiceT *contextCB= (LuaCallServiceT*)handle; - int count=1; - - lua_getglobal(luaState, contextCB->callback); - - // push error status & response - lua_pushboolean(luaState, iserror); - count+= LuaPushArgument(responseJ); - count+= LuaPushArgument(contextCB->context); - - int err=lua_pcall(luaState, count, LUA_MULTRET, 0); - if (err) { - AFB_ERROR ("LUA-SERICE-CB:FAIL response=%s err=%s", json_object_get_string(responseJ), lua_tostring(luaState,-1) ); - } - - free (contextCB); -} - - -STATIC int LuaAfbService(lua_State* luaState) { - int count = lua_gettop(luaState); - - // note: argument start at 2 because of AFB: table - if (count <5 || !lua_isstring(luaState, 2) || !lua_isstring(luaState, 3) || !lua_istable(luaState, 4) || !lua_isstring(luaState, 5)) { - lua_pushliteral (luaState, "ERROR: syntax AFB:service(api, verb, {[Lua Table]})"); - goto OnErrorExit; - } - - // get api/verb+query - const char *api = lua_tostring(luaState,2); - const char *verb= lua_tostring(luaState,3); - json_object *queryJ= LuaTableToJson(luaState, 4); - if (queryJ == JSON_ERROR) return 1; - - LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT)); - contextCB->callback= lua_tostring(luaState, 5); - contextCB->context = LuaPopArgs(luaState, 6); - - afb_service_call(api, verb, queryJ, LuaAfbServiceCB, contextCB); - - return 0; // no value return - - OnErrorExit: - lua_error(luaState); - return 1; -} - -STATIC int LuaAfbServiceSync(lua_State* luaState) { - int count = lua_gettop(luaState); - json_object *responseJ; - - // note: argument start at 2 because of AFB: table - if (count <3 || !lua_isstring(luaState, 2) || !lua_isstring(luaState, 3) || !lua_istable(luaState, 4)) { - lua_pushliteral (luaState, "ERROR: syntax AFB:servsync(api, verb, {[Lua Table]})"); - goto OnErrorExit; - } - - // get api/verb+query - const char *api = lua_tostring(luaState,2); - const char *verb= lua_tostring(luaState,3); - json_object *queryJ= LuaTableToJson(luaState, 4); - - int iserror=afb_service_call_sync (api, verb, queryJ, &responseJ); - - // push error status & response - count=1; lua_pushboolean(luaState, iserror); - count+= LuaPushArgument(responseJ); - - return count; // return count values - - OnErrorExit: - lua_error(luaState); - return 1; -} - -STATIC int LuaAfbEventPush(lua_State* luaState) { - LuaAfbEvent *afbevt; - int index; - - // if no private event handle then use default binding event - if (lua_islightuserdata(luaState, LUA_FIST_ARG)) { - afbevt = (LuaAfbEvent*) lua_touserdata(luaState, LUA_FIST_ARG); - index=LUA_FIST_ARG+1; - } else { - index=LUA_FIST_ARG; - afbevt=luaDefaultEvt; - } - - if (!afb_event_is_valid(afbevt->event)) { - lua_pushliteral (luaState, "LuaAfbMakePush-Fail invalid event"); - goto OnErrorExit; - } - - json_object *ctlEventJ= LuaTableToJson(luaState, index); - if (!ctlEventJ) { - lua_pushliteral (luaState, "LuaAfbEventPush-Syntax is AFB:signal ([evtHandle], {lua table})"); - goto OnErrorExit; - } - - int done = afb_event_push(afbevt->event, ctlEventJ); - if (!done) { - lua_pushliteral (luaState, "LuaAfbEventPush-Fail No Subscriber to event"); - AFB_ERROR ("LuaAfbEventPush-Fail name subscriber event=%s count=%d", afbevt->name, afbevt->count); - goto OnErrorExit; - } - afbevt->count++; - return 0; - - OnErrorExit: - lua_error(luaState); - return 1; -} - -STATIC int LuaAfbEventSubscribe(lua_State* luaState) { - LuaAfbEvent *afbevt; - - LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG); - if (!afbContext) { - lua_pushliteral (luaState, "LuaAfbEventSubscribe-Fail Invalid request handle"); - goto OnErrorExit; - } - - // if no private event handle then use default binding event - if (lua_islightuserdata(luaState, LUA_FIST_ARG+1)) { - afbevt = (LuaAfbEvent*) lua_touserdata(luaState, LUA_FIST_ARG+1); - } else { - afbevt=luaDefaultEvt; - } - - if (!afb_event_is_valid(afbevt->event)) { - lua_pushliteral (luaState, "LuaAfbMakePush-Fail invalid event handle"); - goto OnErrorExit; - } - - int err = afb_req_subscribe(afbContext->request, afbevt->event); - if (err) { - lua_pushliteral (luaState, "LuaAfbEventSubscribe-Fail No Subscriber to event"); - AFB_ERROR ("LuaAfbEventPush-Fail name subscriber event=%s count=%d", afbevt->name, afbevt->count); - goto OnErrorExit; - } - afbevt->count++; - return 0; - - OnErrorExit: - lua_error(luaState); - return 1; -} - -STATIC int LuaAfbEventMake(lua_State* luaState) { - int count = lua_gettop(luaState); - LuaAfbEvent *afbevt=calloc(1,sizeof(LuaAfbEvent)); - - if (count != LUA_FIST_ARG || !lua_isstring(luaState, LUA_FIST_ARG)) { - lua_pushliteral (luaState, "LuaAfbEventMake-Syntax is evtHandle= AFB:event ('myEventName')"); - goto OnErrorExit; - } - - // event name should be the only argument - afbevt->name= strdup (lua_tostring(luaState,LUA_FIST_ARG)); - - // create a new binder event - afbevt->event = afb_daemon_make_event(afbevt->name); - if (!afb_event_is_valid(afbevt->event)) { - lua_pushliteral (luaState, "LuaAfbEventMake-Fail to Create Binder event"); - goto OnErrorExit; - } - - // push event handler as a LUA opaque handle - lua_pushlightuserdata(luaState, afbevt); - return 1; - - OnErrorExit: - lua_error(luaState); - return 1; -} - -// Function call from LUA when lua2c plugin L2C is used -int Lua2cWrapper(lua_State* luaState, const char *funcname, Lua2cFunctionT callback) { - - json_object *argsJ = LuaPopArgs(luaState, LUA_FIST_ARG); - int response = (*callback) (funcname, argsJ); - - // push response to LUA - lua_pushinteger(luaState, response); - - return 1; -} - -// Call a Lua function from a control action -int LuaCallFunc (CtlActionT *action, json_object *queryJ) { - - int err, count; - - json_object* argsJ = action->argsJ; - const char* func = action->call; - - // load function (should exist in CONTROL_PATH_LUA - lua_getglobal(luaState, func); - - // push source on the stack - count=1; - lua_pushstring(luaState, action->source.label); - - // push argsJ on the stack - if (!argsJ) { - lua_pushnil(luaState); - count++; - } else { - count+= LuaPushArgument (argsJ); - } - - // push queryJ on the stack - if (!queryJ) { - lua_pushnil(luaState); - count++; - } else { - count+= LuaPushArgument (queryJ); - } - - // effectively exec LUA script code - err=lua_pcall(luaState, count, 1, 0); - if (err) { - AFB_ERROR("LuaCallFunc Fail calling %s error=%s", func, lua_tostring(luaState,-1)); - goto OnErrorExit; - } - - // return LUA script value - int rc= (int)lua_tointeger(luaState, -1); - return rc; - - OnErrorExit: - return -1; -} - - -// Execute LUA code from received API request -STATIC 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; - } - // Push AFB client context on the stack - LuaAfbContextT *afbContext= LuaCtxPush(luaState, request,NULL,script); - if (!afbContext) goto OnErrorExit; - - break; - } - - case LUA_DOCALL: { - const char *func; - json_object *argsJ=NULL; - - err= wrap_json_unpack (queryJ, "{s:s, s?o !}", "target", &func, "args", &argsJ); - if (err) { - AFB_ERROR ("LUA-DOCALL-SYNTAX missing target|args query=%s", json_object_get_string(queryJ)); - goto OnErrorExit; - } - - // load function (should exist in CONTROL_PATH_LUA - lua_getglobal(luaState, func); - - // Push AFB client context on the stack - LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, NULL, func); - if (!afbContext) goto OnErrorExit; - - // push query on the stack - if (!argsJ) { - lua_pushnil(luaState); - count++; - } else { - count+= LuaPushArgument (argsJ); - } - - break; - } - - case LUA_DOSCRIPT: { // Fulup need to fix argument passing - char *filename; char*fullpath; - char luaScriptPath[CONTROL_MAXPATH_LEN]; - int index; - - // scan luascript search path once - static json_object *luaScriptPathJ =NULL; - - // extract value from query - const char *target=NULL,*func=NULL; - json_object *argsJ=NULL; - err= wrap_json_unpack (queryJ, "{s:s,s?s,s?s,s?o !}","target", &target,"path",&luaScriptPathJ,"function",&func,"args",&argsJ); - if (err) { - AFB_ERROR ("LUA-DOSCRIPT-SYNTAX:missing target|[path]|[function]|[args] query=%s", json_object_get_string(queryJ)); - goto OnErrorExit; - } - - // search for filename=script in binding data dir - if (!luaScriptPathJ) { - const char* dirList = strncat(GetBindingDirPath(), "/data", sizeof(GetBindingDirPath()) - strlen(GetBindingDirPath()) - 1); - strncpy(luaScriptPath,CONTROL_DOSCRIPT_PRE, sizeof(luaScriptPath)); - strncat(luaScriptPath,"-", strlen("-")); - strncat(luaScriptPath,target, strlen(target)); - luaScriptPathJ= ScanForConfig(dirList, CTL_SCAN_RECURSIVE,luaScriptPath,".lua"); - } - for (index=0; index < json_object_array_length(luaScriptPathJ); index++) { - json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index); - - err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename); - if (err) { - AFB_ERROR ("LUA-DOSCRIPT-SCAN:HOOPs invalid config file path = %s", json_object_get_string(entryJ)); - goto OnErrorExit; - } - - if (index > 0) AFB_WARNING("LUA-DOSCRIPT-SCAN:Ignore second script=%s path=%s", filename, fullpath); - else { - strncpy (luaScriptPath, fullpath, sizeof(luaScriptPath)); - strncat (luaScriptPath, "/", sizeof(luaScriptPath)); - strncat (luaScriptPath, filename, strlen(filename)); - } - } - - err= luaL_loadfile(luaState, luaScriptPath); - if (err) { - AFB_ERROR ("LUA-DOSCRIPT HOOPs Error in LUA loading scripts=%s err=%s", luaScriptPath, lua_tostring(luaState,-1)); - goto OnErrorExit; - } - - // script was loaded we need to parse to make it executable - err=lua_pcall(luaState, 0, 0, 0); - if (err) { - AFB_ERROR ("LUA-DOSCRIPT:FAIL to load %s", luaScriptPath); - goto OnErrorExit; - } - - // if no func name given try to deduct from filename - if (!func && (func=(char*)GetMidleName(filename))!=NULL) { - strncpy(luaScriptPath,"_", sizeof(luaScriptPath)); - strncat(luaScriptPath,func, strlen(func)); - func=luaScriptPath; - } - if (!func) { - AFB_ERROR ("LUA-DOSCRIPT:FAIL to deduct funcname from %s", filename); - goto OnErrorExit; - } - - // load function (should exist in CONTROL_PATH_LUA - lua_getglobal(luaState, func); - - // Push AFB client context on the stack - LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, NULL, func); - if (!afbContext) goto OnErrorExit; - - // push function arguments - if (!argsJ) { - lua_pushnil(luaState); - count++; - } else { - count+= LuaPushArgument(argsJ); - } - - break; - } - - default: - AFB_ERROR ("LUA-DOSCRIPT-ACTION unknown query=%s", json_object_get_string(queryJ)); - goto OnErrorExit; - } - - // effectively exec LUA code (afb_reply/fail done later from callback) - err=lua_pcall(luaState, count+1, 0, 0); - if (err) { - AFB_ERROR ("LUA-DO-EXEC:FAIL query=%s err=%s", json_object_get_string(queryJ), lua_tostring(luaState,-1)); - goto OnErrorExit; - } - return; - - OnErrorExit: - afb_req_fail(request,"LUA:ERROR", lua_tostring(luaState,-1)); - return; -} - -void ctlapi_execlua (afb_req request) { - LuaDoAction (LUA_DOSTRING, request); -} - -void ctlapi_request (afb_req request) { - LuaDoAction (LUA_DOCALL, request); -} - -void ctlapi_debuglua (afb_req request) { - LuaDoAction (LUA_DOSCRIPT, request); -} - -STATIC int LuaTimerClear (lua_State* luaState) { - - // Get Timer Handle - LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG); - if (!afbContext) goto OnErrorExit; - - // retrieve useful information opaque handle - TimerHandleT *timerHandle = (TimerHandleT*)afbContext->handle; - - AFB_NOTICE ("LuaTimerClear timer=%s", timerHandle->label); - TimerEvtStop(timerHandle); - - return 0; //happy end - -OnErrorExit: - return 1; -} -STATIC int LuaTimerGet (lua_State* luaState) { - - // Get Timer Handle - LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG); - if (!afbContext) goto OnErrorExit; - - // retrieve useful information opaque handle - TimerHandleT *timerHandle = (TimerHandleT*)afbContext->handle; - - // create response as a JSON object - json_object *responseJ= json_object_new_object(); - json_object_object_add(responseJ,"label", json_object_new_string(timerHandle->label)); - json_object_object_add(responseJ,"delay", json_object_new_int(timerHandle->delay)); - json_object_object_add(responseJ,"count", json_object_new_int(timerHandle->count)); - - // return JSON object as Lua table - int count=LuaPushArgument(responseJ); - - // free json object - json_object_put(responseJ); - - return count; // return argument - -OnErrorExit: - return 0; -} - -// Timer Callback - -// Set timer -STATIC int LuaTimerSetCB (void *handle) { - LuaCallServiceT *contextCB =(LuaCallServiceT*) handle; - TimerHandleT *timerHandle = (TimerHandleT*) contextCB->handle; - int count; - - // push timer handle and user context on Lua stack - lua_getglobal(luaState, contextCB->callback); - - // Push timer handle - LuaAfbContextT *afbContext= LuaCtxPush(luaState, NULL_AFBREQ, contextCB->handle, timerHandle->label); - if (!afbContext) goto OnErrorExit; - count=1; - - // Push user Context - count+= LuaPushArgument(contextCB->context); - - int err=lua_pcall(luaState, count, LUA_MULTRET, 0); - if (err) { - AFB_ERROR ("LUA-TIMER-CB:FAIL response=%s err=%s", json_object_get_string(contextCB->context), lua_tostring(luaState,-1)); - goto OnErrorExit; - } - - // get return parameter - if (!lua_isboolean(luaState, -1)) { - return (lua_toboolean(luaState, -1)); - } - - // timer last run free context resource - if (timerHandle->count == 1) { - LuaCtxFree(afbContext); - } - return 0; // By default we are happy - - OnErrorExit: - return 1; // stop timer -} - -STATIC int LuaTimerSet(lua_State* luaState) { - const char *label=NULL, *info=NULL; - int delay=0, count=0; - - json_object *timerJ = LuaPopOneArg(luaState, LUA_FIST_ARG); - const char *callback = lua_tostring(luaState, LUA_FIST_ARG + 1); - json_object *contextJ = LuaPopOneArg(luaState, LUA_FIST_ARG + 2); - - if (lua_gettop(luaState) != LUA_FIST_ARG+2 || !timerJ || !callback || !contextJ) { - lua_pushliteral(luaState, "LuaTimerSet-Syntax timerset (timerT, 'callback', contextT)"); - goto OnErrorExit; - } - - int err = wrap_json_unpack(timerJ, "{ss, s?s si, si !}", "label", &label, "info", &info, "delay", &delay, "count", &count); - if (err) { - lua_pushliteral(luaState, "LuaTimerSet-Syntax timerT={label:xxx delay:ms, count:xx}"); - goto OnErrorExit; - } - - // everything look fine create timer structure - TimerHandleT *timerHandle = malloc (sizeof (TimerHandleT)); - timerHandle->delay=delay; - timerHandle->count=count; - timerHandle->label=label; - - // Allocate handle to store context and callback - LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT)); - contextCB->callback= callback; - contextCB->context = contextJ; - contextCB->handle = timerHandle; - - // fire timer - TimerEvtStart (timerHandle, LuaTimerSetCB, contextCB); - - return 0; // Happy No Return Function - -OnErrorExit: - lua_error(luaState); - return 1; // return error code -} - -// Register a new L2c list of LUA user plugin commands -void LuaL2cNewLib(const char *label, luaL_Reg *l2cFunc, int count) { - // 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, label); -} - -static const luaL_Reg afbFunction[] = { - {"timerclear", LuaTimerClear}, - {"timerget" , LuaTimerGet}, - {"timerset" , LuaTimerSet}, - {"notice" , LuaPrintNotice}, - {"info" , LuaPrintInfo}, - {"warning" , LuaPrintWarning}, - {"debug" , LuaPrintDebug}, - {"error" , LuaPrintError}, - {"servsync" , LuaAfbServiceSync}, - {"service" , LuaAfbService}, - {"success" , LuaAfbSuccess}, - {"fail" , LuaAfbFail}, - {"subscribe" , LuaAfbEventSubscribe}, - {"evtmake" , LuaAfbEventMake}, - {"evtpush" , LuaAfbEventPush}, - - {NULL, NULL} /* sentinel */ -}; - -// Load Lua Interpreter -int LuaConfigLoad () { - // open a new LUA interpretor - luaState = luaL_newstate(); - if (!luaState) { - AFB_ERROR ("LUA_INIT: Fail to open lua interpretor"); - goto OnErrorExit; - } - - // load auxiliary libraries - luaL_openlibs(luaState); - - // redirect print to AFB_NOTICE - luaL_newlib(luaState, afbFunction); - lua_setglobal(luaState, "AFB"); - - return 0; - - OnErrorExit: - return 1; -} - -// Create Binding Event at Init Exec Time -int LuaConfigExec () { - - int err, index; - // create default lua event to send test pause/resume - luaDefaultEvt=calloc(1,sizeof(LuaAfbEvent)); - luaDefaultEvt->name=CONTROL_LUA_EVENT; - luaDefaultEvt->event = afb_daemon_make_event(CONTROL_LUA_EVENT); - if (!afb_event_is_valid(luaDefaultEvt->event)) { - AFB_ERROR ("POLCTL_INIT: Cannot register lua-events=%s ", CONTROL_LUA_EVENT); - goto OnErrorExit;; - } - - // search for default policy config file - char fullprefix[CONTROL_MAXPATH_LEN]; - strncpy (fullprefix, CONTROL_CONFIG_PRE "-", sizeof(fullprefix)); - strncat (fullprefix, GetBinderName(), sizeof(fullprefix)); - strncat (fullprefix, "-", sizeof(fullprefix)); - - const char *dirList = getenv("CONTROL_LUA_PATH"); - if (!dirList) dirList = strncat(GetBindingDirPath(), "/data", sizeof(GetBindingDirPath()) - strlen(GetBindingDirPath()) - 1); - - // 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 - 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_ERROR ("LUA-INIT HOOPs invalid config file path = %s", json_object_get_string(entryJ)); - goto OnErrorExit; - } - - char filepath[CONTROL_MAXPATH_LEN]; - strncpy(filepath, fullpath, sizeof(filepath)); - strncat(filepath, "/", sizeof(filepath)); - strncat(filepath, filename, strlen(filename)); - err= luaL_loadfile(luaState, filepath); - if (err) { - AFB_ERROR ("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_ERROR ("LUA-LOAD HOOPs Error in LUA exec scripts=%s err=%s", filepath, lua_tostring(luaState,-1)); - goto OnErrorExit; - } - } - - // no policy config found remove control API from binder - if (index == 0) { - AFB_WARNING ("POLICY-INIT:WARNING (setenv CONTROL_LUA_PATH) No LUA '%s*.lua' in '%s'", fullprefix, dirList); - } - - AFB_DEBUG("Control-LUA Init Done"); - return 0; - - OnErrorExit: - return 1; -} diff --git a/controller/ctl-lua.h b/controller/ctl-lua.h deleted file mode 100644 index 0b8de45..0000000 --- a/controller/ctl-lua.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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, something express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Reference: - * Json load using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values - */ - -#ifndef _LUA_CTL_INCLUDE_ -#define _LUA_CTL_INCLUDE_ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// prefix start debug script -#ifndef CONTROL_DOSCRIPT_PRE -#define CONTROL_DOSCRIPT_PRE "debug" -#endif - -// default event name used by LUA -#ifndef CONTROL_LUA_EVENT -#define CONTROL_LUA_EVENT "luaevt" -#endif - -#define AFB_BINDING_VERSION 2 -#include <afb/afb-binding.h> - -#include <json-c/json.h> - -#ifdef SUSE_LUA_INCDIR -#include <lua5.3/lua.h> -#include <lua5.3/lauxlib.h> -#include <lua5.3/lualib.h> -#else -#include <lua.h> -#include <lauxlib.h> -#include <lualib.h> -#endif - -#include "ctl-timer.h" -#include "ctl-config.h" - -int LuaLibInit (); - -typedef int (*Lua2cFunctionT)(const char *funcname, json_object *argsJ); -typedef int (*Lua2cWrapperT) (lua_State* luaState, const char *funcname, Lua2cFunctionT callback); - -#define CTLP_LUALOAD Lua2cWrapperT Lua2cWrap; -#define CTLP_LUA2C(FuncName, label, argsJ) static int FuncName(const char*label,json_object*argsJ);\ - int lua2c_ ## FuncName(lua_State* luaState){return((*Lua2cWrap)(luaState, MACRO_STR_VALUE(FuncName), FuncName));};\ - static int FuncName(const char* label, json_object* argsJ) - -typedef enum { - LUA_DOCALL, - LUA_DOSTRING, - LUA_DOSCRIPT, -} LuaDoActionT; - -int LuaConfigLoad(); -int LuaConfigExec(); -void LuaL2cNewLib(const char *label, luaL_Reg *l2cFunc, int count); -int Lua2cWrapper(lua_State* luaState, const char *funcname, Lua2cFunctionT callback); -int LuaCallFunc (CtlActionT *action, json_object *queryJ) ; -void ctlapi_lua_docall (afb_req request); -void ctlapi_lua_dostring (afb_req request); -void ctlapi_lua_doscript (afb_req request); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/controller/ctl-onload.c b/controller/ctl-onload.c deleted file mode 100644 index 5000542..0000000 --- a/controller/ctl-onload.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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, something express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <string.h> - -#include "ctl-config.h" - -// onload section receive one action or an array of actions -int OnloadConfig(CtlSectionT *section, json_object *actionsJ) { - CtlActionT *actions; - - // Load time parse actions in config file - if (actionsJ != NULL) { - actions= ActionLoad(actionsJ); - section->handle=actions; - - if (!actions) { - AFB_ERROR ("OnloadLoad config fail processing onload actions"); - goto OnErrorExit; - } - - } else { - // Exec time process onload action now - actions=(CtlActionT*)section->handle; - if (!actions) { - AFB_ERROR ("OnloadLoad Cannot Exec Non Existing Onload Action"); - goto OnErrorExit; - } - - for (int idx=0; actions[idx].source.label != NULL; idx ++) { - ActionExecOne(&actions[idx], NULL); - } - } - - return 0; - -OnErrorExit: - return 1; - -} diff --git a/controller/ctl-plugin.c b/controller/ctl-plugin.c deleted file mode 100644 index 62fdb8b..0000000 --- a/controller/ctl-plugin.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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, something express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Reference: - * Json load using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values - */ - -#define _GNU_SOURCE -#include <string.h> -#include <dlfcn.h> -#include <link.h> -#include <stdio.h> -#include <stdlib.h> - -#include "ctl-config.h" - -static CtlPluginT *ctlPlugins=NULL; - -int PluginGetCB (CtlActionT *action , json_object *callbackJ) { - const char *plugin=NULL, *function=NULL; - json_object *argsJ; - int idx; - - if (!ctlPlugins) { - AFB_ERROR ("PluginGetCB plugin section missing cannot call '%s'", json_object_get_string(callbackJ)); - goto OnErrorExit; - } - - int err = wrap_json_unpack(callbackJ, "{ss,ss,s?o!}", "plugin", &plugin, "function", &function, "args", &argsJ); - if (err) { - AFB_ERROR("PluginGet missing plugin|function|[args] in %s", json_object_get_string(callbackJ)); - goto OnErrorExit; - } - - for (idx=0; ctlPlugins[idx].label != NULL; idx++) { - if (!strcasecmp (ctlPlugins[idx].label, plugin)) break; - } - - if (!ctlPlugins[idx].label) { - AFB_ERROR ("PluginGetCB no plugin with label=%s", plugin); - goto OnErrorExit; - } - - action->actionCB = dlsym(ctlPlugins[idx].dlHandle, function); - action->source.context = ctlPlugins[idx].context; - - if (!action->actionCB) { - AFB_ERROR ("PluginGetCB no plugin=%s no function=%s", plugin, function); - goto OnErrorExit; - } - return 0; - -OnErrorExit: - return 1; -} - -// Wrapper to Lua2c plugin command add context and delegate to LuaWrapper -STATIC int DispatchOneL2c(lua_State* luaState, const char *funcname, Lua2cFunctionT callback) { -#ifndef CONTROL_SUPPORT_LUA - AFB_ERROR("CTL-ONE-L2C: LUA support not selected (cf:CONTROL_SUPPORT_LUA) in config.cmake"); - return 1; -#else - int err=Lua2cWrapper(luaState, funcname, callback); - return err; -#endif -} - -STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* handle) { - json_object *lua2csJ = NULL, *actionsJ = NULL; - const char *basename = NULL; - char *ldSearchPath = NULL; - void *dlHandle; - - // 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,ss,s?o,s?o!}", - "label", &ctlPlugin->label, - "version", &ctlPlugin->version, - "info", &ctlPlugin->info, - "ldpath", &ldSearchPath, - "basename", &basename, - "lua2c", &lua2csJ, - "actions", &actionsJ); - if (err) { - AFB_ERROR("CTL-PLUGIN-LOADONE Plugin missing label|basename|version|[info]|[ldpath]|[lua2c]|[actions] in:\n-- %s", json_object_get_string(pluginJ)); - goto OnErrorExit; - } - - // if search path not in Json config file, then try default binding dir - if (!ldSearchPath) ldSearchPath = getenv("CONTROL_PLUGIN_PATH"); - if (!ldSearchPath) { - ldSearchPath = strncat(GetBindingDirPath(), "/lib", sizeof(GetBindingDirPath()) - strlen(GetBindingDirPath()) - 1); - } - - // search for default policy config file - json_object *pluginPathJ = ScanForConfig(ldSearchPath, CTL_SCAN_RECURSIVE, basename, CTL_PLUGIN_EXT); - if (!pluginPathJ || json_object_array_length(pluginPathJ) == 0) { - AFB_ERROR("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_ERROR("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_WARNING("CTL-PLUGIN-LOADONE plugin multiple instances in searchpath will use %s/%s", fullpath, filename); - } - - char pluginpath[CONTROL_MAXPATH_LEN]; - strncpy(pluginpath, fullpath, strlen(fullpath)); - strncat(pluginpath, "/", strlen("/")); - strncat(pluginpath, filename, strlen(filename)); - dlHandle = dlopen(pluginpath, RTLD_NOW); - if (!dlHandle) { - AFB_ERROR("CTL-PLUGIN-LOADONE Fail to load pluginpath=%s err= %s", pluginpath, dlerror()); - goto OnErrorExit; - } - - CtlPluginMagicT *ctlPluginMagic = (CtlPluginMagicT*) dlsym(dlHandle, "CtlPluginMagic"); - if (!ctlPluginMagic || ctlPluginMagic->magic != CTL_PLUGIN_MAGIC) { - AFB_ERROR("CTL-PLUGIN-LOADONE symbol'CtlPluginMagic' missing or != CTL_PLUGIN_MAGIC plugin=%s", pluginpath); - goto OnErrorExit; - } else { - AFB_NOTICE("CTL-PLUGIN-LOADONE %s successfully registered", ctlPluginMagic->label); - } - - // store dlopen handle to enable onload action at exec time - ctlPlugin->dlHandle = dlHandle; - - // Push lua2cWrapper @ into plugin - Lua2cWrapperT *lua2cInPlug = dlsym(dlHandle, "Lua2cWrap"); -#ifndef CONTROL_SUPPORT_LUA - if (lua2cInPlug) *lua2cInPlug = NULL; -#else - // Lua2cWrapper is part of binder and not expose to dynamic link - if (lua2csJ && lua2cInPlug) { - *lua2cInPlug = DispatchOneL2c; - - int Lua2cAddOne(luaL_Reg *l2cFunc, const char* l2cName, int index) { - char funcName[CONTROL_MAXPATH_LEN]; - strncpy(funcName, "lua2c_", sizeof (funcName)); - strncat(funcName, l2cName, strlen(l2cName)); - - Lua2cFunctionT l2cFunction = (Lua2cFunctionT) dlsym(dlHandle, funcName); - if (!l2cFunction) { - AFB_ERROR("CTL-PLUGIN-LOADONE symbol'%s' missing err=%s", funcName, dlerror()); - return 1; - } - l2cFunc[index].func = (void*) l2cFunction; - l2cFunc[index].name = strdup(l2cName); - - return 0; - } - - int errCount = 0, count = 0; - luaL_Reg *l2cFunc = NULL; - - // look on l2c command and push them to LUA - if (json_object_get_type(lua2csJ) == json_type_array) { - int length = json_object_array_length(lua2csJ); - l2cFunc = calloc(length + 1, sizeof (luaL_Reg)); - for (count = 0; count < length; count++) { - int err; - const char *l2cName = json_object_get_string(json_object_array_get_idx(lua2csJ, count)); - err = Lua2cAddOne(l2cFunc, l2cName, count); - if (err) errCount++; - } - } else { - l2cFunc = calloc(2, sizeof (luaL_Reg)); - const char *l2cName = json_object_get_string(lua2csJ); - errCount = Lua2cAddOne(l2cFunc, l2cName, 0); - count = 1; - } - if (errCount) { - AFB_ERROR("CTL-PLUGIN-LOADONE %d symbols not found in plugin='%s'", errCount, pluginpath); - goto OnErrorExit; - } - else { - ctlPlugin->l2cFunc = l2cFunc; - ctlPlugin->l2cCount = count; - LuaL2cNewLib (ctlPlugin->label, - ctlPlugin->l2cFunc, - ctlPlugin->l2cCount); - } - } -#endif - -DispatchPluginInstallCbT ctlPluginOnload = dlsym(dlHandle, "CtlPluginOnload"); - if (ctlPluginOnload) { - ctlPlugin->context = (*ctlPluginOnload) (ctlPlugin, handle); - } - return 0; - -OnErrorExit: - return 1; -} - -int PluginConfig(CtlSectionT *section, json_object *pluginsJ) { - int err=0; - - if (ctlPlugins) - { - int idx = 0; - while(ctlPlugins[idx].label != NULL) - { - // Jose hack to make verbosity visible from sharedlib and - // be able to call verb from others api inside the binder - struct afb_binding_data_v2 *afbHidenData = dlsym(ctlPlugins[idx++].dlHandle, "afbBindingV2data"); - if (afbHidenData) *afbHidenData = afbBindingV2data; - } - return 0; - } - else - { - if (json_object_get_type(pluginsJ) == json_type_array) { - int length = json_object_array_length(pluginsJ); - ctlPlugins = calloc (length+1, sizeof(CtlPluginT)); - for (int idx=0; idx < length; idx++) { - json_object *pluginJ = json_object_array_get_idx(pluginsJ, idx); - err += PluginLoadOne(&ctlPlugins[idx], pluginJ, section->handle); - } - } else { - ctlPlugins = calloc (2, sizeof(CtlPluginT)); - err += PluginLoadOne(&ctlPlugins[0], pluginsJ, section->handle); - } - } - - return err; -} diff --git a/controller/ctl-plugin.h b/controller/ctl-plugin.h deleted file mode 100644 index 4b8bd26..0000000 --- a/controller/ctl-plugin.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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, something express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _CTL_PLUGIN_INCLUDE_ -#define _CTL_PLUGIN_INCLUDE_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include <json-c/json.h> - -#ifndef CTL_PLUGIN_MAGIC - #define CTL_PLUGIN_MAGIC 852369147 -#endif - -#ifndef STATIC - #define STATIC static -#endif - -#ifndef UNUSED_ARG - #define UNUSED_ARG(x) UNUSED_ ## x __attribute__((__unused__)) - #define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x -#endif - -typedef struct luaL_Reg luaL_Reg; - -typedef struct { - const char *label; - const char *info; - afb_req request; - void *context; -} CtlSourceT; - -typedef struct { - long magic; - const char *label; - void *handle; -} CtlPluginMagicT; - -typedef struct { - const char *label; - const char *info; - const char *version; - void *context; - void *dlHandle; -#ifdef CONTROL_SUPPORT_LUA - luaL_Reg *l2cFunc; - int l2cCount; -#endif -} CtlPluginT; - -typedef void*(*DispatchPluginInstallCbT)(CtlPluginT *plugin, void* handle); - -#define MACRO_STR_VALUE(arg) #arg -#define CTLP_REGISTER(pluglabel) CtlPluginMagicT CtlPluginMagic={.magic=CTL_PLUGIN_MAGIC,.label=pluglabel,.handle=NULL}; struct afb_binding_data_v2; -#define CTLP_ONLOAD(plugin, handle) void* CtlPluginOnload(CtlPluginT *plugin, void* handle) -#define CTLP_CAPI(funcname, source, argsJ, queryJ, context) int funcname(CtlSourceT *source, json_object* argsJ, json_object* queryJ, void* context) - -#ifdef __cplusplus -} -#endif - -#endif /* _CTL_PLUGIN_INCLUDE_ */ diff --git a/controller/ctl-timer.c b/controller/ctl-timer.c deleted file mode 100644 index 2d99472..0000000 --- a/controller/ctl-timer.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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. - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <string.h> -#include <time.h> - -#include "ctl-config.h" -#include "ctl-timer.h" - -#define DEFAULT_PAUSE_DELAY 3000 -#define DEFAULT_TEST_COUNT 1 -typedef struct { - int value; - const char *label; -} AutoTestCtxT; - -static afb_event afbevt; - -STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) { - TimerHandleT *timerHandle = (TimerHandleT*) handle; - int done; - uint64_t usec; - - // Rearm timer if needed - timerHandle->count --; - if (timerHandle->count == 0) { - sd_event_source_unref(source); - free (handle); - return 0; - } - else { - // otherwise validate timer for a new run - sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec); - sd_event_source_set_enabled(source, SD_EVENT_ONESHOT); - sd_event_source_set_time(source, usec + timerHandle->delay*1000); - } - - done= timerHandle->callback(timerHandle->context); - if (!done) goto OnErrorExit; - - return 0; - -OnErrorExit: - AFB_WARNING("TimerNext Callback Fail Tag=%s", timerHandle->label); - return -1; -} - -void TimerEvtStop(TimerHandleT *timerHandle) { - - sd_event_source_unref(timerHandle->evtSource); - free (timerHandle); -} - - -void TimerEvtStart(TimerHandleT *timerHandle, timerCallbackT callback, void *context) { - uint64_t usec; - - // populate CB handle - timerHandle->callback=callback; - timerHandle->context=context; - - // set a timer with ~250us accuracy - sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec); - sd_event_add_time(afb_daemon_get_event_loop(), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay*1000, 250, TimerNext, timerHandle); -} - -afb_event TimerEvtGet(void) { - return afbevt; -} - - -// Create Binding Event at Init -int TimerEvtInit () { - - // create binder event to send test pause/resume - afbevt = afb_daemon_make_event("control"); - if (!afb_event_is_valid(afbevt)) { - AFB_ERROR ("POLCTL_INIT: Cannot register ctl-events"); - return 1; - } - - AFB_DEBUG ("Audio Control-Events Init Done"); - return 0; -} - diff --git a/controller/ctl-timer.h b/controller/ctl-timer.h deleted file mode 100644 index e1a1ef3..0000000 --- a/controller/ctl-timer.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author Fulup Ar Foll <fulup@iot.bzh> - * - * 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. - */ - - -#ifndef CTL_TIMER_INCLUDE -#define CTL_TIMER_INCLUDE - -#include <systemd/sd-event.h> - -// ctl-timer.c -// ---------------------- -typedef int (*timerCallbackT)(void *context); - -typedef struct TimerHandleS { - int count; - int delay; - const char*label; - void *context; - timerCallbackT callback; - sd_event_source *evtSource; -} TimerHandleT; - -int TimerEvtInit (void); -afb_event TimerEvtGet(void); -void TimerEvtStart(TimerHandleT *timerHandle, timerCallbackT callback, void *context); -void TimerEvtStop(TimerHandleT *timerHandle); - -#endif // CTL_TIMER_INCLUDE |