summaryrefslogtreecommitdiffstats
path: root/ctl-lib
diff options
context:
space:
mode:
authorfulup <fulup.arfoll@iot.bzh>2017-10-18 11:31:33 +0200
committerfulup <fulup.arfoll@iot.bzh>2017-10-18 11:31:33 +0200
commit17a6011775e8c6d1536994f8b9cd4fa2f99791f7 (patch)
tree262f653a0369d080e2368bddd840e3c0fa089b29 /ctl-lib
parent29d0c8e83b1ac766395d2d5bee4d83cb0148a7ec (diff)
1st V2/pre-V3 version
Diffstat (limited to 'ctl-lib')
-rw-r--r--ctl-lib/CMakeLists.txt2
-rw-r--r--ctl-lib/ctl-action.c119
-rw-r--r--ctl-lib/ctl-config.c122
-rw-r--r--ctl-lib/ctl-config.h87
-rw-r--r--ctl-lib/ctl-control.c43
-rw-r--r--ctl-lib/ctl-event.c94
-rw-r--r--ctl-lib/ctl-lua.c564
-rw-r--r--ctl-lib/ctl-lua.h15
-rw-r--r--ctl-lib/ctl-onload.c28
-rw-r--r--ctl-lib/ctl-plugin.c64
-rw-r--r--ctl-lib/ctl-plugin.h176
-rw-r--r--ctl-lib/ctl-timer.c28
-rw-r--r--ctl-lib/ctl-timer.h8
13 files changed, 886 insertions, 464 deletions
diff --git a/ctl-lib/CMakeLists.txt b/ctl-lib/CMakeLists.txt
index 6f765d8..2630b94 100644
--- a/ctl-lib/CMakeLists.txt
+++ b/ctl-lib/CMakeLists.txt
@@ -30,7 +30,7 @@ endif(CONTROL_SUPPORT_LUA)
PROJECT_TARGET_ADD(ctl-utilities)
# Define project Targets
- ADD_LIBRARY(${TARGET_NAME} STATIC ctl-action.c ctl-config.c ctl-onload.c ctl-plugin.c ${CTL_LUA_SOURCE})
+ ADD_LIBRARY(${TARGET_NAME} STATIC ctl-action.c ctl-config.c ctl-onload.c ctl-plugin.c ctl-control.c ctl-event.c ${CTL_LUA_SOURCE})
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
diff --git a/ctl-lib/ctl-action.c b/ctl-lib/ctl-action.c
index b24269c..fa0fa6f 100644
--- a/ctl-lib/ctl-action.c
+++ b/ctl-lib/ctl-action.c
@@ -24,11 +24,18 @@
#include "ctl-config.h"
+PUBLIC int ActionLabelToIndex(CtlActionT*actions, const char* actionLabel) {
-PUBLIC int ActionExecOne(CtlActionT* action, json_object *queryJ) {
- int err;
+ for (int idx = 0; actions[idx].label; idx++) {
+ if (!strcasecmp(actionLabel, actions[idx].label)) return idx;
+ }
+ return -1;
+}
+PUBLIC void ActionExecOne(CtlSourceT *source, CtlActionT* action, json_object *queryJ) {
+ int err;
+
switch (action->type) {
case CTL_TYPE_API:
{
@@ -51,92 +58,123 @@ PUBLIC int ActionExecOne(CtlActionT* action, json_object *queryJ) {
}
}
- json_object_object_add(queryJ, "label", json_object_new_string(action->source.label));
+ json_object_object_add(queryJ, "label", json_object_new_string(source->label));
- int err = afb_service_call_sync(action->api, action->call, queryJ, &returnJ);
+ int err = AFB_ServiceSync(action->api, action->exec.subcall.api, action->exec.subcall.verb, 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;
+ AFB_ApiError(action->api, "ActionExecOne(AppFw) label=%s api=%s verb=%s args=%s", source->label, action->exec.subcall.api, action->exec.subcall.verb, json_object_get_string(action->argsJ));
}
break;
}
#ifdef CONTROL_SUPPORT_LUA
case CTL_TYPE_LUA:
- err = LuaCallFunc(action, queryJ);
+ err = LuaCallFunc(source, 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;
+ AFB_ApiError(action->api, "ActionExecOne(Lua) label=%s func=%s args=%s", source->label, action->exec.lua.funcname, json_object_get_string(action->argsJ));
}
break;
#endif
case CTL_TYPE_CB:
- err = (*action->actionCB) (&action->source, action->argsJ, queryJ);
+ err = (*action->exec.cb.callback) (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;
+ AFB_ApiError(action->api, "ActionExecOne(Callback) label%s plugin=%s function=%s args=%s", source->label, action->exec.cb.plugin->label, action->exec.cb.funcname, json_object_get_string(action->argsJ));
}
break;
default:
{
- AFB_ERROR("ActionExecOne(unknown) API type label=%s", action->source.label);
- goto OnErrorExit;
+ AFB_ApiError(action->api, "ActionExecOne(unknown) API type label=%s", source->label);
+ break;
}
}
+}
- return 0;
-OnErrorExit:
- return -1;
+// Direct Request Call in APIV3
+#ifdef AFB_BINDING_PREV3
+STATIC void ActionDynRequest (AFB_ReqT request) {
+
+ // retrieve action handle from request and execute the request
+ json_object *queryJ = afb_request_json(request);
+ CtlActionT* action = (CtlActionT*)afb_request_get_vcbdata(request);
+
+ CtlSourceT source;
+ source.label = action->label;
+ source.request = request;
+ source.api = action->api;
+
+ // provide request and execute the action
+ ActionExecOne(&source, action, queryJ);
}
-
+#endif
// unpack individual action object
-PUBLIC int ActionLoadOne(CtlActionT *action, json_object *actionJ) {
- char *api = NULL, *verb = NULL, *lua = NULL;
+PUBLIC int ActionLoadOne(AFB_ApiT apiHandle, CtlActionT *action, json_object *actionJ, int exportApi) {
int err, modeCount = 0;
- json_object *callbackJ=NULL;
+ json_object *callbackJ=NULL, *luaJ=NULL, *subcallJ=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);
+ err = wrap_json_unpack(actionJ, "{ss,s?s,s?o,s?o,s?o,s?o !}"
+ , "label", &action->label, "info", &action->info, "callback", &callbackJ, "lua", &luaJ, "subcall", &subcallJ, "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));
+ AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Action missing label|[info]|[callback]|[lua]|[subcall]|[args] in:\n-- %s", json_object_get_string(actionJ));
goto OnErrorExit;
}
+
+ // save per action api handle
+ action->api = apiHandle;
+
+ // in API V3 each control is optionally map to a verb
+#ifdef AFB_BINDING_PREV3
+ if (apiHandle && exportApi) {
+ err = afb_dynapi_add_verb(apiHandle, action->label, action->info, ActionDynRequest, action, NULL, 0);
+ if (err) {
+ AFB_ApiError(apiHandle,"ACTION-LOAD-ONE fail to register API verb=%s", action->label);
+ goto OnErrorExit;
+ }
+ action->api = apiHandle;
+ }
+#endif
- if (lua) {
- action->type = CTL_TYPE_LUA;
- action->call = lua;
+ if (luaJ) {
modeCount++;
+ action->type = CTL_TYPE_LUA;
+ 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 missing [load]|func in:\n-- %s", json_object_get_string(luaJ));
+ goto OnErrorExit;
+ }
}
- if (api && verb) {
- action->type = CTL_TYPE_API;
- action->api = api;
- action->call = verb;
+ if (subcallJ) {
modeCount++;
+ action->type = CTL_TYPE_API;
+
+ err = wrap_json_unpack(luaJ, "{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(luaJ));
+ goto OnErrorExit;
+ }
}
if (callbackJ) {
+ modeCount++;
action->type = CTL_TYPE_CB;
modeCount++;
- err = PluginGetCB (action, callbackJ);
- if (err) goto OnErrorExit;
-
+ err = PluginGetCB (apiHandle, 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));
+ 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_ERROR("ACTION-LOAD-ONE:ToMany arguments lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
+ AFB_ApiError(apiHandle,"ACTION-LOAD-ONE:ToMany arguments lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
goto OnErrorExit;
}
return 0;
@@ -145,7 +183,7 @@ OnErrorExit:
return 1;
};
-PUBLIC CtlActionT *ActionLoad(json_object *actionsJ) {
+PUBLIC CtlActionT *ActionConfig(AFB_ApiT apiHandle, json_object *actionsJ, int exportApi) {
int err;
CtlActionT *actions;
@@ -156,13 +194,14 @@ PUBLIC CtlActionT *ActionLoad(json_object *actionsJ) {
for (int idx = 0; idx < count; idx++) {
json_object *actionJ = json_object_array_get_idx(actionsJ, idx);
- err = ActionLoadOne(&actions[idx], actionJ);
+
+ err = ActionLoadOne(apiHandle, &actions[idx], actionJ, exportApi);
if (err) goto OnErrorExit;
}
} else {
actions = calloc(2, sizeof (CtlActionT));
- err = ActionLoadOne(&actions[0], actionsJ);
+ err = ActionLoadOne(apiHandle, &actions[0], actionsJ, exportApi);
if (err) goto OnErrorExit;
}
diff --git a/ctl-lib/ctl-config.c b/ctl-lib/ctl-config.c
index b7c0d54..2b5d345 100644
--- a/ctl-lib/ctl-config.c
+++ b/ctl-lib/ctl-config.c
@@ -21,6 +21,8 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
+#include <sys/time.h>
+
#include "filescan-utils.h"
#include "ctl-config.h"
@@ -28,16 +30,36 @@
// Load control config file
-PUBLIC char* CtlConfigSearch(const char *dirList) {
- int index, err;
- char controlFile [CONTROL_MAXPATH_LEN];
+PUBLIC int CtlConfigMagicNew() {
+ static int InitRandomDone=0;
+
+ if (!InitRandomDone) {
+ struct timeval tv;
+ InitRandomDone=1;
+ gettimeofday(&tv,NULL);
+ srand ((int)tv.tv_usec);
+ }
+
+ return ((long)rand());
+}
- strncpy(controlFile, CONTROL_CONFIG_PRE "-", CONTROL_MAXPATH_LEN);
+PUBLIC json_object* CtlConfigScan(const char *dirList, const char *prefix) {
+ char controlFile [CONTROL_MAXPATH_LEN];
+ strncpy(controlFile, prefix, CONTROL_MAXPATH_LEN);
strncat(controlFile, GetBinderName(), CONTROL_MAXPATH_LEN);
// search for default dispatch config file
json_object* responseJ = ScanForConfig(dirList, CTL_SCAN_RECURSIVE, controlFile, ".json");
+ return responseJ;
+}
+
+PUBLIC char* CtlConfigSearch(AFB_ApiT apiHandle, const char *dirList, const char *prefix) {
+ int index, err;
+
+ // search for default dispatch config file
+ json_object* responseJ = CtlConfigScan (dirList, prefix);
+
// 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);
@@ -46,18 +68,16 @@ PUBLIC char* CtlConfigSearch(const char *dirList) {
char*fullpath;
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));
+ AFB_ApiError(apiHandle, "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, sizeof (filepath));
- strncat(filepath, "/", sizeof (filepath));
- strncat(filepath, filename, sizeof (filepath));
- return (strdup(filepath));
- }
+ char filepath[CONTROL_MAXPATH_LEN];
+ strncpy(filepath, fullpath, sizeof (filepath));
+ strncat(filepath, "/", sizeof (filepath));
+ strncat(filepath, filename, sizeof (filepath));
+ return (strdup(filepath));
}
}
@@ -65,15 +85,16 @@ PUBLIC char* CtlConfigSearch(const char *dirList) {
return NULL;
}
-PUBLIC int CtlConfigExec(CtlConfigT *ctlConfig) {
+PUBLIC int CtlConfigExec(AFB_ApiT apiHandle, 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);
+ int err = AFB_RequireApi(apiHandle, requireBinding, 1);
if (err) {
- AFB_WARNING("CTL-LOAD-CONFIG:REQUIRE Fail to get=%s", requireBinding);
+ AFB_ApiWarning(apiHandle, "CTL-LOAD-CONFIG:REQUIRE Fail to get=%s", requireBinding);
}
}
@@ -87,14 +108,14 @@ PUBLIC int CtlConfigExec(CtlConfigT *ctlConfig) {
}
#ifdef CONTROL_SUPPORT_LUA
- int err= LuaConfigExec();
+ int err= LuaConfigExec(apiHandle);
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);
+ errcount += ctlConfig->sections[idx].loadCB(apiHandle, &ctlConfig->sections[idx], NULL);
}
return errcount;
@@ -102,73 +123,66 @@ OnErrorExit:
return 1;
}
-PUBLIC CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections) {
+PUBLIC CtlConfigT *CtlLoadMetaData(AFB_ApiT apiHandle, const char* filepath) {
json_object *ctlConfigJ;
- CtlConfigT *ctlConfig;
+ CtlConfigT *ctlHandle=NULL;
int err;
-#ifdef CONTROL_SUPPORT_LUA
- err= LuaConfigLoad();
- if (err) goto OnErrorExit;
-#endif
-
- // Search for config in filepath
- filepath = CtlConfigSearch(filepath);
-
- if (!filepath) {
- AFB_ERROR("CTL-LOAD-CONFIG No JSON Config found invalid JSON %s ", filepath);
- goto OnErrorExit;
- }
-
// Load JSON file
ctlConfigJ = json_object_from_file(filepath);
if (!ctlConfigJ) {
- AFB_ERROR("CTL-LOAD-CONFIG Not invalid JSON %s ", filepath);
+ AFB_ApiError(apiHandle, "CTL-LOAD-CONFIG Not invalid JSON %s ", filepath);
goto OnErrorExit;
}
- AFB_INFO("CTL-LOAD-CONFIG: loading config filepath=%s", filepath);
+ AFB_ApiInfo(apiHandle, "CTL-LOAD-CONFIG: loading config filepath=%s", filepath);
json_object *metadataJ;
int done = json_object_object_get_ex(ctlConfigJ, "metadata", &metadataJ);
if (done) {
- ctlConfig = calloc(1, sizeof (CtlConfigT));
- err = wrap_json_unpack(metadataJ, "{ss,ss,ss,s?s,s?o !}", "label", &ctlConfig->label, "version", &ctlConfig->version
- , "api", &ctlConfig->api, "info", &ctlConfig->info, "require", &ctlConfig->requireJ);
+ ctlHandle = calloc(1, sizeof (CtlConfigT));
+ err = wrap_json_unpack(metadataJ, "{ss,ss,ss,s?s,s?o !}", "label", &ctlHandle->label, "version", &ctlHandle->version
+ , "api", &ctlHandle->api, "info", &ctlHandle->info, "require", &ctlHandle->requireJ);
if (err) {
- AFB_ERROR("CTL-LOAD-CONFIG:METADATA Missing something label|api|version|[info]|[require] in:\n-- %s", json_object_get_string(metadataJ));
+ AFB_ApiError(apiHandle, "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);
- }
-
}
+
+ ctlHandle->configJ = ctlConfigJ;
+ return ctlHandle;
+
+OnErrorExit:
+ if (ctlHandle) free(ctlHandle);
+ return NULL;
+}
+
+PUBLIC int CtlLoadSections(AFB_ApiT apiHandle, CtlConfigT *ctlHandle, CtlSectionT *sections) {
+ int err;
+
+#ifdef CONTROL_SUPPORT_LUA
+ err= LuaConfigLoad(apiHandle);
+ if (err) goto OnErrorExit;
+#endif
- //load config sections
err = 0;
- ctlConfig->sections = sections;
+ ctlHandle->sections = sections;
for (int idx = 0; sections[idx].key != NULL; idx++) {
json_object * sectionJ;
- int done = json_object_object_get_ex(ctlConfigJ, sections[idx].key, &sectionJ);
+ int done = json_object_object_get_ex(ctlHandle->configJ, sections[idx].key, &sectionJ);
if (!done) {
- AFB_ERROR("CtlConfigLoad: fail to find '%s' section in config '%s'", sections[idx].key, filepath);
+ AFB_ApiError(apiHandle, "CtlConfigLoad: fail to find '%s' section in config '%s'", sections[idx].key, ctlHandle->label);
err++;
} else {
- err += sections[idx].loadCB(&sections[idx], sectionJ);
+ err += sections[idx].loadCB(apiHandle, &sections[idx], sectionJ);
}
-
}
if (err) goto OnErrorExit;
- return (ctlConfig);
+ return 0;
OnErrorExit:
- free(ctlConfig);
- return NULL;
+ return 1;
}
diff --git a/ctl-lib/ctl-config.h b/ctl-lib/ctl-config.h
index 2e3a16a..09c573f 100644
--- a/ctl-lib/ctl-config.h
+++ b/ctl-lib/ctl-config.h
@@ -22,13 +22,10 @@
#define _CTL_CONFIG_INCLUDE_
#define _GNU_SOURCE
-#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"
+#include <filescan-utils.h>
+#include <wrap-json.h>
#ifndef CONTROL_MAXPATH_LEN
#define CONTROL_MAXPATH_LEN 255
@@ -42,37 +39,13 @@
#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;
+ int (*loadCB)(AFB_ApiT apihandle, struct ConfigSectionS *section, json_object *sectionJ);
+ void *handle;
+ CtlActionT *actions;
} CtlSectionT;
typedef struct {
@@ -80,6 +53,7 @@ typedef struct {
const char* label;
const char *info;
const char *version;
+ json_object *configJ;
json_object *requireJ;
CtlSectionT *sections;
} CtlConfigT;
@@ -87,27 +61,54 @@ typedef struct {
#ifdef CONTROL_SUPPORT_LUA
#include "ctl-lua.h"
-#else
- typedef void* Lua2cWrapperT;
#endif
+
+// This should not be global as application may want to define their own sections
+typedef enum {
+ CTL_SECTION_PLUGIN,
+ CTL_SECTION_ONLOAD,
+ CTL_SECTION_CONTROL,
+ CTL_SECTION_EVENT,
+ CTL_SECTION_HAL,
+
+ CTL_SECTION_ENDTAG,
+} SectionEnumT;
// ctl-action.c
-PUBLIC CtlActionT *ActionLoad(json_object *actionsJ);
-PUBLIC int ActionExecOne(CtlActionT* action, json_object *queryJ);
-PUBLIC int ActionLoadOne(CtlActionT *action, json_object *actionJ);
+PUBLIC CtlActionT *ActionConfig(AFB_ApiT apiHandle, json_object *actionsJ, int exportApi);
+PUBLIC void ActionExecOne( CtlSourceT *source, CtlActionT* action, json_object *queryJ);
+PUBLIC int ActionLoadOne(AFB_ApiT apiHandle, CtlActionT *action, json_object *, int exportApi);
+PUBLIC int ActionLabelToIndex(CtlActionT* actions, const char* actionLabel);
+
// ctl-config.c
-PUBLIC CtlConfigT *CtlConfigLoad(const char* filepath, CtlSectionT *sections);
-PUBLIC int CtlConfigExec(CtlConfigT *ctlConfig);
+PUBLIC int CtlConfigMagicNew();
+PUBLIC json_object* CtlConfigScan(const char *dirList, const char *prefix) ;
+PUBLIC char* CtlConfigSearch(AFB_ApiT apiHandle, const char *dirList, const char *prefix) ;
+PUBLIC int CtlConfigExec(AFB_ApiT apiHandle, CtlConfigT *ctlConfig) ;
+PUBLIC CtlConfigT *CtlLoadMetaData(AFB_ApiT apiHandle,const char* filepath) ;
+PUBLIC int CtlLoadSections(AFB_ApiT apiHandle, CtlConfigT *ctlHandle, CtlSectionT *sections);
-// ctl-onload.c
-PUBLIC int OnloadConfig(CtlSectionT *section, json_object *actionsJ);
+// ctl-event.c
+PUBLIC int EventConfig(AFB_ApiT apihandle, CtlSectionT *section, json_object *actionsJ);
+#ifdef AFB_BINDING_PREV3
+PUBLIC void CtrlDispatchApiEvent (AFB_ApiT apiHandle, const char *evtLabel, struct json_object *eventJ);
+#else
+PUBLIC void CtrlDispatchV2Event(const char *evtLabel, json_object *eventJ);
+#endif
+
+// ctl-control.c
+PUBLIC int ControlConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ);
+
+// ctl-onload.c
+PUBLIC int OnloadConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ);
+
// ctl-plugin.c
-PUBLIC int PluginConfig(CtlSectionT *section, json_object *pluginsJ);
-PUBLIC int PluginGetCB (CtlActionT *action , json_object *callbackJ);
+PUBLIC int PluginConfig(AFB_ApiT UNUSED_ARG(apiHandle), CtlSectionT *section, json_object *pluginsJ);
+PUBLIC int PluginGetCB (AFB_ApiT apiHandle, CtlActionT *action , json_object *callbackJ);
#endif /* _CTL_CONFIG_INCLUDE_ */ \ No newline at end of file
diff --git a/ctl-lib/ctl-control.c b/ctl-lib/ctl-control.c
new file mode 100644
index 0000000..117f5b5
--- /dev/null
+++ b/ctl-lib/ctl-control.c
@@ -0,0 +1,43 @@
+/*
+ * 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
+PUBLIC int ControlConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ) {
+
+ // Load time parse actions in config file
+ if (actionsJ != NULL) {
+ section->actions= ActionConfig(apiHandle, actionsJ, 1);
+
+ if (!section->actions) {
+ AFB_ApiError (apiHandle, "ControlLoad config fail processing onload actions");
+ goto OnErrorExit;
+ }
+ }
+
+ return 0;
+
+OnErrorExit:
+ return 1;
+
+}
diff --git a/ctl-lib/ctl-event.c b/ctl-lib/ctl-event.c
new file mode 100644
index 0000000..b9be1c7
--- /dev/null
+++ b/ctl-lib/ctl-event.c
@@ -0,0 +1,94 @@
+/*
+ * 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"
+
+
+// Event dynamic API-V3 mode
+#ifdef AFB_BINDING_PREV3
+PUBLIC void CtrlDispatchApiEvent (AFB_ApiT apiHandle, const char *evtLabel, struct json_object *eventJ) {
+ AFB_ApiNotice (apiHandle, "Received event=%s, query=%s", evtLabel, json_object_get_string(eventJ));
+
+ // retrieve section config from api handle
+ CtlConfigT *ctrlConfig = (CtlConfigT*) afb_dynapi_get_userdata(apiHandle);
+
+ CtlActionT* actions = ctrlConfig->sections[CTL_SECTION_EVENT].actions;
+
+ int index= ActionLabelToIndex(actions, evtLabel);
+ if (index < 0) {
+ AFB_ApiWarning(apiHandle, "CtlDispatchEvent: fail to find label=%s in action event section", evtLabel);
+ return;
+ }
+
+ // create a dummy source for action
+ CtlSourceT source;
+ source.label = actions[index].label;
+ source.api = actions[index].api;
+ source.request = NULL;
+
+ // Best effort ignoring error to exec corresponding action
+ (void) ActionExecOne (&source, &actions[index], eventJ);
+
+}
+#else
+// In API-V2 controller config is unique and static
+extern CtlConfigT *ctrlConfig;
+
+// call action attached to even name if any
+PUBLIC void CtrlDispatchV2Event(const char *evtLabel, json_object *eventJ) {
+ CtlActionT* actions = ctrlConfig->sections[CTL_SECTION_EVENT].actions;
+
+ int index= ActionLabelToIndex(actions, evtLabel);
+ if (index < 0) {
+ AFB_WARNING ("CtlDispatchEvent: fail to find label=%s in action event section", evtLabel);
+ return;
+ }
+
+ CtlSourceT source;
+ source.label = actions[index].label;
+ source.api = actions[index].api;
+ source.request = AFB_ReqNone;
+
+ // Best effort ignoring error to exec corresponding action
+ (void) ActionExecOne (&source, &actions[index], eventJ);
+}
+#endif
+
+// onload section receive one action or an array of actions
+PUBLIC int EventConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ) {
+
+ // Load time parse actions in config file
+ if (actionsJ != NULL) {
+ section->actions= ActionConfig(apiHandle, actionsJ, 1);
+
+ if (!section->actions) {
+ AFB_ApiError (apiHandle, "EventLoad config fail processing onload actions");
+ goto OnErrorExit;
+ }
+ }
+
+ return 0;
+
+OnErrorExit:
+ return 1;
+
+}
diff --git a/ctl-lib/ctl-lua.c b/ctl-lib/ctl-lua.c
index 7b68fe2..2aaaabb 100644
--- a/ctl-lib/ctl-lua.c
+++ b/ctl-lib/ctl-lua.c
@@ -27,47 +27,43 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
+#include <sys/time.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"
+#ifndef CTX_MAGIC
+ static int CTX_MAGIC;
+#endif
+
+#ifndef TIMER_MAGIC
+ static int TIMER_MAGIC;
+#endif
typedef struct {
char *name;
int count;
- afb_event event;
+ AFB_EventT event;
} LuaAfbEvent;
-static LuaAfbEvent *luaDefaultEvt;
typedef struct {
int ctxMagic;
- afb_req request;
- void *handle;
- char *info;
-} LuaAfbContextT;
+ CtlSourceT *source;
+} LuaAfbSourceT;
typedef struct {
const char *callback;
json_object *context;
- void *handle;
-} LuaCallServiceT;
+ CtlSourceT *source;
+} LuaCbHandleT;
+
-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
@@ -75,43 +71,32 @@ typedef enum {
* 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);
+STATIC CtlSourceT *LuaSourcePop (lua_State *luaState, int index) {
+ LuaAfbSourceT *afbSource;
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");
+ afbSource = (LuaAfbSourceT *) lua_touserdata(luaState, index);
+ if (afbSource == NULL || afbSource->ctxMagic != CTX_MAGIC) {
+ luaL_error(luaState, "(Hoops) Invalid source handle");
return NULL;
}
- return afbContext;
+ return afbSource->source;
}
-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");
+STATIC LuaAfbSourceT *LuaSourcePush (lua_State *luaState, CtlSourceT *source) {
+ LuaAfbSourceT *afbSource = (LuaAfbSourceT *)calloc(1, sizeof(LuaAfbSourceT));
+ if (!afbSource) {
+ AFB_ApiError(source->api, "LuaSourcePush 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);
+
+ lua_pushlightuserdata(luaState, afbSource);
+ afbSource->ctxMagic=CTX_MAGIC;
+ afbSource->source= source;
+ return afbSource;
}
// Push a json structure on the stack as a LUA table
-STATIC int LuaPushArgument (json_object *argsJ) {
+STATIC int LuaPushArgument (CtlSourceT *source, json_object *argsJ) {
//AFB_NOTICE("LuaPushArgument argsJ=%s", json_object_get_string(argsJ));
@@ -120,7 +105,7 @@ STATIC int LuaPushArgument (json_object *argsJ) {
case json_type_object: {
lua_newtable (luaState);
json_object_object_foreach (argsJ, key, val) {
- int done = LuaPushArgument (val);
+ int done = LuaPushArgument (source, val);
if (done) {
lua_setfield(luaState,-2, key);
}
@@ -132,7 +117,7 @@ STATIC int LuaPushArgument (json_object *argsJ) {
lua_newtable (luaState);
for (int idx=0; idx < length; idx ++) {
json_object *val=json_object_array_get_idx(argsJ, idx);
- LuaPushArgument (val);
+ LuaPushArgument (source, val);
lua_seti (luaState,-2, idx);
}
break;
@@ -150,23 +135,23 @@ STATIC int LuaPushArgument (json_object *argsJ) {
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));
+ AFB_ApiWarning(source->api, "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));
+ AFB_ApiError(source->api, "LuaPushArgument: unsupported Json object type %s", json_object_get_string(argsJ));
return 0;
}
return 1;
}
-STATIC json_object *LuaPopOneArg (lua_State* luaState, int idx);
+STATIC json_object *LuaPopOneArg (CtlSourceT *source, 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) {
+STATIC json_object *LuaTableToJson (CtlSourceT *source, lua_State* luaState, int index) {
#define LUA_KEY_INDEX -2
#define LUA_VALUE_INDEX -1
@@ -185,12 +170,12 @@ STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
tableJ= json_object_new_object();
tableType=LUA_TSTRING;
} else if (tableType != LUA_TSTRING){
- AFB_ERROR("MIX Lua Table with key string/numeric not supported");
+ AFB_ApiError(source->api, "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 *argJ= LuaPopOneArg(source, luaState, LUA_VALUE_INDEX);
json_object_object_add(tableJ, key, argJ);
} else {
@@ -198,11 +183,11 @@ STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
tableJ= json_object_new_array();
tableType=LUA_TNUMBER;
} else if(tableType != LUA_TNUMBER) {
- AFB_ERROR("MIX Lua Table with key numeric/string not supported");
+ AFB_ApiError(source->api, "MIX Lua Table with key numeric/string not supported");
return NULL;
}
- json_object *argJ= LuaPopOneArg(luaState, LUA_VALUE_INDEX);
+ json_object *argJ= LuaPopOneArg(source, luaState, LUA_VALUE_INDEX);
json_object_array_add(tableJ, argJ);
}
@@ -218,7 +203,7 @@ STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
return tableJ;
}
-STATIC json_object *LuaPopOneArg (lua_State* luaState, int idx) {
+STATIC json_object *LuaPopOneArg (CtlSourceT *source, lua_State* luaState, int idx) {
json_object *value=NULL;
int luaType = lua_type(luaState, idx);
@@ -240,7 +225,7 @@ STATIC json_object *LuaPopOneArg (lua_State* luaState, int idx) {
value= json_object_new_string(lua_tostring(luaState, idx));
break;
case LUA_TTABLE:
- value= LuaTableToJson(luaState, idx);
+ value= LuaTableToJson(source, luaState, idx);
break;
case LUA_TNIL:
value=json_object_new_string("nil") ;
@@ -250,14 +235,14 @@ STATIC json_object *LuaPopOneArg (lua_State* luaState, int idx) {
break;
default:
- AFB_NOTICE ("LuaPopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType));
+ AFB_ApiNotice (source->api, "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) {
+static json_object *LuaPopArgs (CtlSourceT *source, lua_State* luaState, int start) {
json_object *responseJ;
int stop = lua_gettop(luaState);
@@ -265,12 +250,12 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) {
// start at 2 because we are using a function array lib
if (start == stop) {
- responseJ=LuaPopOneArg (luaState, start);
+ responseJ=LuaPopOneArg (source, 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);
+ json_object *argJ=LuaPopOneArg (source, luaState, idx);
if (!argJ) goto OnErrorExit;
json_object_array_add(responseJ, argJ);
}
@@ -283,10 +268,41 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) {
}
-STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
- char *message;
- json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG);
+ /*
+ * 'level' is defined by syslog standard:
+ * EMERGENCY 0 System is unusable
+ * ALERT 1 Action must be taken immediately
+ * CRITICAL 2 Critical conditions
+ * ERROR 3 Error conditions
+ * WARNING 4 Warning conditions
+ * NOTICE 5 Normal but significant condition
+ * INFO 6 Informational
+ * DEBUG 7 Debug-level messages
+ */
+typedef enum {
+ AFB_MSG_INFO=6,
+ AFB_MSG_WARNING=4,
+ AFB_MSG_NOTICE=5,
+ AFB_MSG_DEBUG=7,
+ AFB_MSG_ERROR=3,
+} LuaAfbLevelT;
+
+STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbLevelT level) {
+ char *message;
+
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) goto OnErrorExit;
+\
+
+ // if log level low then silently ignore message
+#ifdef AFB_BINDING_PREV3
+ if(source->api->verbosity < level) return 0;
+#else
+ if(afb_get_verbosity() < level) return 0;
+#endif
+
+ json_object *responseJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
if (!responseJ) {
luaL_error(luaState,"LuaFormatMessage empty message");
@@ -329,6 +345,10 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
message[targetIdx]='%';
targetIdx++;
break;
+
+ case 'A':
+ targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"level: %s", source->label);
+ break;
case 's':
default:
@@ -339,7 +359,7 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
} else {
if (targetIdx >= LUA_MSG_MAX_LENGTH) {
- AFB_WARNING ("LuaFormatMessage: message[%s] owerverflow LUA_MSG_MAX_LENGTH=%d", format, LUA_MSG_MAX_LENGTH);
+ AFB_ApiWarning (source->api, "LuaFormatMessage: message[%s] owerverflow LUA_MSG_MAX_LENGTH=%d", format, LUA_MSG_MAX_LENGTH);
targetIdx --; // move backward for EOL
break;
} else {
@@ -350,36 +370,22 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
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);
- }
+ // TBD: __file__ and __line__ should match LUA source code
+ AFB_ApiVerbose(source->api, level,__FILE__,__LINE__,source->label, 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);
+ int err=LuaFormatMessage (luaState, AFB_MSG_DEBUG);
return err; // no value return
}
@@ -394,21 +400,20 @@ STATIC int LuaPrintNotice(lua_State* luaState) {
}
STATIC int LuaPrintDebug(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_DEBUG);
+ int err=LuaFormatMessage (luaState, AFB_MSG_ERROR);
return err;
}
STATIC int LuaAfbSuccess(lua_State* luaState) {
- LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
- if (!afbContext) goto OnErrorExit;
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) goto OnErrorExit;
// ignore context argument
- json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
+ json_object *responseJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
if (responseJ == JSON_ERROR) return 1;
- afb_req_success(afbContext->request, responseJ, NULL);
+ AFB_ReqSucess (source->request, responseJ, NULL);
- LuaCtxFree(afbContext);
return 0;
OnErrorExit:
@@ -417,15 +422,14 @@ STATIC int LuaAfbSuccess(lua_State* luaState) {
}
STATIC int LuaAfbFail(lua_State* luaState) {
- LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
- if (!afbContext) goto OnErrorExit;
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) goto OnErrorExit;
- json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
+ json_object *responseJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
if (responseJ == JSON_ERROR) return 1;
- afb_req_fail(afbContext->request, afbContext->info, json_object_get_string(responseJ));
+ AFB_ReqFail(source->request, source->label, json_object_get_string(responseJ));
- LuaCtxFree(afbContext);
return 0;
OnErrorExit:
@@ -433,46 +437,52 @@ STATIC int LuaAfbFail(lua_State* luaState) {
return 1;
}
-STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ) {
- LuaCallServiceT *contextCB= (LuaCallServiceT*)handle;
+STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ, AFB_ApiT apiHandle) {
+ LuaCbHandleT *handleCb= (LuaCbHandleT*)handle;
int count=1;
- lua_getglobal(luaState, contextCB->callback);
+ lua_getglobal(luaState, handleCb->callback);
// push error status & response
lua_pushboolean(luaState, iserror);
- count+= LuaPushArgument(responseJ);
- count+= LuaPushArgument(contextCB->context);
+ count+= LuaPushArgument(handleCb->source, responseJ);
+ count+= LuaPushArgument(handleCb->source, handleCb->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) );
+ AFB_ApiError(apiHandle, "LUA-SERICE-CB:FAIL response=%s err=%s", json_object_get_string(responseJ), lua_tostring(luaState,-1) );
}
- free (contextCB);
+ free (handleCb);
}
STATIC int LuaAfbService(lua_State* luaState) {
int count = lua_gettop(luaState);
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) {
+ lua_pushliteral (luaState, "LuaAfbService-Fail Invalid request handle");
+ goto OnErrorExit;
+ }
+
// 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)) {
+ if (count <6 || !lua_isstring(luaState, 3) || !lua_isstring(luaState, 4) || !lua_istable(luaState, 5) || !lua_isstring(luaState, 6)) {
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);
+ const char *api = lua_tostring(luaState,3);
+ const char *verb= lua_tostring(luaState,4);
+ json_object *queryJ= LuaTableToJson(source, luaState, 5);
if (queryJ == JSON_ERROR) return 1;
- LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT));
- contextCB->callback= lua_tostring(luaState, 5);
- contextCB->context = LuaPopArgs(luaState, 6);
+ LuaCbHandleT *handleCb = calloc (1, sizeof(LuaCbHandleT));
+ handleCb->callback= lua_tostring(luaState, 6);
+ handleCb->context = LuaPopArgs(source, luaState, 7);
- afb_service_call(api, verb, queryJ, LuaAfbServiceCB, contextCB);
+ AFB_ServiceCall(source->api, api, verb, queryJ, LuaAfbServiceCB, handleCb);
return 0; // no value return
@@ -485,22 +495,29 @@ STATIC int LuaAfbServiceSync(lua_State* luaState) {
int count = lua_gettop(luaState);
json_object *responseJ;
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) {
+ lua_pushliteral (luaState, "LuaAfbServiceSync-Fail Invalid request handle");
+ goto OnErrorExit;
+ }
+
// note: argument start at 2 because of AFB: table
- if (count <3 || !lua_isstring(luaState, 2) || !lua_isstring(luaState, 3) || !lua_istable(luaState, 4)) {
+ if (count <4 || !lua_isstring(luaState, 3) || !lua_isstring(luaState, 4) || !lua_istable(luaState, 5)) {
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);
+
+ // get source/api/verb+query
+ const char *api = lua_tostring(luaState,LUA_FIST_ARG+2);
+ const char *verb= lua_tostring(luaState,LUA_FIST_ARG+3);
+ json_object *queryJ= LuaTableToJson(source, luaState, LUA_FIST_ARG+4);
- int iserror=afb_service_call_sync (api, verb, queryJ, &responseJ);
+ int iserror=AFB_ServiceSync(source->api, api, verb, queryJ, &responseJ);
// push error status & response
count=1; lua_pushboolean(luaState, iserror);
- count+= LuaPushArgument(responseJ);
+ count+= LuaPushArgument(source, responseJ);
return count; // return count values
@@ -511,38 +528,42 @@ STATIC int LuaAfbServiceSync(lua_State* luaState) {
STATIC int LuaAfbEventPush(lua_State* luaState) {
LuaAfbEvent *afbevt;
- int index;
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) {
+ 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)) {
- afbevt = (LuaAfbEvent*) lua_touserdata(luaState, LUA_FIST_ARG);
- index=LUA_FIST_ARG+1;
- } else {
- index=LUA_FIST_ARG;
- afbevt=luaDefaultEvt;
+ if (!lua_islightuserdata(luaState, LUA_FIST_ARG+1)) {
+ lua_pushliteral (luaState, "LuaAfbMakePush-Fail missing event handle");
+ goto OnErrorExit;
}
-
- if (!afb_event_is_valid(afbevt->event)) {
+
+ afbevt = (LuaAfbEvent*) lua_touserdata(luaState, LUA_FIST_ARG+1);
+
+ if (!AFB_EventIsValid(afbevt->event)) {
lua_pushliteral (luaState, "LuaAfbMakePush-Fail invalid event");
goto OnErrorExit;
}
- json_object *ctlEventJ= LuaTableToJson(luaState, index);
+ json_object *ctlEventJ= LuaTableToJson(source, luaState, LUA_FIST_ARG+2);
if (!ctlEventJ) {
lua_pushliteral (luaState, "LuaAfbEventPush-Syntax is AFB:signal ([evtHandle], {lua table})");
goto OnErrorExit;
}
- int done = afb_event_push(afbevt->event, ctlEventJ);
+ int done = AFB_EventPush(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);
+ AFB_ApiError(source->api, "LuaAfbEventPush-Fail name subscriber event=%s count=%d", afbevt->name, afbevt->count);
goto OnErrorExit;
}
afbevt->count++;
return 0;
- OnErrorExit:
+OnErrorExit:
lua_error(luaState);
return 1;
}
@@ -550,28 +571,29 @@ STATIC int LuaAfbEventPush(lua_State* luaState) {
STATIC int LuaAfbEventSubscribe(lua_State* luaState) {
LuaAfbEvent *afbevt;
- LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
- if (!afbContext) {
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) {
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 (!lua_islightuserdata(luaState, LUA_FIST_ARG+1)) {
+ lua_pushliteral (luaState, "LuaAfbMakePush-Fail missing event handle");
+ goto OnErrorExit;
}
+
+ afbevt = (LuaAfbEvent*) lua_touserdata(luaState, LUA_FIST_ARG+1);
- if (!afb_event_is_valid(afbevt->event)) {
+ if (!AFB_EventIsValid(afbevt->event)) {
lua_pushliteral (luaState, "LuaAfbMakePush-Fail invalid event handle");
goto OnErrorExit;
}
- int err = afb_req_subscribe(afbContext->request, afbevt->event);
+ int err = AFB_ReqSubscribe(source->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);
+ AFB_ApiError(source->api, "LuaAfbEventPush-Fail name subscriber event=%s count=%d", afbevt->name, afbevt->count);
goto OnErrorExit;
}
afbevt->count++;
@@ -586,17 +608,24 @@ 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)) {
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) {
+ lua_pushliteral (luaState, "LuaAfbEventMake-Fail Invalid request handle");
+ goto OnErrorExit;
+ }
+
+ if (count != LUA_FIST_ARG+1 || !lua_isstring(luaState, LUA_FIST_ARG+1)) {
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));
+ afbevt->name= strdup (lua_tostring(luaState,LUA_FIST_ARG+1));
// create a new binder event
- afbevt->event = afb_daemon_make_event(afbevt->name);
- if (!afb_event_is_valid(afbevt->event)) {
+ afbevt->event = AFB_EventMake(source->api, afbevt->name);
+ if (!AFB_EventIsValid(afbevt->event)) {
+ AFB_ApiError (source->api,"Fail to CreateEvent evtname=%s", afbevt->name);
lua_pushliteral (luaState, "LuaAfbEventMake-Fail to Create Binder event");
goto OnErrorExit;
}
@@ -610,38 +639,63 @@ STATIC int LuaAfbEventMake(lua_State* luaState) {
return 1;
}
+STATIC int LuaAfbGetLabel (lua_State* luaState) {
+
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) {
+ lua_pushliteral (luaState, "LuaAfbEventSubscribe-Fail Invalid request handle");
+ goto OnErrorExit;
+ }
+
+ // extract and return afbSource from timer handle
+ lua_pushstring(luaState, source->label);
+
+ return 1; // return argument
+
+OnErrorExit:
+ return 0;
+}
+
// Function call from LUA when lua2c plugin L2C is used
-PUBLIC int Lua2cWrapper(lua_State* luaState, char *funcname, Lua2cFunctionT callback) {
+PUBLIC int Lua2cWrapper(void* luaHandle, char *funcname, Lua2cFunctionT callback) {
+ lua_State* luaState = (lua_State*)luaHandle;
+ json_object *responseJ=NULL;
+
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
- json_object *argsJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
- int response = (*callback) (funcname, argsJ);
+ json_object *argsJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
+ int err= (*callback) (source, argsJ, &responseJ);
- // push response to LUA
- lua_pushinteger(luaState, response);
- return 1;
+ // push error code and eventual response to LUA
+ int count=1;
+ lua_pushinteger (luaState, err);
+ if (!responseJ) count += LuaPushArgument (source, responseJ);
+
+ return count;
}
// Call a Lua function from a control action
-PUBLIC int LuaCallFunc (CtlActionT *action, json_object *queryJ) {
+PUBLIC int LuaCallFunc (CtlSourceT *source, CtlActionT *action, json_object *queryJ) {
int err, count;
json_object* argsJ = action->argsJ;
- const char* func = action->call;
+ const char* func = action->exec.lua.funcname;
// 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 AFB client context on the stack
+ LuaAfbSourceT *afbSource= LuaSourcePush(luaState, source);
+ if (!afbSource) goto OnErrorExit;
// push argsJ on the stack
if (!argsJ) {
- lua_pushnil(luaState);
- count++;
+ lua_pushnil(luaState); count++;
} else {
- count+= LuaPushArgument (argsJ);
+ count+= LuaPushArgument (source, argsJ);
}
// push queryJ on the stack
@@ -649,13 +703,13 @@ PUBLIC int LuaCallFunc (CtlActionT *action, json_object *queryJ) {
lua_pushnil(luaState);
count++;
} else {
- count+= LuaPushArgument (queryJ);
+ count+= LuaPushArgument (source, 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));
+ AFB_ApiError(source->api, "LuaCallFunc Fail calling %s error=%s", func, lua_tostring(luaState,-1));
goto OnErrorExit;
}
@@ -669,11 +723,14 @@ PUBLIC int LuaCallFunc (CtlActionT *action, json_object *queryJ) {
// Execute LUA code from received API request
-STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
+STATIC void LuaDoAction (LuaDoActionT action, AFB_ReqT request) {
int err, count=0;
+ CtlSourceT *source = alloca(sizeof(CtlSourceT));
+ source->request = request;
- json_object* queryJ = afb_req_json(request);
+ json_object* queryJ = AFB_ReqJson(request);
+
switch (action) {
@@ -681,12 +738,12 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
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) );
+ AFB_ApiError(source->api, "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;
+ LuaAfbSourceT *afbSource= LuaSourcePush(luaState, source);
+ if (!afbSource) goto OnErrorExit;
break;
}
@@ -697,7 +754,7 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
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));
+ AFB_ApiError(source->api, "LUA-DOCALL-SYNTAX missing target|args query=%s", json_object_get_string(queryJ));
goto OnErrorExit;
}
@@ -705,15 +762,15 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
lua_getglobal(luaState, func);
// Push AFB client context on the stack
- LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, NULL, func);
- if (!afbContext) goto OnErrorExit;
+ LuaAfbSourceT *afbSource= LuaSourcePush(luaState, source);
+ if (!afbSource) goto OnErrorExit;
// push query on the stack
if (!argsJ) {
lua_pushnil(luaState);
count++;
} else {
- count+= LuaPushArgument (argsJ);
+ count+= LuaPushArgument (source, argsJ);
}
break;
@@ -732,7 +789,7 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
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));
+ AFB_ApiError(source->api, "LUA-DOSCRIPT-SYNTAX:missing target|[path]|[function]|[args] query=%s", json_object_get_string(queryJ));
goto OnErrorExit;
}
@@ -748,11 +805,11 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
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));
+ AFB_ApiError(source->api, "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);
+ if (index > 0) AFB_ApiWarning(source->api, "LUA-DOSCRIPT-SCAN:Ignore second script=%s path=%s", filename, fullpath);
else {
strncpy (luaScriptPath, fullpath, sizeof(luaScriptPath));
strncat (luaScriptPath, "/", sizeof(luaScriptPath));
@@ -762,14 +819,14 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
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));
+ AFB_ApiError(source->api, "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);
+ AFB_ApiError(source->api, "LUA-DOSCRIPT:FAIL to load %s", luaScriptPath);
goto OnErrorExit;
}
@@ -780,7 +837,7 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
func=luaScriptPath;
}
if (!func) {
- AFB_ERROR ("LUA-DOSCRIPT:FAIL to deduct funcname from %s", filename);
+ AFB_ApiError(source->api, "LUA-DOSCRIPT:FAIL to deduct funcname from %s", filename);
goto OnErrorExit;
}
@@ -788,60 +845,73 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
lua_getglobal(luaState, func);
// Push AFB client context on the stack
- LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, NULL, func);
- if (!afbContext) goto OnErrorExit;
+ LuaAfbSourceT *afbSource= LuaSourcePush(luaState, source);
+ if (!afbSource) goto OnErrorExit;
// push function arguments
if (!argsJ) {
lua_pushnil(luaState);
count++;
} else {
- count+= LuaPushArgument(argsJ);
+ count+= LuaPushArgument(source, argsJ);
}
break;
}
default:
- AFB_ERROR ("LUA-DOSCRIPT-ACTION unknown query=%s", json_object_get_string(queryJ));
+ AFB_ApiError(source->api, "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));
+ AFB_ApiError(source->api, "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));
+ AFB_ReqFail(request,"LUA:ERROR", lua_tostring(luaState,-1));
return;
}
-PUBLIC void ctlapi_execlua (afb_req request) {
+PUBLIC void ctlapi_execlua (AFB_ReqT request) {
LuaDoAction (LUA_DOSTRING, request);
}
-PUBLIC void ctlapi_request (afb_req request) {
+PUBLIC void ctlapi_request (AFB_ReqT request) {
LuaDoAction (LUA_DOCALL, request);
}
-PUBLIC void ctlapi_debuglua (afb_req request) {
+PUBLIC void ctlapi_debuglua (AFB_ReqT 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;
+STATIC TimerHandleT *LuaTimerPop (lua_State *luaState, int index) {
+ TimerHandleT *timerHandle;
+
+ luaL_checktype(luaState, index, LUA_TLIGHTUSERDATA);
+ timerHandle = (TimerHandleT *) lua_touserdata(luaState, index);
+
+ if (timerHandle == NULL && timerHandle->magic != TIMER_MAGIC) {
+ luaL_error(luaState, "Invalid source handle");
+ fprintf(stderr, "LuaSourcePop error retrieving afbSource");
+ return NULL;
+ }
+ return timerHandle;
+}
+
+STATIC int LuaTimerClear (lua_State* luaState) {
// retrieve useful information opaque handle
- TimerHandleT *timerHandle = (TimerHandleT*)afbContext->handle;
+ TimerHandleT *timerHandle = LuaTimerPop(luaState, LUA_FIST_ARG);
+ if (!timerHandle) goto OnErrorExit;
+ LuaCbHandleT *luaCbHandle = (LuaCbHandleT*) timerHandle->context;
- AFB_NOTICE ("LuaTimerClear timer=%s", timerHandle->label);
+ AFB_ApiNotice (luaCbHandle->source->api,"LuaTimerClear timer=%s", timerHandle->label);
TimerEvtStop(timerHandle);
return 0; //happy end
@@ -851,13 +921,11 @@ OnErrorExit:
}
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;
-
+ TimerHandleT *timerHandle = LuaTimerPop(luaState, LUA_FIST_ARG);
+ if (!timerHandle) goto OnErrorExit;
+ LuaCbHandleT *luaCbHandle = (LuaCbHandleT*) timerHandle->context;
+
// 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));
@@ -865,7 +933,7 @@ STATIC int LuaTimerGet (lua_State* luaState) {
json_object_object_add(responseJ,"count", json_object_new_int(timerHandle->count));
// return JSON object as Lua table
- int count=LuaPushArgument(responseJ);
+ int count=LuaPushArgument(luaCbHandle->source, responseJ);
// free json object
json_object_put(responseJ);
@@ -880,24 +948,24 @@ OnErrorExit:
// Set timer
STATIC int LuaTimerSetCB (void *handle) {
- LuaCallServiceT *contextCB =(LuaCallServiceT*) handle;
- TimerHandleT *timerHandle = (TimerHandleT*) contextCB->handle;
+ LuaCbHandleT *LuaCbHandle = (LuaCbHandleT*) handle;
int count;
// push timer handle and user context on Lua stack
- lua_getglobal(luaState, contextCB->callback);
+ lua_getglobal(luaState, LuaCbHandle->callback);
- // Push timer handle
- LuaAfbContextT *afbContext= LuaCtxPush(luaState, NULL_AFBREQ, contextCB->handle, timerHandle->label);
- if (!afbContext) goto OnErrorExit;
count=1;
+ // Push AFB client context on the stack
+ LuaAfbSourceT *afbSource= LuaSourcePush(luaState, LuaCbHandle->source);
+ if (!afbSource) goto OnErrorExit;
// Push user Context
- count+= LuaPushArgument(contextCB->context);
+ count+= LuaPushArgument(LuaCbHandle->source, LuaCbHandle->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));
+ printf ("LUA-TIMER-CB:FAIL response=%s err=%s\n", json_object_get_string(LuaCbHandle->context), lua_tostring(luaState,-1));
+ AFB_ApiError (LuaCbHandle->source->api,"LUA-TIMER-CB:FAIL response=%s err=%s", json_object_get_string(LuaCbHandle->context), lua_tostring(luaState,-1));
goto OnErrorExit;
}
@@ -906,26 +974,36 @@ STATIC int LuaTimerSetCB (void *handle) {
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
}
+// Free Timer context handle
+STATIC int LuaTimerCtxFree(void *handle) {
+ LuaCbHandleT *LuaCbHandle = (LuaCbHandleT*) handle;
+
+ free (LuaCbHandle->source);
+ free (LuaCbHandle);
+
+ return 0;
+}
+
STATIC int LuaTimerSet(lua_State* luaState) {
const char *label=NULL, *info=NULL;
int delay=0, count=0;
+
+ // Get source handle
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) goto OnErrorExit;
- 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);
+ json_object *timerJ = LuaPopOneArg(source, luaState, LUA_FIST_ARG+1);
+ const char *callback = lua_tostring(luaState, LUA_FIST_ARG + 2);
+ json_object *contextJ = LuaPopOneArg(source, luaState, LUA_FIST_ARG + 3);
- if (lua_gettop(luaState) != LUA_FIST_ARG+2 || !timerJ || !callback || !contextJ) {
- lua_pushliteral(luaState, "LuaTimerSet-Syntax timerset (timerT, 'callback', contextT)");
+ if (lua_gettop(luaState) != LUA_FIST_ARG+3 || !timerJ || !callback || !contextJ) {
+ lua_pushliteral(luaState, "LuaTimerSet-Syntax timerset (source, timerT, 'callback', contextT)");
goto OnErrorExit;
}
@@ -935,22 +1013,30 @@ STATIC int LuaTimerSet(lua_State* luaState) {
goto OnErrorExit;
}
+ // Allocate handle to store context and callback
+ LuaCbHandleT *handleCb = calloc (1, sizeof(LuaCbHandleT));
+ handleCb->callback= callback;
+ handleCb->context = contextJ;
+ handleCb->source = malloc(sizeof(CtlSourceT));
+ memcpy (handleCb->source, source, sizeof(CtlSourceT)); // Fulup need to be free when timer is done
+
// everything look fine create timer structure
TimerHandleT *timerHandle = malloc (sizeof (TimerHandleT));
+ timerHandle->magic= TIMER_MAGIC;
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;
+ timerHandle->freeCB=LuaTimerCtxFree;
// fire timer
- TimerEvtStart (timerHandle, LuaTimerSetCB, contextCB);
+ TimerEvtStart (source->api, timerHandle, LuaTimerSetCB, handleCb);
+
+ // Fulup finir les timers avec handle
- return 0; // Happy No Return Function
+ // return empty error code plus timer handle
+ lua_pushnil(luaState);
+ lua_pushlightuserdata(luaState, timerHandle);
+ return 2;
OnErrorExit:
lua_error(luaState);
@@ -982,18 +1068,23 @@ static const luaL_Reg afbFunction[] = {
{"subscribe" , LuaAfbEventSubscribe},
{"evtmake" , LuaAfbEventMake},
{"evtpush" , LuaAfbEventPush},
+ {"getlabel" , LuaAfbGetLabel},
{NULL, NULL} /* sentinel */
};
// Load Lua Interpreter
-PUBLIC int LuaConfigLoad () {
-
+PUBLIC int LuaConfigLoad (AFB_ApiT apiHandle) {
+ static int luaLoaded=0;
+ // Lua loads only once
+ if (luaLoaded) return 0;
+ luaLoaded=1;
+
// open a new LUA interpretor
luaState = luaL_newstate();
if (!luaState) {
- AFB_ERROR ("LUA_INIT: Fail to open lua interpretor");
+ AFB_ApiError(apiHandle, "LUA_INIT: Fail to open lua interpretor");
goto OnErrorExit;
}
@@ -1004,6 +1095,15 @@ PUBLIC int LuaConfigLoad () {
luaL_newlib(luaState, afbFunction);
lua_setglobal(luaState, "AFB");
+ // initialise static magic for context
+ #ifndef CTX_MAGIC
+ CTX_MAGIC=CtlConfigMagicNew();
+ #endif
+
+ #ifndef TIMER_MAGIC
+ TIMER_MAGIC=CtlConfigMagicNew();
+ #endif
+
return 0;
OnErrorExit:
@@ -1011,17 +1111,9 @@ PUBLIC int LuaConfigLoad () {
}
// Create Binding Event at Init Exec Time
-PUBLIC int LuaConfigExec () {
+PUBLIC int LuaConfigExec (AFB_ApiT apiHandle) {
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];
@@ -1046,7 +1138,7 @@ PUBLIC int LuaConfigExec () {
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));
+ AFB_ApiError(apiHandle, "LUA-INIT HOOPs invalid config file path = %s", json_object_get_string(entryJ));
goto OnErrorExit;
}
@@ -1056,24 +1148,26 @@ PUBLIC int LuaConfigExec () {
strncat(filepath, filename, sizeof(filepath));
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));
+ 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_ERROR ("LUA-LOAD HOOPs Error in LUA exec scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
+ 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);
}
}
// 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_ApiWarning (apiHandle, "POLICY-INIT:WARNING (setenv CONTROL_LUA_PATH) No LUA '%s*.lua' in '%s'", fullprefix, dirList);
}
- AFB_DEBUG ("Audio control-LUA Init Done");
+ AFB_ApiDebug (apiHandle, "Audio control-LUA Init Done");
return 0;
OnErrorExit:
diff --git a/ctl-lib/ctl-lua.h b/ctl-lib/ctl-lua.h
index 6f2ce7d..53eb6cb 100644
--- a/ctl-lib/ctl-lua.h
+++ b/ctl-lib/ctl-lua.h
@@ -49,13 +49,6 @@
PUBLIC int LuaLibInit ();
-typedef int (*Lua2cFunctionT)(char *funcname, json_object *argsJ);
-typedef int (*Lua2cWrapperT) (lua_State* luaState, char *funcname, Lua2cFunctionT callback);
-
-#define CTLP_LUALOAD Lua2cWrapperT Lua2cWrap;
-#define CTLP_LUA2C(FuncName, label,argsJ, context) static int FuncName(char*label,json_object*argsJ);\
- int lua2c_ ## FuncName(lua_State* luaState){return((*Lua2cWrap)(luaState, MACRO_STR_VALUE(FuncName), FuncName, PLUGIN_NAME));};\
- static int FuncName(char* label, json_object* argsJ, void* context)
typedef enum {
LUA_DOCALL,
@@ -64,11 +57,11 @@ typedef enum {
} LuaDoActionT;
-PUBLIC int LuaConfigLoad();
-PUBLIC int LuaConfigExec();
+PUBLIC int LuaConfigLoad (AFB_ApiT apiHandle);
+PUBLIC int LuaConfigExec(AFB_ApiT apiHandle);
PUBLIC void LuaL2cNewLib(const char *label, luaL_Reg *l2cFunc, int count);
-PUBLIC int Lua2cWrapper(lua_State* luaState, char *funcname, Lua2cFunctionT callback);
-PUBLIC int LuaCallFunc (CtlActionT *action, json_object *queryJ) ;
+PUBLIC int Lua2cWrapper(void* luaHandle, char *funcname, Lua2cFunctionT callback);
+PUBLIC int LuaCallFunc (CtlSourceT *source, CtlActionT *action, json_object *queryJ) ;
PUBLIC void ctlapi_lua_docall (afb_req request);
PUBLIC void ctlapi_lua_dostring (afb_req request);
PUBLIC void ctlapi_lua_doscript (afb_req request);
diff --git a/ctl-lib/ctl-onload.c b/ctl-lib/ctl-onload.c
index 97bd109..1dec75a 100644
--- a/ctl-lib/ctl-onload.c
+++ b/ctl-lib/ctl-onload.c
@@ -23,29 +23,31 @@
#include "ctl-config.h"
// onload section receive one action or an array of actions
-PUBLIC int OnloadConfig(CtlSectionT *section, json_object *actionsJ) {
- CtlActionT *actions;
-
- // Load time parse actions in config file
+PUBLIC int OnloadConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *actionsJ) {
+
+ // Load time parse actions in control file
if (actionsJ != NULL) {
- actions= ActionLoad(actionsJ);
- section->handle=actions;
+ section->actions= ActionConfig(apiHandle, actionsJ, 0);
- if (!actions) {
- AFB_ERROR ("OnloadLoad config fail processing onload actions");
+ if (!section->actions) {
+ AFB_ApiError (apiHandle, "OnloadConfig control 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");
+ if (!section->actions) {
+ AFB_ApiError (apiHandle, "OnloadConfig Cannot Exec Non Existing Onload Action");
goto OnErrorExit;
}
- for (int idx=0; actions[idx].source.label != NULL; idx ++) {
- ActionExecOne(&actions[idx], NULL);
+ for (int idx=0; section->actions[idx].label != NULL; idx ++) {
+ CtlSourceT source;
+ source.label = section->actions[idx].label;
+ source.api = section->actions[idx].api;
+ source.request = AFB_ReqNone;
+
+ ActionExecOne(&source, &section->actions[idx], NULL);
}
}
diff --git a/ctl-lib/ctl-plugin.c b/ctl-lib/ctl-plugin.c
index f589035..03f4c34 100644
--- a/ctl-lib/ctl-plugin.c
+++ b/ctl-lib/ctl-plugin.c
@@ -26,20 +26,19 @@
static CtlPluginT *ctlPlugins=NULL;
-PUBLIC int PluginGetCB (CtlActionT *action , json_object *callbackJ) {
+PUBLIC int PluginGetCB (AFB_ApiT apiHandle, 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));
+ AFB_ApiError(apiHandle, "PluginGetCB plugin section missing cannot call '%s'", json_object_get_string(callbackJ));
goto OnErrorExit;
}
-
-
+
int err = wrap_json_unpack(callbackJ, "{ss,ss,s?s,s?o!}", "plugin", &plugin, "function", &function, "args", &argsJ);
if (err) {
- AFB_ERROR("PluginGet missing plugin|function|[args] in %s", json_object_get_string(callbackJ));
+ AFB_ApiError(apiHandle, "PluginGet missing plugin|function|[args] in %s", json_object_get_string(callbackJ));
goto OnErrorExit;
}
@@ -48,15 +47,16 @@ PUBLIC int PluginGetCB (CtlActionT *action , json_object *callbackJ) {
}
if (!ctlPlugins[idx].label) {
- AFB_ERROR ("PluginGetCB no plugin with label=%s", plugin);
+ AFB_ApiError(apiHandle, "PluginGetCB no plugin with label=%s", plugin);
goto OnErrorExit;
}
- action->actionCB = dlsym(ctlPlugins[idx].dlHandle, function);
- action->source.context = ctlPlugins[idx].context;
+ action->exec.cb.funcname = function;
+ action->exec.cb.callback = dlsym(ctlPlugins[idx].dlHandle, function);
+ action->exec.cb.plugin= &ctlPlugins[idx];
- if (!action->actionCB) {
- AFB_ERROR ("PluginGetCB no plugin=%s no function=%s", plugin, function);
+ if (!action->exec.cb.callback) {
+ AFB_ApiError(apiHandle, "PluginGetCB no plugin=%s no function=%s", plugin, function);
goto OnErrorExit;
}
return 0;
@@ -67,9 +67,9 @@ OnErrorExit:
}
// Wrapper to Lua2c plugin command add context and delegate to LuaWrapper
-STATIC int DispatchOneL2c(lua_State* luaState, char *funcname, Lua2cFunctionT callback) {
+STATIC int DispatchOneL2c(void* luaState, char *funcname, Lua2cFunctionT callback) {
#ifndef CONTROL_SUPPORT_LUA
- AFB_ERROR("CTL-ONE-L2C: LUA support not selected (cf:CONTROL_SUPPORT_LUA) in config.cmake");
+ fprintf(stderr, "CTL-ONE-L2C: LUA support not selected (cf:CONTROL_SUPPORT_LUA) in config.cmake");
return 1;
#else
int err=Lua2cWrapper(luaState, funcname, callback);
@@ -77,8 +77,8 @@ STATIC int DispatchOneL2c(lua_State* luaState, char *funcname, Lua2cFunctionT ca
#endif
}
-STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* handle) {
- json_object *lua2csJ = NULL, *actionsJ = NULL;
+STATIC int PluginLoadOne (AFB_ApiT apiHandle, CtlPluginT *ctlPlugin, json_object *pluginJ, void* handle) {
+ json_object *lua2csJ = NULL;
const char*ldSearchPath = NULL, *basename = NULL;
void *dlHandle;
@@ -86,12 +86,15 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
// 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);
+ int err = wrap_json_unpack(pluginJ, "{ss,s?s,s?s,s?s !}",
+ "label", &ctlPlugin->label, "info", &ctlPlugin->info, "ldpath", &ldSearchPath, "basename", &basename);
if (err) {
- AFB_ERROR("CTL-PLUGIN-LOADONE Plugin missing label|basename|version|[info]|[ldpath]|[lua2c]|[actions] in:\n-- %s", json_object_get_string(pluginJ));
+ AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Plugin missing label|[info]|[basename]|[ldpath] in:\n-- %s", json_object_get_string(pluginJ));
goto OnErrorExit;
}
+
+ // default basename equal label
+ if (!basename) basename=ctlPlugin->label;
// if search path not in Json config file, then try default
if (!ldSearchPath) ldSearchPath = CONTROL_PLUGIN_PATH;
@@ -99,7 +102,7 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
// 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);
+ AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Missing plugin=%s*%s (config ldpath?) search=\n-- %s", basename, CTL_PLUGIN_EXT, ldSearchPath);
goto OnErrorExit;
}
@@ -107,12 +110,12 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
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));
+ AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE HOOPs invalid plugin file path=\n-- %s", json_object_get_string(pluginPathJ));
goto OnErrorExit;
}
if (json_object_array_length(pluginPathJ) > 1) {
- AFB_WARNING("CTL-PLUGIN-LOADONE plugin multiple instances in searchpath will use %s/%s", fullpath, filename);
+ AFB_ApiWarning(apiHandle, "CTL-PLUGIN-LOADONE plugin multiple instances in searchpath will use %s/%s", fullpath, filename);
}
char pluginpath[CONTROL_MAXPATH_LEN];
@@ -121,24 +124,26 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
strncat(pluginpath, filename, sizeof (pluginpath));
dlHandle = dlopen(pluginpath, RTLD_NOW);
if (!dlHandle) {
- AFB_ERROR("CTL-PLUGIN-LOADONE Fail to load pluginpath=%s err= %s", pluginpath, dlerror());
+ AFB_ApiError(apiHandle, "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);
+ AFB_ApiError(apiHandle, "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);
+ AFB_ApiNotice(apiHandle, "CTL-PLUGIN-LOADONE %s successfully registered", ctlPluginMagic->label);
}
// store dlopen handle to enable onload action at exec time
ctlPlugin->dlHandle = dlHandle;
- // Jose hack to make verbosity visible from sharelib
+#ifndef AFB_BINDING_PREV3
+ // Jose hack to make verbosity visible from sharelib with API-V2
struct afb_binding_data_v2 *afbHidenData = dlsym(dlHandle, "afbBindingV2data");
if (afbHidenData) *afbHidenData = afbBindingV2data;
+#endif
// Push lua2cWrapper @ into plugin
Lua2cWrapperT *lua2cInPlug = dlsym(dlHandle, "Lua2cWrap");
@@ -156,7 +161,7 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
Lua2cFunctionT l2cFunction = (Lua2cFunctionT) dlsym(dlHandle, funcName);
if (!l2cFunction) {
- AFB_ERROR("CTL-PLUGIN-LOADONE symbol'%s' missing err=%s", funcName, dlerror());
+ AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE symbol'%s' missing err=%s", funcName, dlerror());
return 1;
}
l2cFunc[index].func = (void*) l2cFunction;
@@ -184,13 +189,14 @@ STATIC int PluginLoadOne (CtlPluginT *ctlPlugin, json_object *pluginJ, void* han
errCount = Lua2cAddOne(l2cFunc, l2cName, 0);
}
if (errCount) {
- AFB_ERROR("CTL-PLUGIN-LOADONE %d symbols not found in plugin='%s'", errCount, pluginpath);
+ AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE %d symbols not found in plugin='%s'", errCount, pluginpath);
goto OnErrorExit;
}
}
#endif
DispatchPluginInstallCbT ctlPluginOnload = dlsym(dlHandle, "CtlPluginOnload");
if (ctlPluginOnload) {
+ ctlPlugin->api = apiHandle;
ctlPlugin->context = (*ctlPluginOnload) (ctlPlugin, handle);
}
return 0;
@@ -200,7 +206,7 @@ OnErrorExit:
}
-PUBLIC int PluginConfig(CtlSectionT *section, json_object *pluginsJ) {
+PUBLIC int PluginConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *pluginsJ) {
int err=0;
if (json_object_get_type(pluginsJ) == json_type_array) {
@@ -208,11 +214,11 @@ PUBLIC int PluginConfig(CtlSectionT *section, json_object *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);
+ err += PluginLoadOne(apiHandle, &ctlPlugins[idx], pluginJ, section->handle);
}
} else {
ctlPlugins = calloc (2, sizeof(CtlPluginT));
- err += PluginLoadOne(&ctlPlugins[0], pluginsJ, section->handle);
+ err += PluginLoadOne(apiHandle, &ctlPlugins[0], pluginsJ, section->handle);
}
return err;
diff --git a/ctl-lib/ctl-plugin.h b/ctl-lib/ctl-plugin.h
index e0ab3dd..a678af4 100644
--- a/ctl-lib/ctl-plugin.h
+++ b/ctl-lib/ctl-plugin.h
@@ -20,9 +20,112 @@
#ifndef _CTL_PLUGIN_INCLUDE_
#define _CTL_PLUGIN_INCLUDE_
+
#define _GNU_SOURCE
#include <json-c/json.h>
+// Waiting for a clean AppFW-V3 API
+#ifdef USE_API_DYN
+ #define AFB_BINDING_VERSION dyn
+ #include <afb/afb-binding.h>
+
+ #define AFB_BINDING_PREV3
+ #define AFB_ReqNone NULL
+ typedef afb_request* AFB_ReqT;
+ typedef afb_dynapi* AFB_ApiT;
+
+ typedef afb_eventid* AFB_EventT;
+ #define AFB_EventIsValid(eventid) eventid
+ #define AFB_EventPush afb_eventid_push
+ #define AFB_ReqSubscribe afb_request_subscribe
+ #define AFB_EventMake(api, name) afb_dynapi_make_eventid(api, name)
+
+ #define AFB_ReqJson(request) afb_request_json(request)
+
+ #define AFB_ReqSucess afb_request_success
+ #define AFB_ReqSucessF afb_request_success_f
+ #define AFB_ReqFail afb_request_fail
+ #define AFB_ReqFailF afb_request_fail_f
+
+ #define AFB_ReqNotice(request, ...) AFB_REQUEST_NOTICE (request, __VA_ARGS__)
+ #define AFB_ReqWarning(request, ...) AFB_REQUEST_WARNING (request, __VA_ARGS__)
+ #define AFB_ReqDebug(request, ...) AFB_REQUEST_DEBUG (request, __VA_ARGS__)
+ #define AFB_ReqError(request, ...) AFB_REQUEST_ERROR (request, __VA_ARGS__)
+ #define AFB_ReqInfo(request, ...) AFB_REQUEST_INFO (request, __VA_ARGS__)
+
+ #define AFB_ApiVerbose(api, level, ...) afb_dynapi_verbose(api, level, __VA_ARGS__)
+ #define AFB_ApiNotice(api, ...) AFB_DYNAPI_NOTICE (api, __VA_ARGS__)
+ #define AFB_ApiWarning(api, ...) AFB_DYNAPI_WARNING (api, __VA_ARGS__)
+ #define AFB_ApiDebug(api, ...) AFB_DYNAPI_DEBUG (api, __VA_ARGS__)
+ #define AFB_ApiError(api, ...) AFB_DYNAPI_ERROR (api, __VA_ARGS__)
+ #define AFB_ApiInfo(api, ...) AFB_DYNAPI_INFO (api, __VA_ARGS__)
+
+ #define AFB_ReqIsValid(request) request
+ #define AFB_EvtIsValid(evtHandle) evtHandle
+
+ #define AFB_ServiceCall(api, ...) afb_dynapi_call(api, __VA_ARGS__)
+ #define AFB_ServiceSync(api, ...) afb_dynapi_call_sync(api, __VA_ARGS__)
+
+ #define AFB_RequireApi(api, ...) afb_dynapi_require_api(api, __VA_ARGS__)
+
+ #define AFB_GetEventLoop(api) afb_dynapi_get_event_loop(api)
+
+
+ typedef struct {
+ const char *verb; /* name of the verb, NULL only at end of the array */
+ void (*callback)(AFB_ReqT req); /* callback function implementing the verb */
+ const struct afb_auth *auth; /* required authorisation, can be NULL */
+ const char *info; /* some info about the verb, can be NULL */
+ uint32_t session;
+ } AFB_ApiVerbs;
+
+#else
+ #define AFB_BINDING_VERSION 2
+ #include <afb/afb-binding.h>
+
+ typedef afb_req AFB_ReqT;
+ typedef void* AFB_ApiT;
+ #define AFB_ReqNone (struct afb_req){0,0}
+
+ typedef afb_event AFB_EventT;
+ #define AFB_EventPush afb_event_push
+ #define AFB_ReqSubscribe afb_req_subscribe
+ #define AFB_EventIsValid(event) afb_event_is_valid(event)
+ #define AFB_EventMake(api, name) afb_daemon_make_event(name)
+
+ #define AFB_ReqJson(request) afb_req_json(request)
+ #define AFB_ReqSucess afb_req_success
+ #define AFB_ReqSucessF afb_req_success_f
+ #define AFB_ReqFail afb_req_fail
+ #define AFB_ReqFailF afb_req_fail_f
+
+ #define AFB_ReqNotice(request, ...) AFB_NOTICE (__VA_ARGS__)
+ #define AFB_ReqWarning(request, ...) AFB_WARNING (__VA_ARGS__)
+ #define AFB_ReqDebug(request, ...) AFB_DEBUG (__VA_ARGS__)
+ #define AFB_ReqError(request, ...) AFB_ERROR (__VA_ARGS__)
+ #define AFB_ReqInfo(request, ...) AFB_INFO (__VA_ARGS__)
+
+ #define AFB_ApiVerbose(api, level, ...) afb_daemon_verbose_v2(level,__VA_ARGS__)
+ #define AFB_ApiNotice(api, ...) AFB_NOTICE (__VA_ARGS__)
+ #define AFB_ApiWarning(api, ...) AFB_WARNING (__VA_ARGS__)
+ #define AFB_ApiDebug(api, ...) AFB_DEBUG (__VA_ARGS__)
+ #define AFB_ApiError(api, ...) AFB_ERROR (__VA_ARGS__)
+ #define AFB_ApiInfo(api, ...) AFB_INFO (__VA_ARGS__)
+
+ #define AFB_ReqIsValid(request) afb_req_is_valid(request)
+ #define AFB_EvtIsValid(evtHandle) afb_event_is_valid(evtHandle)
+
+ #define AFB_ServiceCall(api, ...) afb_service_call(__VA_ARGS__)
+ #define AFB_ServiceSync(api, ...) afb_service_call_sync(__VA_ARGS__)
+
+ #define AFB_RequireApi (api, ...) afb_daemon_require_api(__VA_ARGS__)
+
+ #define AFB_GetEventLoop(api) afb_daemon_get_event_loop()
+
+ #define AFB_ApiVerbs afb_verb_v2
+#endif
+
+
#ifndef CTL_PLUGIN_MAGIC
#define CTL_PLUGIN_MAGIC 852369147
#endif
@@ -40,35 +143,76 @@
#define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x
#endif
-typedef struct {
- char *label;
- char *info;
- afb_req request;
- void *context;
-} CtlSourceT;
-
+
typedef struct {
- long magic;
- char *label;
- void *handle;
+ const char *label;
+ const long magic;
} CtlPluginMagicT;
+typedef struct {
+ const char *label;
+ const char *info;
+ AFB_ApiT api;
+ void *dlHandle;
+ void *context;
+} CtlPluginT;
+
+
+typedef enum {
+ CTL_TYPE_NONE=0,
+ CTL_TYPE_API,
+ CTL_TYPE_CB,
+ CTL_TYPE_LUA,
+} CtlActionTypeT;
typedef struct {
const char *label;
- const char *info;
- const char *version;
+ AFB_ApiT api;
+ AFB_ReqT request;
void *context;
- void *dlHandle;
-} CtlPluginT;
+} CtlSourceT;
+
+typedef struct {
+ const char *label;
+ const char *info;
+ AFB_ApiT api;
+ json_object *argsJ;
+ CtlActionTypeT type;
+ union {
+ struct {
+ const char* api;
+ const char* verb;
+ } subcall;
+
+ struct {
+ const char* load;
+ const char* funcname;
+ } lua;
+
+ struct {
+ const char* funcname;
+ int (*callback)(CtlSourceT *source, json_object *argsJ, json_object *queryJ);
+ CtlPluginT *plugin;
+ } cb;
+ } exec;
+} CtlActionT;
-typedef void*(*DispatchPluginInstallCbT)(CtlPluginT *plugin, void* handle);
+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}; struct afb_binding_data_v2;
+#define CTLP_CAPI_REGISTER(pluglabel) CtlPluginMagicT CtlPluginMagic={.magic=CTL_PLUGIN_MAGIC,.label=pluglabel}; struct afb_binding_data_v2;
#define CTLP_ONLOAD(plugin, handle) void* CtlPluginOnload(CtlPluginT *plugin, void* handle)
#define CTLP_CAPI(funcname, source, argsJ, queryJ) int funcname(CtlSourceT *source, json_object* argsJ, json_object* queryJ)
+// LUA2c Wrapper macro. Allows to call C code from Lua script
+typedef int (*Lua2cFunctionT)(CtlSourceT *source, json_object *argsJ, json_object **responseJ);
+typedef int (*Lua2cWrapperT) (void*luaHandle, char *funcname, Lua2cFunctionT callback);
+
+#define CTLP_LUA_REGISTER(pluglabel) Lua2cWrapperT Lua2cWrap; CTLP_CAPI_REGISTER(pluglabel);
+#define CTLP_LUA2C(funcname, source, argsJ, responseJ) static int funcname (CtlSourceT* source, json_object* argsJ, json_object** responseJ);\
+ int lua2c_ ## funcname (void* luaState){return((*Lua2cWrap)(luaState, MACRO_STR_VALUE(funcname), funcname));};\
+ static int funcname (CtlSourceT* source, json_object* argsJ, json_object** responseJ)
+
#endif /* _CTL_PLUGIN_INCLUDE_ */ \ No newline at end of file
diff --git a/ctl-lib/ctl-timer.c b/ctl-lib/ctl-timer.c
index 1de6f99..81aa984 100644
--- a/ctl-lib/ctl-timer.c
+++ b/ctl-lib/ctl-timer.c
@@ -30,7 +30,6 @@ typedef struct {
const char *label;
} AutoTestCtxT;
-static afb_event afbevt;
STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
TimerHandleT *timerHandle = (TimerHandleT*) handle;
@@ -41,12 +40,13 @@ STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
timerHandle->count --;
if (timerHandle->count == 0) {
sd_event_source_unref(source);
+ if (timerHandle->freeCB) timerHandle->freeCB(timerHandle->context);
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_now(AFB_GetEventLoop(timerHandle->api), CLOCK_MONOTONIC, &usec);
sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
sd_event_source_set_time(source, usec + timerHandle->delay*1000);
}
@@ -57,7 +57,7 @@ STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
return 0;
OnErrorExit:
- AFB_WARNING("TimerNext Callback Fail Tag=%s", timerHandle->label);
+ AFB_ApiWarning(timerHandle->api, "TimerNext Callback Fail Tag=%s", timerHandle->label);
return -1;
}
@@ -68,34 +68,24 @@ PUBLIC void TimerEvtStop(TimerHandleT *timerHandle) {
}
-PUBLIC void TimerEvtStart(TimerHandleT *timerHandle, timerCallbackT callback, void *context) {
+PUBLIC void TimerEvtStart(AFB_ApiT apiHandle, TimerHandleT *timerHandle, timerCallbackT callback, void *context) {
uint64_t usec;
// populate CB handle
timerHandle->callback=callback;
timerHandle->context=context;
+ timerHandle->api=apiHandle;
// 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);
-}
-
-PUBLIC afb_event TimerEvtGet(void) {
- return afbevt;
+ sd_event_now(AFB_GetEventLoop(apiHandle), CLOCK_MONOTONIC, &usec);
+ sd_event_add_time(AFB_GetEventLoop(apiHandle), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay*1000, 250, TimerNext, timerHandle);
}
// Create Binding Event at Init
-PUBLIC 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;
- }
+PUBLIC int TimerEvtInit (AFB_ApiT apiHandle) {
- AFB_DEBUG ("Audio Control-Events Init Done");
+ AFB_ApiDebug (apiHandle, "Timer-Init Done");
return 0;
}
diff --git a/ctl-lib/ctl-timer.h b/ctl-lib/ctl-timer.h
index b08299f..ced0417 100644
--- a/ctl-lib/ctl-timer.h
+++ b/ctl-lib/ctl-timer.h
@@ -26,17 +26,19 @@
typedef int (*timerCallbackT)(void *context);
typedef struct TimerHandleS {
+ int magic;
int count;
int delay;
const char*label;
void *context;
timerCallbackT callback;
sd_event_source *evtSource;
+ AFB_ApiT api;
+ timerCallbackT freeCB;
} TimerHandleT;
-PUBLIC int TimerEvtInit (void);
-PUBLIC afb_event TimerEvtGet(void);
-PUBLIC void TimerEvtStart(TimerHandleT *timerHandle, timerCallbackT callback, void *context);
+PUBLIC int TimerEvtInit (AFB_ApiT apiHandle);
+PUBLIC void TimerEvtStart(AFB_ApiT apiHandle, TimerHandleT *timerHandle, timerCallbackT callback, void *context);
PUBLIC void TimerEvtStop(TimerHandleT *timerHandle);
#endif // CTL_TIMER_INCLUDE