diff options
author | Fulup Ar Foll <fulup@iot.bzh> | 2017-10-24 22:17:59 +0200 |
---|---|---|
committer | Romain Forlot <romain.forlot@iot.bzh> | 2018-12-13 15:02:54 +0100 |
commit | 67d50c819ea60b00a3441d446ce6719ec3bf2349 (patch) | |
tree | 158e6d4920cd460ccafbdaa1cee97738242daec6 /ctl-lib | |
parent | 2b77a50d5c578d92ac692b872f5a51c227c29334 (diff) |
First working version as submodule
Diffstat (limited to 'ctl-lib')
-rw-r--r-- | ctl-lib/ctl-action.c | 45 | ||||
-rw-r--r-- | ctl-lib/ctl-config.c | 17 | ||||
-rw-r--r-- | ctl-lib/ctl-config.h | 4 | ||||
-rw-r--r-- | ctl-lib/ctl-control.c | 1 | ||||
-rw-r--r-- | ctl-lib/ctl-event.c | 10 | ||||
-rw-r--r-- | ctl-lib/ctl-lua.c | 258 | ||||
-rw-r--r-- | ctl-lib/ctl-lua.h | 4 | ||||
-rw-r--r-- | ctl-lib/ctl-onload.c | 4 | ||||
-rw-r--r-- | ctl-lib/ctl-plugin.c | 18 | ||||
-rw-r--r-- | ctl-lib/ctl-plugin.h | 29 | ||||
-rw-r--r-- | ctl-lib/ctl-timer.c | 4 | ||||
-rw-r--r-- | ctl-lib/ctl-timer.h | 2 |
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, §ionJ); - 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, §ions[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; |