summaryrefslogtreecommitdiffstats
path: root/ctl-lib
diff options
context:
space:
mode:
authorFulup Ar Foll <fulup@iot.bzh>2017-10-24 22:17:59 +0200
committerRomain Forlot <romain.forlot@iot.bzh>2018-12-13 15:02:54 +0100
commit67d50c819ea60b00a3441d446ce6719ec3bf2349 (patch)
tree158e6d4920cd460ccafbdaa1cee97738242daec6 /ctl-lib
parent2b77a50d5c578d92ac692b872f5a51c227c29334 (diff)
First working version as submodule
Diffstat (limited to 'ctl-lib')
-rw-r--r--ctl-lib/ctl-action.c45
-rw-r--r--ctl-lib/ctl-config.c17
-rw-r--r--ctl-lib/ctl-config.h4
-rw-r--r--ctl-lib/ctl-control.c1
-rw-r--r--ctl-lib/ctl-event.c10
-rw-r--r--ctl-lib/ctl-lua.c258
-rw-r--r--ctl-lib/ctl-lua.h4
-rw-r--r--ctl-lib/ctl-onload.c4
-rw-r--r--ctl-lib/ctl-plugin.c18
-rw-r--r--ctl-lib/ctl-plugin.h29
-rw-r--r--ctl-lib/ctl-timer.c4
-rw-r--r--ctl-lib/ctl-timer.h2
12 files changed, 283 insertions, 113 deletions
diff --git a/ctl-lib/ctl-action.c b/ctl-lib/ctl-action.c
index fa0fa6f..10eba09 100644
--- a/ctl-lib/ctl-action.c
+++ b/ctl-lib/ctl-action.c
@@ -26,8 +26,8 @@
PUBLIC int ActionLabelToIndex(CtlActionT*actions, const char* actionLabel) {
- for (int idx = 0; actions[idx].label; idx++) {
- if (!strcasecmp(actionLabel, actions[idx].label)) return idx;
+ for (int idx = 0; actions[idx].uid; idx++) {
+ if (!strcasecmp(actionLabel, actions[idx].uid)) return idx;
}
return -1;
}
@@ -58,11 +58,11 @@ PUBLIC void ActionExecOne(CtlSourceT *source, CtlActionT* action, json_object *q
}
}
- json_object_object_add(queryJ, "label", json_object_new_string(source->label));
+ json_object_object_add(queryJ, "uid", json_object_new_string(source->uid));
int err = AFB_ServiceSync(action->api, action->exec.subcall.api, action->exec.subcall.verb, queryJ, &returnJ);
if (err) {
- 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));
+ AFB_ApiError(action->api, "ActionExecOne(AppFw) uid=%s api=%s verb=%s args=%s", source->uid, action->exec.subcall.api, action->exec.subcall.verb, json_object_get_string(action->argsJ));
}
break;
}
@@ -71,7 +71,7 @@ PUBLIC void ActionExecOne(CtlSourceT *source, CtlActionT* action, json_object *q
case CTL_TYPE_LUA:
err = LuaCallFunc(source, action, queryJ);
if (err) {
- AFB_ApiError(action->api, "ActionExecOne(Lua) label=%s func=%s args=%s", source->label, action->exec.lua.funcname, json_object_get_string(action->argsJ));
+ AFB_ApiError(action->api, "ActionExecOne(Lua) uid=%s func=%s args=%s", source->uid, action->exec.lua.funcname, json_object_get_string(action->argsJ));
}
break;
#endif
@@ -79,13 +79,13 @@ PUBLIC void ActionExecOne(CtlSourceT *source, CtlActionT* action, json_object *q
case CTL_TYPE_CB:
err = (*action->exec.cb.callback) (source, action->argsJ, queryJ);
if (err) {
- 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));
+ AFB_ApiError(action->api, "ActionExecOne(Callback) uid%s plugin=%s function=%s args=%s", source->uid, action->exec.cb.plugin->uid, action->exec.cb.funcname, json_object_get_string(action->argsJ));
}
break;
default:
{
- AFB_ApiError(action->api, "ActionExecOne(unknown) API type label=%s", source->label);
+ AFB_ApiError(action->api, "ActionExecOne(unknown) API type uid=%s", source->uid);
break;
}
}
@@ -101,7 +101,7 @@ STATIC void ActionDynRequest (AFB_ReqT request) {
CtlActionT* action = (CtlActionT*)afb_request_get_vcbdata(request);
CtlSourceT source;
- source.label = action->label;
+ source.uid = action->uid;
source.request = request;
source.api = action->api;
@@ -116,10 +116,10 @@ PUBLIC int ActionLoadOne(AFB_ApiT apiHandle, CtlActionT *action, json_object *ac
int err, modeCount = 0;
json_object *callbackJ=NULL, *luaJ=NULL, *subcallJ=NULL;
- 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);
+ err = wrap_json_unpack(actionJ, "{ss,s?s,s?s,s?o,s?o,s?o,s?o !}"
+ , "uid", &action->uid, "info", &action->info, "privileges", &action->privileges, "callback", &callbackJ, "lua", &luaJ, "subcall", &subcallJ, "args", &action->argsJ);
if (err) {
- AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Action missing label|[info]|[callback]|[lua]|[subcall]|[args] in:\n-- %s", json_object_get_string(actionJ));
+ AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Action missing uid|[info]|[callback]|[lua]|[subcall]|[args] in:\n-- %s", json_object_get_string(actionJ));
goto OnErrorExit;
}
@@ -129,9 +129,9 @@ PUBLIC int ActionLoadOne(AFB_ApiT apiHandle, CtlActionT *action, json_object *ac
// 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);
+ err = afb_dynapi_add_verb(apiHandle, action->uid, action->info, ActionDynRequest, action, NULL, 0);
if (err) {
- AFB_ApiError(apiHandle,"ACTION-LOAD-ONE fail to register API verb=%s", action->label);
+ AFB_ApiError(apiHandle,"ACTION-LOAD-ONE fail to register API verb=%s", action->uid);
goto OnErrorExit;
}
action->api = apiHandle;
@@ -140,11 +140,22 @@ PUBLIC int ActionLoadOne(AFB_ApiT apiHandle, CtlActionT *action, json_object *ac
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;
+ switch (json_object_get_type(luaJ)) {
+ case json_type_object:
+ err = wrap_json_unpack(luaJ, "{s?s,s:s !}", "load", &action->exec.lua.load, "func", &action->exec.lua.funcname);
+ if (err) {
+ AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Lua action missing [load]|func in:\n-- %s", json_object_get_string(luaJ));
+ goto OnErrorExit;
+ }
+ break;
+ case json_type_string:
+ action->exec.lua.funcname = json_object_get_string(luaJ);
+ break;
+ default:
+ AFB_ApiError(apiHandle,"ACTION-LOAD-ONE Lua action invalid syntax in:\n-- %s", json_object_get_string(luaJ));
+ goto OnErrorExit;
}
}
diff --git a/ctl-lib/ctl-config.c b/ctl-lib/ctl-config.c
index 2b5d345..9b04df6 100644
--- a/ctl-lib/ctl-config.c
+++ b/ctl-lib/ctl-config.c
@@ -108,13 +108,19 @@ PUBLIC int CtlConfigExec(AFB_ApiT apiHandle, CtlConfigT *ctlConfig) {
}
#ifdef CONTROL_SUPPORT_LUA
- int err= LuaConfigExec(apiHandle);
+ int err= LuaConfigExec(apiHandle, ctlConfig->api);
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++) {
+
+ if (!ctlConfig->sections[idx].actions) {
+ AFB_ApiNotice(apiHandle, "CtlConfigLoad: notice empty section '%s'", ctlConfig->sections[idx].key);
+ continue;
+ }
+
errcount += ctlConfig->sections[idx].loadCB(apiHandle, &ctlConfig->sections[idx], NULL);
}
return errcount;
@@ -141,10 +147,10 @@ PUBLIC CtlConfigT *CtlLoadMetaData(AFB_ApiT apiHandle, const char* filepath) {
int done = json_object_object_get_ex(ctlConfigJ, "metadata", &metadataJ);
if (done) {
ctlHandle = calloc(1, sizeof (CtlConfigT));
- err = wrap_json_unpack(metadataJ, "{ss,ss,ss,s?s,s?o !}", "label", &ctlHandle->label, "version", &ctlHandle->version
+ err = wrap_json_unpack(metadataJ, "{ss,ss,ss,s?s,s?o !}", "uid", &ctlHandle->uid, "version", &ctlHandle->version
, "api", &ctlHandle->api, "info", &ctlHandle->info, "require", &ctlHandle->requireJ);
if (err) {
- AFB_ApiError(apiHandle, "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 uid|api|version|[info]|[require] in:\n-- %s", json_object_get_string(metadataJ));
goto OnErrorExit;
}
}
@@ -170,10 +176,7 @@ PUBLIC int CtlLoadSections(AFB_ApiT apiHandle, CtlConfigT *ctlHandle, CtlSection
for (int idx = 0; sections[idx].key != NULL; idx++) {
json_object * sectionJ;
int done = json_object_object_get_ex(ctlHandle->configJ, sections[idx].key, &sectionJ);
- if (!done) {
- AFB_ApiError(apiHandle, "CtlConfigLoad: fail to find '%s' section in config '%s'", sections[idx].key, ctlHandle->label);
- err++;
- } else {
+ if (done) {
err += sections[idx].loadCB(apiHandle, &sections[idx], sectionJ);
}
}
diff --git a/ctl-lib/ctl-config.h b/ctl-lib/ctl-config.h
index 09c573f..31b31d2 100644
--- a/ctl-lib/ctl-config.h
+++ b/ctl-lib/ctl-config.h
@@ -41,7 +41,7 @@
typedef struct ConfigSectionS {
const char *key;
- const char *label;
+ const char *uid;
const char *info;
int (*loadCB)(AFB_ApiT apihandle, struct ConfigSectionS *section, json_object *sectionJ);
void *handle;
@@ -50,7 +50,7 @@ typedef struct ConfigSectionS {
typedef struct {
const char* api;
- const char* label;
+ const char* uid;
const char *info;
const char *version;
json_object *configJ;
diff --git a/ctl-lib/ctl-control.c b/ctl-lib/ctl-control.c
index 117f5b5..2248756 100644
--- a/ctl-lib/ctl-control.c
+++ b/ctl-lib/ctl-control.c
@@ -34,7 +34,6 @@ PUBLIC int ControlConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *
goto OnErrorExit;
}
}
-
return 0;
OnErrorExit:
diff --git a/ctl-lib/ctl-event.c b/ctl-lib/ctl-event.c
index b9be1c7..62632e6 100644
--- a/ctl-lib/ctl-event.c
+++ b/ctl-lib/ctl-event.c
@@ -35,13 +35,13 @@ PUBLIC void CtrlDispatchApiEvent (AFB_ApiT apiHandle, const char *evtLabel, stru
int index= ActionLabelToIndex(actions, evtLabel);
if (index < 0) {
- AFB_ApiWarning(apiHandle, "CtlDispatchEvent: fail to find label=%s in action event section", evtLabel);
+ AFB_ApiWarning(apiHandle, "CtlDispatchEvent: fail to find uid=%s in action event section", evtLabel);
return;
}
// create a dummy source for action
CtlSourceT source;
- source.label = actions[index].label;
+ source.uid = actions[index].uid;
source.api = actions[index].api;
source.request = NULL;
@@ -59,12 +59,12 @@ PUBLIC void CtrlDispatchV2Event(const char *evtLabel, json_object *eventJ) {
int index= ActionLabelToIndex(actions, evtLabel);
if (index < 0) {
- AFB_WARNING ("CtlDispatchEvent: fail to find label=%s in action event section", evtLabel);
+ AFB_WARNING ("CtlDispatchEvent: fail to find uid=%s in action event section", evtLabel);
return;
}
CtlSourceT source;
- source.label = actions[index].label;
+ source.uid = actions[index].uid;
source.api = actions[index].api;
source.request = AFB_ReqNone;
@@ -78,7 +78,7 @@ PUBLIC int EventConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *ac
// Load time parse actions in config file
if (actionsJ != NULL) {
- section->actions= ActionConfig(apiHandle, actionsJ, 1);
+ section->actions= ActionConfig(apiHandle, actionsJ, 0);
if (!section->actions) {
AFB_ApiError (apiHandle, "EventLoad config fail processing onload actions");
diff --git a/ctl-lib/ctl-lua.c b/ctl-lib/ctl-lua.c
index 2aaaabb..1db0ed3 100644
--- a/ctl-lib/ctl-lua.c
+++ b/ctl-lib/ctl-lua.c
@@ -64,13 +64,11 @@ typedef struct {
} LuaCbHandleT;
-
/*
* 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 CtlSourceT *LuaSourcePop (lua_State *luaState, int index) {
LuaAfbSourceT *afbSource;
luaL_checktype(luaState, index, LUA_TLIGHTUSERDATA);
@@ -269,26 +267,7 @@ static json_object *LuaPopArgs (CtlSourceT *source, lua_State* luaState, int sta
- /*
- * '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) {
+STATIC int LuaFormatMessage(lua_State* luaState, int verbosity, int level) {
char *message;
CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
@@ -297,9 +276,9 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbLevelT level) {
// if log level low then silently ignore message
#ifdef AFB_BINDING_PREV3
- if(source->api->verbosity < level) return 0;
+ if(source->api->verbosity < verbosity) return 0;
#else
- if(afb_get_verbosity() < level) return 0;
+ if(afb_get_verbosity() < verbosity) return 0;
#endif
json_object *responseJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
@@ -347,7 +326,7 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbLevelT level) {
break;
case 'A':
- targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"level: %s", source->label);
+ targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"level: %s", source->uid);
break;
case 's':
@@ -371,7 +350,7 @@ STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbLevelT level) {
PrintMessage:
// TBD: __file__ and __line__ should match LUA source code
- AFB_ApiVerbose(source->api, level,__FILE__,__LINE__,source->label, message);
+ AFB_ApiVerbose(source->api, level,__FILE__,__LINE__,source->uid, message);
return 0; // nothing return to lua
OnErrorExit: // on argument to return (the error message)
@@ -380,27 +359,27 @@ PrintMessage:
STATIC int LuaPrintInfo(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_INFO);
+ int err=LuaFormatMessage (luaState, AFB_VERBOSITY_LEVEL_INFO, _AFB_SYSLOG_LEVEL_INFO_);
return err;
}
STATIC int LuaPrintError(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_DEBUG);
+ int err=LuaFormatMessage (luaState, AFB_VERBOSITY_LEVEL_ERROR, _AFB_SYSLOG_LEVEL_ERROR_);
return err; // no value return
}
STATIC int LuaPrintWarning(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_WARNING);
+ int err=LuaFormatMessage (luaState, AFB_VERBOSITY_LEVEL_WARNING, _AFB_SYSLOG_LEVEL_WARNING_);
return err;
}
STATIC int LuaPrintNotice(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_NOTICE);
+ int err=LuaFormatMessage (luaState, AFB_VERBOSITY_LEVEL_NOTICE, _AFB_SYSLOG_LEVEL_NOTICE_);
return err;
}
STATIC int LuaPrintDebug(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_ERROR);
+ int err=LuaFormatMessage (luaState, AFB_VERBOSITY_LEVEL_DEBUG, _AFB_SYSLOG_LEVEL_DEBUG_);
return err;
}
@@ -428,7 +407,7 @@ STATIC int LuaAfbFail(lua_State* luaState) {
json_object *responseJ= LuaPopArgs(source, luaState, LUA_FIST_ARG+1);
if (responseJ == JSON_ERROR) return 1;
- AFB_ReqFail(source->request, source->label, json_object_get_string(responseJ));
+ AFB_ReqFail(source->request, source->uid, json_object_get_string(responseJ));
return 0;
@@ -443,16 +422,21 @@ STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *respo
lua_getglobal(luaState, handleCb->callback);
- // push error status & response
- lua_pushboolean(luaState, iserror);
+ // Push AFB client context on the stack
+ if (iserror) handleCb->source->status = CTL_STATUS_ERR;
+ else handleCb->source->status = CTL_STATUS_DONE;
+ LuaSourcePush(luaState, handleCb->source);
+
+ // push response
count+= LuaPushArgument(handleCb->source, responseJ);
- count+= LuaPushArgument(handleCb->source, handleCb->context);
+ if (handleCb->context) count+= LuaPushArgument(handleCb->source, handleCb->context);
int err=lua_pcall(luaState, count, LUA_MULTRET, 0);
if (err) {
- AFB_ApiError(apiHandle, "LUA-SERICE-CB:FAIL response=%s err=%s", json_object_get_string(responseJ), lua_tostring(luaState,-1) );
+ AFB_ApiError(apiHandle, "LUA-SERVICE-CB:FAIL response=%s err=%s", json_object_get_string(responseJ), lua_tostring(luaState,-1) );
}
+ free (handleCb->source);
free (handleCb);
}
@@ -467,8 +451,8 @@ STATIC int LuaAfbService(lua_State* luaState) {
}
// note: argument start at 2 because of AFB: table
- 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]})");
+ if (count <6 || !lua_isstring(luaState, 3) || !lua_isstring(luaState, 4) || !lua_isstring(luaState, 6)) {
+ lua_pushliteral (luaState, "ERROR: syntax AFB:service(source, api, verb, {[Lua Table]})");
goto OnErrorExit;
}
@@ -480,7 +464,11 @@ STATIC int LuaAfbService(lua_State* luaState) {
LuaCbHandleT *handleCb = calloc (1, sizeof(LuaCbHandleT));
handleCb->callback= lua_tostring(luaState, 6);
- handleCb->context = LuaPopArgs(source, luaState, 7);
+ handleCb->context = LuaPopArgs(source, luaState, 7);
+
+ // source need to be duplicate because request return free it
+ handleCb->source = malloc(sizeof(CtlSourceT));
+ handleCb->source = memcpy (handleCb->source, source, sizeof(CtlSourceT));
AFB_ServiceCall(source->api, api, verb, queryJ, LuaAfbServiceCB, handleCb);
@@ -502,16 +490,16 @@ STATIC int LuaAfbServiceSync(lua_State* luaState) {
}
// note: argument start at 2 because of AFB: table
- if (count <4 || !lua_isstring(luaState, 3) || !lua_isstring(luaState, 4) || !lua_istable(luaState, 5)) {
+ if (count != 5 || !lua_isstring(luaState, LUA_FIST_ARG+1) || !lua_isstring(luaState, LUA_FIST_ARG+2) || !lua_istable(luaState, LUA_FIST_ARG+3)) {
lua_pushliteral (luaState, "ERROR: syntax AFB:servsync(api, verb, {[Lua Table]})");
goto OnErrorExit;
}
// 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);
+ const char *api = lua_tostring(luaState,LUA_FIST_ARG+1);
+ const char *verb= lua_tostring(luaState,LUA_FIST_ARG+2);
+ json_object *queryJ= LuaTableToJson(source, luaState, LUA_FIST_ARG+3);
int iserror=AFB_ServiceSync(source->api, api, verb, queryJ, &responseJ);
@@ -639,7 +627,7 @@ STATIC int LuaAfbEventMake(lua_State* luaState) {
return 1;
}
-STATIC int LuaAfbGetLabel (lua_State* luaState) {
+STATIC int LuaAfbGetUid (lua_State* luaState) {
CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
if (!source) {
@@ -648,7 +636,24 @@ STATIC int LuaAfbGetLabel (lua_State* luaState) {
}
// extract and return afbSource from timer handle
- lua_pushstring(luaState, source->label);
+ lua_pushstring(luaState, source->uid);
+
+ return 1; // return argument
+
+OnErrorExit:
+ return 0;
+}
+
+STATIC int LuaAfbGetStatus (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_pushinteger(luaState, source->status);
return 1; // return argument
@@ -911,7 +916,7 @@ STATIC int LuaTimerClear (lua_State* luaState) {
if (!timerHandle) goto OnErrorExit;
LuaCbHandleT *luaCbHandle = (LuaCbHandleT*) timerHandle->context;
- AFB_ApiNotice (luaCbHandle->source->api,"LuaTimerClear timer=%s", timerHandle->label);
+ AFB_ApiNotice (luaCbHandle->source->api,"LuaTimerClear timer=%s", timerHandle->uid);
TimerEvtStop(timerHandle);
return 0; //happy end
@@ -928,7 +933,7 @@ STATIC int LuaTimerGet (lua_State* luaState) {
// 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,"uid", json_object_new_string(timerHandle->uid));
json_object_object_add(responseJ,"delay", json_object_new_int(timerHandle->delay));
json_object_object_add(responseJ,"count", json_object_new_int(timerHandle->count));
@@ -964,7 +969,6 @@ STATIC int LuaTimerSetCB (void *handle) {
int err=lua_pcall(luaState, count, LUA_MULTRET, 0);
if (err) {
- 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;
}
@@ -991,7 +995,7 @@ STATIC int LuaTimerCtxFree(void *handle) {
}
STATIC int LuaTimerSet(lua_State* luaState) {
- const char *label=NULL, *info=NULL;
+ const char *uid=NULL, *info=NULL;
int delay=0, count=0;
// Get source handle
@@ -1007,9 +1011,9 @@ STATIC int LuaTimerSet(lua_State* luaState) {
goto OnErrorExit;
}
- int err = wrap_json_unpack(timerJ, "{ss, s?s si, si !}", "label", &label, "info", &info, "delay", &delay, "count", &count);
+ int err = wrap_json_unpack(timerJ, "{ss, s?s si, si !}", "uid", &uid, "info", &info, "delay", &delay, "count", &count);
if (err) {
- lua_pushliteral(luaState, "LuaTimerSet-Syntax timerT={label:xxx delay:ms, count:xx}");
+ lua_pushliteral(luaState, "LuaTimerSet-Syntax timerT={uid:xxx delay:ms, count:xx}");
goto OnErrorExit;
}
@@ -1025,7 +1029,7 @@ STATIC int LuaTimerSet(lua_State* luaState) {
timerHandle->magic= TIMER_MAGIC;
timerHandle->delay=delay;
timerHandle->count=count;
- timerHandle->label=label;
+ timerHandle->uid=uid;
timerHandle->freeCB=LuaTimerCtxFree;
// fire timer
@@ -1043,13 +1047,146 @@ OnErrorExit:
return 1; // return error code
}
+typedef struct {
+ const char *callback;
+ json_object *clientCtxJ;
+ CtlSourceT *source;
+} LuaClientCtxT;
+
+
+STATIC void *LuaClientCtxNew (void * handle) {
+
+ LuaClientCtxT *clientCtx = (LuaClientCtxT*) handle;
+ int count=1;
+
+ // push callback and client context on Lua stack
+ lua_getglobal(luaState, clientCtx->callback);
+
+ // let's Lua script know about new/free
+ clientCtx->source->status = CTL_STATUS_DONE;
+
+ // Push AFB client context on the stack
+ LuaAfbSourceT *afbSource= LuaSourcePush(luaState, clientCtx->source);
+ if (!afbSource) goto OnErrorExit;
+
+ // Push user Context
+ count+= LuaPushArgument(clientCtx->source, clientCtx->clientCtxJ);
+
+ int err=lua_pcall(luaState, count, 1, 0);
+ if (err) {
+ AFB_ApiError (clientCtx->source->api,"LuaClientCtxNew:FAIL response=%s err=%s", json_object_get_string(clientCtx->clientCtxJ), lua_tostring(luaState,-1));
+ goto OnErrorExit;
+ }
+
+ // If function return an error status then free client context
+ if (lua_tointeger(luaState, -1)) {
+ free (clientCtx);
+ goto OnErrorExit;
+ }
+
+ return handle; // By default we are happy
+
+OnErrorExit:
+ return NULL;
+
+}
+
+STATIC void LuaClientCtxFree (void * handle) {
+
+ LuaClientCtxT *clientCtx = (LuaClientCtxT*) handle;
+ int count=1;
+
+ if (!handle) return;
+
+ // let's Lua script know about new/free
+ lua_getglobal(luaState, clientCtx->callback);
+
+ // set source status to notify lua script about free
+ clientCtx->source->status = CTL_STATUS_FREE;
+
+ // Push AFB client context on the stack
+ LuaAfbSourceT *afbSource= LuaSourcePush(luaState, clientCtx->source);
+ if (!afbSource) goto OnErrorExit;
+
+ // Push user Context
+ count+= LuaPushArgument(clientCtx->source, clientCtx->clientCtxJ);
+
+ int err=lua_pcall(luaState, count, LUA_MULTRET, 0);
+ if (err) {
+ AFB_ApiError (clientCtx->source->api,"LuaClientCtxFree:FAIL response=%s err=%s", json_object_get_string(clientCtx->clientCtxJ), lua_tostring(luaState,-1));
+ goto OnErrorExit;
+ }
+
+ // If function return an error status then free client context
+ if (lua_toboolean(luaState, -1)) {
+ free (clientCtx);
+ goto OnErrorExit;
+ }
+
+ return; // No return status
+
+OnErrorExit:
+ return;
+
+}
+
+// set a context that will be free when WS is closed
+STATIC int LuaClientCtx(lua_State* luaState) {
+
+ // Get source handle
+ CtlSourceT *source= LuaSourcePop(luaState, LUA_FIST_ARG);
+ if (!source) goto OnErrorExit;
+
+ if (!AFB_ReqIsValid (source->request)) {
+ lua_pushliteral(luaState, "LuaSessionSet-Syntax should be called within client request context");
+ goto OnErrorExit;
+ }
+
+ // in only one arg then we should free the clientCtx
+ if (lua_gettop(luaState) == LUA_FIST_ARG) {
+ AFB_ClientCtxClear(source->request);
+ goto OnSuccessExit;
+ }
+
+ const char *callback = lua_tostring(luaState, LUA_FIST_ARG + 1);
+ json_object *clientCtxJ = LuaPopOneArg(source, luaState, LUA_FIST_ARG + 2);
+
+ if (lua_gettop(luaState) != LUA_FIST_ARG+2 || !clientCtxJ || !callback) {
+ lua_pushliteral(luaState, "LuaClientCtx-Syntax clientCtx (source, callback, clientCtx)");
+ goto OnErrorExit;
+ }
+
+ // Allocate handle to store clientCtx and callback
+ LuaClientCtxT *clientCtx = calloc (1, sizeof(LuaCbHandleT));
+ clientCtx->callback = callback;
+ clientCtx->clientCtxJ= clientCtxJ;
+ clientCtx->source = malloc(sizeof(CtlSourceT));
+ memcpy (clientCtx->source, source, sizeof(CtlSourceT)); // source if free when command return
+
+ // push client context within session
+ void *done = AFB_ClientCtxSet (source->request, 1, LuaClientCtxNew, LuaClientCtxFree, clientCtx);
+ if (!done) {
+ lua_pushliteral(luaState, "LuaClientCtx-Fail to allocate client context)");
+ goto OnErrorExit;
+ }
+
+OnSuccessExit:
+ lua_pushnil(luaState);
+ return 1;
+
+OnErrorExit:
+ lua_error(luaState);
+ return 1; // return error code
+}
+
+
// Register a new L2c list of LUA user plugin commands
-PUBLIC void LuaL2cNewLib(const char *label, luaL_Reg *l2cFunc, int count) {
+PUBLIC void LuaL2cNewLib(const char *uid, 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);
+ lua_setglobal(luaState, uid);
}
static const luaL_Reg afbFunction[] = {
@@ -1068,7 +1205,9 @@ static const luaL_Reg afbFunction[] = {
{"subscribe" , LuaAfbEventSubscribe},
{"evtmake" , LuaAfbEventMake},
{"evtpush" , LuaAfbEventPush},
- {"getlabel" , LuaAfbGetLabel},
+ {"getuid" , LuaAfbGetUid},
+ {"status" , LuaAfbGetStatus},
+ {"context" , LuaClientCtx},
{NULL, NULL} /* sentinel */
};
@@ -1111,13 +1250,14 @@ PUBLIC int LuaConfigLoad (AFB_ApiT apiHandle) {
}
// Create Binding Event at Init Exec Time
-PUBLIC int LuaConfigExec (AFB_ApiT apiHandle) {
+PUBLIC int LuaConfigExec (AFB_ApiT apiHandle, const char* prefix) {
int err, index;
- // search for default policy config file
+ // search for default policy config files
char fullprefix[CONTROL_MAXPATH_LEN];
- strncpy (fullprefix, CONTROL_CONFIG_PRE "-", sizeof(fullprefix));
+ strncpy (fullprefix, prefix, sizeof(fullprefix));
+ strncat (fullprefix, "-", sizeof(fullprefix));
strncat (fullprefix, GetBinderName(), sizeof(fullprefix));
strncat (fullprefix, "-", sizeof(fullprefix));
diff --git a/ctl-lib/ctl-lua.h b/ctl-lib/ctl-lua.h
index 53eb6cb..c9ab5fd 100644
--- a/ctl-lib/ctl-lua.h
+++ b/ctl-lib/ctl-lua.h
@@ -58,8 +58,8 @@ typedef enum {
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 LuaConfigExec(AFB_ApiT apiHandle, const char * prefix);
+PUBLIC void LuaL2cNewLib(const char *uid, luaL_Reg *l2cFunc, int count);
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);
diff --git a/ctl-lib/ctl-onload.c b/ctl-lib/ctl-onload.c
index 1dec75a..7658622 100644
--- a/ctl-lib/ctl-onload.c
+++ b/ctl-lib/ctl-onload.c
@@ -41,9 +41,9 @@ PUBLIC int OnloadConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *a
goto OnErrorExit;
}
- for (int idx=0; section->actions[idx].label != NULL; idx ++) {
+ for (int idx=0; section->actions[idx].uid != NULL; idx ++) {
CtlSourceT source;
- source.label = section->actions[idx].label;
+ source.uid = section->actions[idx].uid;
source.api = section->actions[idx].api;
source.request = AFB_ReqNone;
diff --git a/ctl-lib/ctl-plugin.c b/ctl-lib/ctl-plugin.c
index 03f4c34..9ecb7d0 100644
--- a/ctl-lib/ctl-plugin.c
+++ b/ctl-lib/ctl-plugin.c
@@ -42,12 +42,12 @@ PUBLIC int PluginGetCB (AFB_ApiT apiHandle, CtlActionT *action , json_object *ca
goto OnErrorExit;
}
- for (idx=0; ctlPlugins[idx].label != NULL; idx++) {
- if (!strcasecmp (ctlPlugins[idx].label, plugin)) break;
+ for (idx=0; ctlPlugins[idx].uid != NULL; idx++) {
+ if (!strcasecmp (ctlPlugins[idx].uid, plugin)) break;
}
- if (!ctlPlugins[idx].label) {
- AFB_ApiError(apiHandle, "PluginGetCB no plugin with label=%s", plugin);
+ if (!ctlPlugins[idx].uid) {
+ AFB_ApiError(apiHandle, "PluginGetCB no plugin with uid=%s", plugin);
goto OnErrorExit;
}
@@ -87,14 +87,14 @@ STATIC int PluginLoadOne (AFB_ApiT apiHandle, CtlPluginT *ctlPlugin, json_object
if (!pluginJ) return 0;
int err = wrap_json_unpack(pluginJ, "{ss,s?s,s?s,s?s !}",
- "label", &ctlPlugin->label, "info", &ctlPlugin->info, "ldpath", &ldSearchPath, "basename", &basename);
+ "uid", &ctlPlugin->uid, "info", &ctlPlugin->info, "ldpath", &ldSearchPath, "basename", &basename);
if (err) {
- AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Plugin missing label|[info]|[basename]|[ldpath] in:\n-- %s", json_object_get_string(pluginJ));
+ AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Plugin missing uid|[info]|[basename]|[ldpath] in:\n-- %s", json_object_get_string(pluginJ));
goto OnErrorExit;
}
- // default basename equal label
- if (!basename) basename=ctlPlugin->label;
+ // default basename equal uid
+ if (!basename) basename=ctlPlugin->uid;
// if search path not in Json config file, then try default
if (!ldSearchPath) ldSearchPath = CONTROL_PLUGIN_PATH;
@@ -133,7 +133,7 @@ STATIC int PluginLoadOne (AFB_ApiT apiHandle, CtlPluginT *ctlPlugin, json_object
AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE symbol'CtlPluginMagic' missing or != CTL_PLUGIN_MAGIC plugin=%s", pluginpath);
goto OnErrorExit;
} else {
- AFB_ApiNotice(apiHandle, "CTL-PLUGIN-LOADONE %s successfully registered", ctlPluginMagic->label);
+ AFB_ApiNotice(apiHandle, "CTL-PLUGIN-LOADONE %s successfully registered", ctlPluginMagic->uid);
}
// store dlopen handle to enable onload action at exec time
diff --git a/ctl-lib/ctl-plugin.h b/ctl-lib/ctl-plugin.h
index a678af4..b2f161d 100644
--- a/ctl-lib/ctl-plugin.h
+++ b/ctl-lib/ctl-plugin.h
@@ -70,6 +70,9 @@
#define AFB_GetEventLoop(api) afb_dynapi_get_event_loop(api)
+ #define AFB_ClientCtxSet(request, replace, createCB, freeCB, handle) afb_request_context(request, replace, createCB, freeCB, handle)
+ #define AFB_ClientCtxClear(request) afb_request_context_clear(request)
+
typedef struct {
const char *verb; /* name of the verb, NULL only at end of the array */
@@ -122,6 +125,11 @@
#define AFB_GetEventLoop(api) afb_daemon_get_event_loop()
+ #define AFB_ClientCtxSet(request, replace, createCB, freeCB, handle) afb_req_context_set(request, createCB(handle), freeCB)
+ #define AFB_ClientCtxClear(request) afb_req_context_clear(request)
+
+
+
#define AFB_ApiVerbs afb_verb_v2
#endif
@@ -146,12 +154,12 @@
typedef struct {
- const char *label;
+ const char *uid;
const long magic;
} CtlPluginMagicT;
typedef struct {
- const char *label;
+ const char *uid;
const char *info;
AFB_ApiT api;
void *dlHandle;
@@ -166,16 +174,25 @@ typedef enum {
CTL_TYPE_LUA,
} CtlActionTypeT;
+typedef enum {
+ CTL_STATUS_DONE=0,
+ CTL_STATUS_ERR=-1,
+ CTL_STATUS_EVT=1,
+ CTL_STATUS_FREE=2,
+} CtlActionStatusT;
+
typedef struct {
- const char *label;
+ const char *uid;
AFB_ApiT api;
AFB_ReqT request;
void *context;
+ CtlActionStatusT status;
} CtlSourceT;
typedef struct {
- const char *label;
- const char *info;
+ const char *uid;
+ const char *info;
+ const char *privileges;
AFB_ApiT api;
json_object *argsJ;
CtlActionTypeT type;
@@ -202,7 +219,7 @@ typedef struct {
typedef void*(*DispatchPluginInstallCbT)(CtlPluginT *plugin, void* handle);
#define MACRO_STR_VALUE(arg) #arg
-#define CTLP_CAPI_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,.uid=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)
diff --git a/ctl-lib/ctl-timer.c b/ctl-lib/ctl-timer.c
index 81aa984..9cab0b2 100644
--- a/ctl-lib/ctl-timer.c
+++ b/ctl-lib/ctl-timer.c
@@ -27,7 +27,7 @@
#define DEFAULT_TEST_COUNT 1
typedef struct {
int value;
- const char *label;
+ const char *uid;
} AutoTestCtxT;
@@ -57,7 +57,7 @@ STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
return 0;
OnErrorExit:
- AFB_ApiWarning(timerHandle->api, "TimerNext Callback Fail Tag=%s", timerHandle->label);
+ AFB_ApiWarning(timerHandle->api, "TimerNext Callback Fail Tag=%s", timerHandle->uid);
return -1;
}
diff --git a/ctl-lib/ctl-timer.h b/ctl-lib/ctl-timer.h
index ced0417..6256dcc 100644
--- a/ctl-lib/ctl-timer.h
+++ b/ctl-lib/ctl-timer.h
@@ -29,7 +29,7 @@ typedef struct TimerHandleS {
int magic;
int count;
int delay;
- const char*label;
+ const char*uid;
void *context;
timerCallbackT callback;
sd_event_source *evtSource;