From 9777a02c7540fdec145feb948b4bbf1cd44c3352 Mon Sep 17 00:00:00 2001 From: fulup Date: Sun, 13 Aug 2017 16:50:34 +0200 Subject: Fix AFB_MESSAGE with null arguments --- Controler-afb/CMakeLists.txt | 4 +- Controler-afb/ctl-apidef.h | 123 ++++++------ Controler-afb/ctl-apidef.json | 50 ++++- Controler-afb/ctl-binding.c | 3 + Controler-afb/ctl-binding.h | 19 +- Controler-afb/ctl-dispatch.c | 396 ++++++++++++++++++++++++-------------- Controler-afb/ctl-events.c | 2 +- Controler-afb/ctl-lua.c | 325 ++++++++++++++++++------------- Controler-afb/ctl-misc.c | 115 +++++++++++ Controler-afb/ctl-misc2.c | 74 +++++++ Controler-afb/ctl-plugin-sample.c | 21 +- 11 files changed, 782 insertions(+), 350 deletions(-) create mode 100644 Controler-afb/ctl-misc.c create mode 100644 Controler-afb/ctl-misc2.c (limited to 'Controler-afb') diff --git a/Controler-afb/CMakeLists.txt b/Controler-afb/CMakeLists.txt index 64ea5e1..4fb97b2 100644 --- a/Controler-afb/CMakeLists.txt +++ b/Controler-afb/CMakeLists.txt @@ -33,7 +33,7 @@ endmacro(SET_TARGET_GENSKEL) PROJECT_TARGET_ADD(control-afb) # Define project Targets - ADD_LIBRARY(${TARGET_NAME} MODULE ctl-binding.c ctl-events.c ctl-dispatch.c ctl-lua.c) + ADD_LIBRARY(${TARGET_NAME} MODULE ctl-binding.c ctl-events.c ctl-dispatch.c ctl-lua.c ctl-misc.c) # Generate API-v2 hat from OpenAPI json definition SET_TARGET_GENSKEL(${TARGET_NAME} ctl-apidef) @@ -56,7 +56,7 @@ PROJECT_TARGET_ADD(control-afb) INSTALL(TARGETS ${TARGET_NAME} LIBRARY DESTINATION CMAKE_INSTALL_PREFIX ) -PROJECT_TARGET_ADD(ctl-plugin-sample) +PROJECT_TARGET_ADD(audio-plugin-sample) # Define targets ADD_LIBRARY(${TARGET_NAME} MODULE ctl-plugin-sample.c) diff --git a/Controler-afb/ctl-apidef.h b/Controler-afb/ctl-apidef.h index 0ab4cd2..0f801cb 100644 --- a/Controler-afb/ctl-apidef.h +++ b/Controler-afb/ctl-apidef.h @@ -1,61 +1,66 @@ static const char _afb_description_v2_control[] = "{\"openapi\":\"3.0.0\",\"$schema\":\"http:iot.bzh/download/openapi/schem" - "a-3.0/default-schema.json\",\"info\":{\"description\":\"\",\"title\":\"p" - "olctl\",\"version\":\"1.0\",\"x-binding-c-generator\":{\"api\":\"control" - "\",\"version\":2,\"prefix\":\"ctlapi_\",\"postfix\":\"\",\"start\":null," - "\"onevent\":null,\"init\":\"CtlBindingInit\",\"scope\":\"\",\"private\":" - "false}},\"servers\":[{\"url\":\"ws://{host}:{port}/api/polctl\",\"descri" - "ption\":\"Unicens2 API.\",\"variables\":{\"host\":{\"default\":\"localho" - "st\"},\"port\":{\"default\":\"1234\"}},\"x-afb-events\":[{\"$ref\":\"#/c" - "omponents/schemas/afb-event\"}]}],\"components\":{\"schemas\":{\"afb-rep" - "ly\":{\"$ref\":\"#/components/schemas/afb-reply-v2\"},\"afb-event\":{\"$" - "ref\":\"#/components/schemas/afb-event-v2\"},\"afb-reply-v2\":{\"title\"" - ":\"Generic response.\",\"type\":\"object\",\"required\":[\"jtype\",\"req" - "uest\"],\"properties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-r" - "eply\"},\"request\":{\"type\":\"object\",\"required\":[\"status\"],\"pro" - "perties\":{\"status\":{\"type\":\"string\"},\"info\":{\"type\":\"string\"" - "},\"token\":{\"type\":\"string\"},\"uuid\":{\"type\":\"string\"},\"reqid" - "\":{\"type\":\"string\"}}},\"response\":{\"type\":\"object\"}}},\"afb-ev" - "ent-v2\":{\"type\":\"object\",\"required\":[\"jtype\",\"event\"],\"prope" - "rties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-event\"},\"event" - "\":{\"type\":\"string\"},\"data\":{\"type\":\"object\"}}}},\"x-permissio" - "ns\":{\"monitor\":{\"permission\":\"urn:AGL:permission:audio:public:moni" - "tor\"},\"multimedia\":{\"permission\":\"urn:AGL:permission:audio:public:" - "monitor\"},\"navigation\":{\"permission\":\"urn:AGL:permission:audio:pub" - "lic:monitor\"},\"emergency\":{\"permission\":\"urn:AGL:permission:audio:" - "public:emergency\"}},\"responses\":{\"200\":{\"description\":\"A complex" - " object array response\",\"content\":{\"application/json\":{\"schema\":{" - "\"$ref\":\"#/components/schemas/afb-reply\"}}}}}},\"paths\":{\"/monitor\"" - ":{\"description\":\"Subcribe Audio Agent Policy Control End\",\"get\":{\"" - "x-permissions\":{\"$ref\":\"#/components/x-permissions/monitor\"},\"para" - "meters\":[{\"in\":\"query\",\"name\":\"event_patern\",\"required\":true," - "\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/" - "components/responses/200\"}}}},\"/event_test\":{\"description\":\"Pause " - "Resume Test\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-perm" - "issions/monitor\"},\"parameters\":[{\"in\":\"query\",\"name\":\"delay\"," - "\"required\":false,\"schema\":{\"type\":\"interger\"}},{\"in\":\"query\"" - ",\"name\":\"count\",\"required\":false,\"schema\":{\"type\":\"interger\"" - "}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}}," - "\"/navigation\":{\"description\":\"Request Access to Navigation Audio Ch" - "annel.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissio" - "ns/navigation\"},\"parameters\":[{\"in\":\"query\",\"name\":\"zone\",\"r" - "equired\":false,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\"" - ":{\"$ref\":\"#/components/responses/200\"}}}},\"/lua_docall\":{\"descrip" - "tion\":\"Execute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref" - "\":\"#/components/x-permissions/navigation\"},\"parameters\":[{\"in\":\"" - "query\",\"name\":\"func\",\"required\":true,\"schema\":{\"type\":\"strin" - "g\"}},{\"in\":\"query\",\"name\":\"args\",\"required\":false,\"schema\":" - "{\"type\":\"array\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/r" - "esponses/200\"}}}},\"/lua_dostring\":{\"description\":\"Execute LUA stri" - "ng script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permi" - "ssions/navigation\"},\"parameters\":[{\"in\":\"query\",\"required\":true" - ",\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#" - "/components/responses/200\"}}}},\"/lua_doscript\":{\"description\":\"Exe" - "cute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/compo" + "a-3.0/default-schema.json\",\"info\":{\"description\":\"\",\"title\":\"c" + "ontroler\",\"version\":\"1.0\",\"x-binding-c-generator\":{\"api\":\"cont" + "rol\",\"version\":2,\"prefix\":\"ctlapi_\",\"postfix\":\"\",\"start\":nu" + "ll,\"onevent\":\"DispatchOneEvent\",\"init\":\"CtlBindingInit\",\"scope\"" + ":\"\",\"private\":false}},\"servers\":[{\"url\":\"ws://{host}:{port}/api" + "/polctl\",\"description\":\"Unicens2 API.\",\"variables\":{\"host\":{\"d" + "efault\":\"localhost\"},\"port\":{\"default\":\"1234\"}},\"x-afb-events\"" + ":[{\"$ref\":\"#/components/schemas/afb-event\"}]}],\"components\":{\"sch" + "emas\":{\"afb-reply\":{\"$ref\":\"#/components/schemas/afb-reply-v2\"},\"" + "afb-event\":{\"$ref\":\"#/components/schemas/afb-event-v2\"},\"afb-reply" + "-v2\":{\"title\":\"Generic response.\",\"type\":\"object\",\"required\":" + "[\"jtype\",\"request\"],\"properties\":{\"jtype\":{\"type\":\"string\",\"" + "const\":\"afb-reply\"},\"request\":{\"type\":\"object\",\"required\":[\"" + "status\"],\"properties\":{\"status\":{\"type\":\"string\"},\"info\":{\"t" + "ype\":\"string\"},\"token\":{\"type\":\"string\"},\"uuid\":{\"type\":\"s" + "tring\"},\"reqid\":{\"type\":\"string\"}}},\"response\":{\"type\":\"obje" + "ct\"}}},\"afb-event-v2\":{\"type\":\"object\",\"required\":[\"jtype\",\"" + "event\"],\"properties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-" + "event\"},\"event\":{\"type\":\"string\"},\"data\":{\"type\":\"object\"}}" + "}},\"x-permissions\":{\"monitor\":{\"permission\":\"urn:AGL:permission:a" + "udio:public:monitor\"},\"multimedia\":{\"permission\":\"urn:AGL:permissi" + "on:audio:public:monitor\"},\"navigation\":{\"permission\":\"urn:AGL:perm" + "ission:audio:public:monitor\"},\"emergency\":{\"permission\":\"urn:AGL:p" + "ermission:audio:public:emergency\"}},\"responses\":{\"200\":{\"descripti" + "on\":\"A complex object array response\",\"content\":{\"application/json" + "\":{\"schema\":{\"$ref\":\"#/components/schemas/afb-reply\"}}}}}},\"path" + "s\":{\"/monitor\":{\"description\":\"Subcribe Audio Agent Policy Control" + " End\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions" + "/monitor\"},\"parameters\":[{\"in\":\"query\",\"name\":\"event_patern\"," + "\"required\":true,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"20" + "0\":{\"$ref\":\"#/components/responses/200\"}}}},\"/event_test\":{\"desc" + "ription\":\"Pause Resume Test\",\"get\":{\"x-permissions\":{\"$ref\":\"#" + "/components/x-permissions/monitor\"},\"parameters\":[{\"in\":\"query\",\"" + "name\":\"delay\",\"required\":false,\"schema\":{\"type\":\"interger\"}}," + "{\"in\":\"query\",\"name\":\"count\",\"required\":false,\"schema\":{\"ty" + "pe\":\"interger\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/res" + "ponses/200\"}}}},\"/navigation\":{\"description\":\"Request Access to Na" + "vigation Audio Channel.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/compo" "nents/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"na" - "me\":\"filename\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\"" - "responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}}}}" + "me\":\"zone\",\"required\":false,\"schema\":{\"type\":\"string\"}}],\"re" + "sponses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/multi" + "media\":{\"description\":\"Request Access to Navigation Audio Channel.\"" + ",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/navig" + "ation\"},\"parameters\":[{\"in\":\"query\",\"name\":\"zone\",\"required\"" + ":false,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref" + "\":\"#/components/responses/200\"}}}},\"/lua_docall\":{\"description\":\"" + "Execute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/co" + "mponents/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"" + "name\":\"func\",\"required\":true,\"schema\":{\"type\":\"string\"}},{\"i" + "n\":\"query\",\"name\":\"args\",\"required\":false,\"schema\":{\"type\":" + "\"array\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/2" + "00\"}}}},\"/lua_dostring\":{\"description\":\"Execute LUA string script." + "\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/nav" + "igation\"},\"parameters\":[{\"in\":\"query\",\"required\":true,\"schema\"" + ":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components" + "/responses/200\"}}}},\"/lua_doscript\":{\"description\":\"Execute LUA st" + "ring script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-per" + "missions/navigation\"},\"parameters\":[{\"in\":\"query\",\"name\":\"file" + "name\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\"responses\"" + ":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}}}}" ; static const struct afb_auth _afb_auths_v2_control[] = { @@ -65,6 +70,7 @@ static const struct afb_auth _afb_auths_v2_control[] = { void ctlapi_monitor(struct afb_req req); void ctlapi_event_test(struct afb_req req); void ctlapi_navigation(struct afb_req req); + void ctlapi_multimedia(struct afb_req req); void ctlapi_lua_docall(struct afb_req req); void ctlapi_lua_dostring(struct afb_req req); void ctlapi_lua_doscript(struct afb_req req); @@ -91,6 +97,13 @@ static const struct afb_verb_v2 _afb_verbs_v2_control[] = { .info = NULL, .session = AFB_SESSION_NONE_V2 }, + { + .verb = "multimedia", + .callback = ctlapi_multimedia, + .auth = &_afb_auths_v2_control[0], + .info = NULL, + .session = AFB_SESSION_NONE_V2 + }, { .verb = "lua_docall", .callback = ctlapi_lua_docall, @@ -122,7 +135,7 @@ const struct afb_binding_v2 afbBindingV2 = { .verbs = _afb_verbs_v2_control, .preinit = NULL, .init = CtlBindingInit, - .onevent = NULL, + .onevent = DispatchOneEvent, .noconcurrency = 0 }; diff --git a/Controler-afb/ctl-apidef.json b/Controler-afb/ctl-apidef.json index fddf301..438a9ef 100644 --- a/Controler-afb/ctl-apidef.json +++ b/Controler-afb/ctl-apidef.json @@ -3,7 +3,7 @@ "$schema": "http:iot.bzh/download/openapi/schema-3.0/default-schema.json", "info": { "description": "", - "title": "polctl", + "title": "controler", "version": "1.0", "x-binding-c-generator": { "api": "control", @@ -11,7 +11,7 @@ "prefix": "ctlapi_", "postfix": "", "start": null, - "onevent": null, + "onevent": "DispatchOneEvent", "init": "CtlBindingInit", "scope": "", "private": false @@ -201,6 +201,52 @@ } } }, + "/multimedia": { + "description": "Request Access to Navigation Audio Channel.", + "get": { + "x-permissions": { + "$ref": "#/components/x-permissions/navigation" + }, + "parameters": [ + { + "in": "query", + "name": "zone", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/200" + } + } + } + }, + "/navigation": { + "description": "Request Access to Navigation Audio Channel.", + "get": { + "x-permissions": { + "$ref": "#/components/x-permissions/navigation" + }, + "parameters": [ + { + "in": "query", + "name": "zone", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/200" + } + } + } + }, "/lua_docall": { "description": "Execute LUA string script.", "get": { diff --git a/Controler-afb/ctl-binding.c b/Controler-afb/ctl-binding.c index dc225a4..19f97eb 100644 --- a/Controler-afb/ctl-binding.c +++ b/Controler-afb/ctl-binding.c @@ -68,6 +68,9 @@ PUBLIC int CtlBindingInit () { errcount += DispatchInit(); errcount += LuaLibInit(); + // now that everything is initialised execute the onload action + errcount += DispatchOneOnLoad(CONTROL_ONLOAD_DEFAULT); + AFB_DEBUG ("Audio Policy Control Binding Done errcount=%d", errcount); return errcount; } diff --git a/Controler-afb/ctl-binding.h b/Controler-afb/ctl-binding.h index deef93c..01840b8 100644 --- a/Controler-afb/ctl-binding.h +++ b/Controler-afb/ctl-binding.h @@ -28,6 +28,11 @@ #endif #define STATIC static +#ifndef UNUSED_ARG +#define UNUSED_ARG(x) UNUSED_ ## x __attribute__((__unused__)) +#define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x +#endif + // sharelib ctl-plugin* typedef struct { long magic; @@ -36,6 +41,9 @@ typedef struct { #define CTL_PLUGIN_REGISTER(pluglabel) CtlPluginMagicT CtlPluginMagic={.magic=CTL_PLUGIN_MAGIC,.label=pluglabel}; struct afb_binding_data_v2; +// ctl-misc.c + + // polctl-binding.c PUBLIC int CtlBindingInit (); @@ -49,12 +57,14 @@ PUBLIC void ctlapi_event_test (afb_req request); // ctl-policy // ----------- - typedef enum { CTL_SCAN_FLAT=0, CTL_SCAN_RECURSIVE=1, } CtlScanDirModeT; +PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext); +PUBLIC const char *GetBinderName(); + typedef enum { CTL_MODE_NONE=0, CTL_MODE_API, @@ -70,10 +80,12 @@ typedef struct DispatchActionS{ const char* call; json_object *argsJ; int timeout; - int (*actionCB)(afb_req request, struct DispatchActionS *action, void *context); + int (*actionCB)(struct DispatchActionS *action, json_object *queryJ, void *context); } DispatchActionT; PUBLIC int DispatchInit(void); +PUBLIC int DispatchOneOnLoad(const char *onLoadLabel); +PUBLIC void DispatchOneEvent(const char *evtLabel, json_object *eventJ); PUBLIC void ctlapi_dispatch (char* control, afb_req request); // ctl-lua.c @@ -85,8 +97,7 @@ typedef enum { } LuaDoActionT; PUBLIC int LuaLibInit (); -PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext); -PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action); +PUBLIC int LuaCallFunc (DispatchActionT *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/Controler-afb/ctl-dispatch.c b/Controler-afb/ctl-dispatch.c index 8fdf46e..7d6a31d 100644 --- a/Controler-afb/ctl-dispatch.c +++ b/Controler-afb/ctl-dispatch.c @@ -28,6 +28,14 @@ typedef void*(*DispatchPluginInstallCbT)(const char* label, const char*version, const char*info); +static afb_req NULL_AFBREQ={}; + +typedef enum { + CTL_DISPATCH_ONLOAD, + CTL_DISPATCH_CONTROL, + CTL_DISPATCH_EVENT, +} DispatchClassT; + typedef struct { const char* label; const char *info; @@ -41,39 +49,36 @@ typedef struct { void *context; char *plugin; void *dlHandle; - DispatchHandleT *onload; - DispatchHandleT *events; + DispatchHandleT **onloads; + DispatchHandleT **events; DispatchHandleT **controls; } DispatchConfigT; // global config handle STATIC DispatchConfigT *configHandle = NULL; -STATIC int DispatchControlToIndex(char* controlLabel) { - DispatchHandleT **controls=configHandle->controls; +STATIC int DispatchControlToIndex(DispatchHandleT **controls, const char* controlLabel) { + for (int idx=0; controls[idx]; idx++) { if (!strcasecmp(controlLabel, controls[idx]->label)) return idx; } - return 0; + return -1; } -PUBLIC void ctlapi_dispatch (char* controlLabel, afb_req request) { - DispatchHandleT **controls=configHandle->controls; +STATIC int DispatchOneControl (DispatchHandleT **controls, const char* controlLabel, json_object *queryJ, afb_req request) { int err; if(!configHandle->controls) { AFB_ERROR ("DISPATCH-CTL-API: No Control Action in Json config label=%s version=%s", configHandle->label, configHandle->version); - goto OnErrorExit; + goto OnErrorExit; } - int index=DispatchControlToIndex(controlLabel); - if (!index || !controls[index]->actions) { - AFB_ERROR ("DISPATCH-CTL-API:NotFound label=%s index=%d", controlLabel, index); + int index=DispatchControlToIndex(controls, controlLabel); + if (index<0 || !controls[index]->actions) { + AFB_ERROR ("DISPATCH-CTL-API:NotFound label=%s in Json Control Config File", controlLabel); goto OnErrorExit; - } else { - AFB_NOTICE("DISPATCH-CTL-API:Found Control=%s", controls[index]->label); - } - + } + // loop on action for this control DispatchActionT *actions=controls[index]->actions; for (int idx=0; actions[idx].label; idx++) { @@ -85,50 +90,80 @@ PUBLIC void ctlapi_dispatch (char* controlLabel, afb_req request) { json_object_get( actions[idx].argsJ); // make sure afb_service_call does not free the argsJ int err = afb_service_call_sync(actions[idx].api, actions[idx].call, actions[idx].argsJ, &returnJ); if (err) { - AFB_NOTICE ("DISPATCH-CTL-MODE:Api api=%s verb=%s args=%s", actions[idx].api, actions[idx].call, actions[idx].label); - afb_req_fail_f(request, "DISPATCH-CTL-MODE:Api", "label=%s api=%s verb=%s", actions[idx].label, actions[idx].api, actions[idx].call); + static const char*format="DispatchOneControl Api api=%s verb=%s args=%s"; + if (afb_req_is_valid(request))afb_req_fail_f(request, "DISPATCH-CTL-MODE:API", format, actions[idx].label, actions[idx].api, actions[idx].call); + else AFB_ERROR (format, actions[idx].api, actions[idx].call, actions[idx].label); goto OnErrorExit; } break; } case CTL_MODE_LUA: - err= LuaCallFunc (request, &actions[idx]); + err= LuaCallFunc (&actions[idx], queryJ); if (err) { - afb_req_fail_f(request, "DISPATCH-CTL-MODE:Lua", "func=%s args=%s", actions[idx].call, json_object_get_string(actions[idx].argsJ)); + static const char*format= "DispatchOneControl func=%s args=%s"; + if (afb_req_is_valid(request)) afb_req_fail_f(request, "DISPATCH-CTL-MODE:Lua", format, actions[idx].call, json_object_get_string(actions[idx].argsJ)); + else AFB_ERROR (format, actions[idx].call, json_object_get_string(actions[idx].argsJ)); goto OnErrorExit; } break; case CTL_MODE_CB: - err= (*actions[idx].actionCB) (request, &actions[idx], configHandle->context); + err= (*actions[idx].actionCB) (&actions[idx], queryJ, configHandle->context); if (err) { - afb_req_fail_f(request, "DISPATCH-CTL-MODE:Cb", "func=%s args=%s", actions[idx].call, json_object_get_string(actions[idx].argsJ)); + static const char*format="DispatchOneControl func=%s args=%s"; + if (afb_req_is_valid(request)) afb_req_fail_f(request, "DISPATCH-CTL-MODE:Cb", format, actions[idx].call, json_object_get_string(actions[idx].argsJ)); + else AFB_ERROR (format, actions[idx].call, json_object_get_string(actions[idx].argsJ)); goto OnErrorExit; } break; - default: - AFB_ERROR ("DISPATCH-CTL-API:control=%s action=%s", controls[index]->label, actions[idx].label); - afb_req_fail_f(request, "DISPATCH-CTL-MODE:Unknown", "control=%s action=%s", controls[index]->label, actions[idx].label); + default:{ + static const char*format="DispatchOneControl unknown mode control=%s action=%s"; + AFB_ERROR (format, controls[index]->label, actions[idx].label); + if (afb_req_is_valid(request))afb_req_fail_f(request, "DISPATCH-CTL-MODE:Unknown", format, controls[index]->label, actions[idx].label); + } } } // everything when fine - afb_req_success(request,NULL,controls[index]->label); - return; + if(afb_req_is_valid(request))afb_req_success(request,NULL,controls[index]->label); + return 0; - OnErrorExit: - return; + OnErrorExit: + return -1; +} + + +// Event name is mapped on control label and executed as a standard control +PUBLIC void DispatchOneEvent(const char *evtLabel, json_object *eventJ){ + DispatchHandleT **events=configHandle->events; + + (void)DispatchOneControl(events, evtLabel, eventJ, NULL_AFBREQ); +} + +// Event name is mapped on control label and executed as a standard control +PUBLIC int DispatchOneOnLoad(const char *onLoadLabel){ + DispatchHandleT **onloads=configHandle->onloads; + + int err=DispatchOneControl(onloads, onLoadLabel, NULL, NULL_AFBREQ); + return err; } +PUBLIC void ctlapi_dispatch (char* controlLabel, afb_req request) { + DispatchHandleT **controls=configHandle->controls; + + json_object* queryJ = afb_req_json(request); + (void)DispatchOneControl(controls, controlLabel, queryJ, request); +} + // List Avaliable Configuration Files PUBLIC void ctlapi_config (struct afb_req request) { json_object*tmpJ; char *dirList; - json_object* argsJ = afb_req_json(request); - if (argsJ && json_object_object_get_ex (argsJ, "cfgpath" , &tmpJ)) { + json_object* queryJ = afb_req_json(request); + if (queryJ && json_object_object_get_ex (queryJ, "cfgpath" , &tmpJ)) { dirList = strdup (json_object_get_string(tmpJ)); } else { dirList = strdup (CONTROL_CONFIG_PATH); @@ -228,6 +263,118 @@ STATIC DispatchActionT *DispatchLoadActions (DispatchConfigT *controlConfig, jso } +STATIC DispatchHandleT *DispatchLoadControl (DispatchConfigT *controlConfig, json_object *controlJ) { + json_object *actionsJ; + int err; + + DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); + err= wrap_json_unpack(controlJ, "{ss,s?s,so !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "actions",&actionsJ); + if (err) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROL Missing something label|[info]|actions in %s", json_object_get_string(controlJ)); + goto OnErrorExit; + } + + dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); + if (!dispatchHandle->actions) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROL Error when parsing actions %s", dispatchHandle->label); + goto OnErrorExit; + } + return dispatchHandle; + + OnErrorExit: + return NULL; +} + +STATIC DispatchHandleT *DispatchLoadOnload (DispatchConfigT *controlConfig, json_object *onloadJ) { + json_object *actionsJ=NULL, *requireJ=NULL; + int err; + + DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); + err= wrap_json_unpack(onloadJ, "{ss,s?s,s?s,s?o,s?o !}", + "label",&dispatchHandle->label, "info",&dispatchHandle->info, "plugin", &controlConfig->plugin, "require", &requireJ, "actions",&actionsJ); + if (err) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Missing something label|[info]|[plugin]|[actions] in %s", json_object_get_string(onloadJ)); + goto OnErrorExit; + } + + // best effort to initialise everything before starting + if (requireJ) { + + void DispatchRequireOneApi (json_object *bindindJ) { + const char* requireBinding = json_object_get_string(bindindJ); + err = afb_daemon_require_api(requireBinding, 1); + if (err) { + AFB_WARNING ("DISPATCH-LOAD-CONFIG:REQUIRE Fail to get=%s", requireBinding); + } + } + + if (json_object_get_type(requireJ) == json_type_array) { + for (int idx=0; idx < json_object_array_length(requireJ); idx++) { + DispatchRequireOneApi (json_object_array_get_idx(requireJ, idx)); + } + } else { + DispatchRequireOneApi (requireJ); + } + } + + if (controlConfig->plugin) { + + // search for default policy config file + json_object *pluginPathJ = ScanForConfig(CONTROL_PLUGIN_PATH , CTL_SCAN_RECURSIVE, controlConfig->plugin, NULL); + if (!pluginPathJ || json_object_array_length(pluginPathJ) == 0) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN Missing plugin=%s in path=%s", controlConfig->plugin, CONTROL_PLUGIN_PATH); + goto OnErrorExit; + } + + char *filename; char*fullpath; + err= wrap_json_unpack (json_object_array_get_idx(pluginPathJ,0), "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename); + if (err) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN HOOPs invalid plugin file path = %s", json_object_get_string(pluginPathJ)); + goto OnErrorExit; + } + + if (json_object_array_length(pluginPathJ) > 1) { + AFB_WARNING ("DISPATCH-LOAD-CONFIG:PLUGIN plugin multiple instances in searchpath will use %s/%s", fullpath, filename); + } + + char pluginpath[CONTROL_MAXPATH_LEN]; + strncpy(pluginpath, fullpath, sizeof(pluginpath)); + strncat(pluginpath, "/", sizeof(pluginpath)); + strncat(pluginpath, filename, sizeof(pluginpath)); + controlConfig->dlHandle = dlopen(pluginpath, RTLD_NOW); + if (!controlConfig->dlHandle) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN Fail to load pluginpath=%s err= %s", pluginpath, dlerror()); + goto OnErrorExit; + } + + CtlPluginMagicT *ctlPluginMagic = (CtlPluginMagicT*)dlsym(controlConfig->dlHandle, "CtlPluginMagic"); + if (!ctlPluginMagic || ctlPluginMagic->magic != CTL_PLUGIN_MAGIC) { + AFB_ERROR("DISPATCH-LOAD-CONFIG:Plugin symbol'CtlPluginMagic' missing or != CTL_PLUGIN_MAGIC plugin=%s", pluginpath); + goto OnErrorExit; + } else { + AFB_NOTICE("DISPATCH-LOAD-CONFIG:Plugin %s successfully registered", ctlPluginMagic->label); + } + + // Jose hack to make verbosity visible from sharelib + struct afb_binding_data_v2 *afbHidenData = dlsym(controlConfig->dlHandle, "afbBindingV2data"); + if (afbHidenData) *afbHidenData = afbBindingV2data; + + DispatchPluginInstallCbT ctlPluginOnload = dlsym(controlConfig->dlHandle, "CtlPluginOnload"); + if (ctlPluginOnload) { + controlConfig->context = (*ctlPluginOnload) (controlConfig->label, controlConfig->version, controlConfig->info); + } + } + + dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); + if (!dispatchHandle->actions) { + AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Error when parsing actions %s", dispatchHandle->label); + goto OnErrorExit; + } + return dispatchHandle; + + OnErrorExit: + return NULL; +} STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) { json_object *controlConfigJ, *ignoreJ; @@ -242,8 +389,8 @@ STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) { AFB_INFO ("DISPATCH-LOAD-CONFIG: loading config filepath=%s", filepath); - json_object *metadataJ=NULL, *onloadJ=NULL, *controlsJ=NULL, *eventsJ=NULL; - err= wrap_json_unpack(controlConfigJ, "{s?o,so,s?o,s?o,s?o !}", "$schema", &ignoreJ, "metadata",&metadataJ, "onload",&onloadJ, "controls",&controlsJ, "events",&eventsJ); + json_object *metadataJ=NULL, *onloadsJ=NULL, *controlsJ=NULL, *eventsJ=NULL; + err= wrap_json_unpack(controlConfigJ, "{s?o,so,s?o,s?o,s?o !}", "$schema", &ignoreJ, "metadata",&metadataJ, "onload",&onloadsJ, "controls",&controlsJ, "events",&eventsJ); if (err) { AFB_ERROR ("DISPATCH-LOAD-CONFIG Missing something metadata|[onload]|[controls]|[events] in %s", json_object_get_string(controlConfigJ)); goto OnErrorExit; @@ -258,117 +405,61 @@ STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) { } } - if (onloadJ) { - json_object * actionsJ; - DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); - err= wrap_json_unpack(onloadJ, "{so,s?s,s?s,s?o !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "plugin", &controlConfig->plugin, "actions",&actionsJ); - if (err) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Missing something label|[info]|[plugin]|[actions] in %s", json_object_get_string(onloadJ)); - goto OnErrorExit; - } + if (onloadsJ) { + DispatchHandleT *dispatchHandle; - if (controlConfig->plugin) { - - // search for default policy config file - json_object *pluginPathJ = ScanForConfig(CONTROL_PLUGIN_PATH , CTL_SCAN_RECURSIVE, controlConfig->plugin, NULL); - if (!pluginPathJ || json_object_array_length(pluginPathJ) == 0) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN Missing plugin=%s in path=%s", controlConfig->plugin, CONTROL_PLUGIN_PATH); - goto OnErrorExit; - } - - char *filename; char*fullpath; - err= wrap_json_unpack (json_object_array_get_idx(pluginPathJ,0), "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename); - if (err) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN HOOPs invalid plugin file path = %s", json_object_get_string(pluginPathJ)); - goto OnErrorExit; - } - - if (json_object_array_length(pluginPathJ) > 1) { - AFB_WARNING ("DISPATCH-LOAD-CONFIG:PLUGIN plugin multiple instances in searchpath will use %s/%s", fullpath, filepath); - } - - char pluginpath[CONTROL_MAXPATH_LEN]; - strncpy(pluginpath, fullpath, sizeof(pluginpath)); - strncat(pluginpath, "/", sizeof(pluginpath)); - strncat(pluginpath, filename, sizeof(pluginpath)); - controlConfig->dlHandle = dlopen(pluginpath, RTLD_NOW); - if (!controlConfig->dlHandle) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN Fail to load pluginpath=%s err= %s", pluginpath, dlerror()); - goto OnErrorExit; - } - - CtlPluginMagicT *ctlPluginMagic = (CtlPluginMagicT*)dlsym(controlConfig->dlHandle, "CtlPluginMagic"); - if (!ctlPluginMagic || ctlPluginMagic->magic != CTL_PLUGIN_MAGIC) { - AFB_ERROR("DISPATCH-LOAD-CONFIG:Plugin symbol'CtlPluginMagic' missing or != CTL_PLUGIN_MAGIC plugin=%s", pluginpath); - goto OnErrorExit; - } else { - AFB_NOTICE("DISPATCH-LOAD-CONFIG:Plugin %s successfully registered", ctlPluginMagic->label); - } - - // Jose hack to make verbosity visible from sharelib - struct afb_binding_data_v2 *afbHidenData = dlsym(controlConfig->dlHandle, "afbBindingV2data"); - if (afbHidenData) *afbHidenData = afbBindingV2data; - - DispatchPluginInstallCbT ctlPluginOnload = dlsym(controlConfig->dlHandle, "CtlPluginOnload"); - if (ctlPluginOnload) { - controlConfig->context = (*ctlPluginOnload) (controlConfig->label, controlConfig->version, controlConfig->info); + if (json_object_get_type(onloadsJ) != json_type_array) { + controlConfig->onloads = (DispatchHandleT**) calloc (2, sizeof(void*)); + dispatchHandle = DispatchLoadOnload (controlConfig, onloadsJ); + controlConfig->onloads[0]= dispatchHandle; + } else { + int length= json_object_array_length(onloadsJ); + controlConfig->onloads = (DispatchHandleT**) calloc (length+1, sizeof(void*)); + + for (int jdx=0; jdx< length; jdx++) { + json_object *onloadJ = json_object_array_get_idx(onloadsJ,jdx); + dispatchHandle = DispatchLoadOnload (controlConfig, onloadJ); + controlConfig->onloads[jdx]= dispatchHandle; } - } - - dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); - if (!dispatchHandle->actions) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Error when parsing actions %s", dispatchHandle->label); - goto OnErrorExit; - } - controlConfig->onload= dispatchHandle; - + } } if (controlsJ) { - json_object * actionsJ; - - if (json_object_get_type(controlsJ) != json_type_array) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS invalid JSON array in %s", json_object_get_string(controlsJ)); - goto OnErrorExit; - } - - int length= json_object_array_length(controlsJ); - controlConfig->controls = (DispatchHandleT**) calloc (length+1, sizeof(void*)); + DispatchHandleT *dispatchHandle; - for (int jdx=0; jdx< length; jdx++) { - DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); - json_object *controlJ = json_object_array_get_idx(controlsJ,jdx); - err= wrap_json_unpack(controlJ, "{ss,s?s,so !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "actions",&actionsJ); - if (err) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS Missing something label|[info]|actions in %s", json_object_get_string(controlJ)); - goto OnErrorExit; - } - - dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); - if (!dispatchHandle->actions) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS Error when parsing actions %s", dispatchHandle->label); - goto OnErrorExit; + if (json_object_get_type(controlsJ) != json_type_array) { + controlConfig->controls = (DispatchHandleT**) calloc (2, sizeof(void*)); + dispatchHandle = DispatchLoadControl (controlConfig, controlsJ); + controlConfig->controls[0]= dispatchHandle; + } else { + int length= json_object_array_length(controlsJ); + controlConfig->controls = (DispatchHandleT**) calloc (length+1, sizeof(void*)); + + for (int jdx=0; jdx< length; jdx++) { + json_object *controlJ = json_object_array_get_idx(controlsJ,jdx); + dispatchHandle = DispatchLoadControl (controlConfig, controlJ); + controlConfig->controls[jdx]= dispatchHandle; } - controlConfig->controls[jdx]= dispatchHandle; - } - + } } if (eventsJ) { - json_object * actionsJ; - DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT)); + DispatchHandleT *dispatchHandle; + + if (json_object_get_type(eventsJ) != json_type_array) { + controlConfig->events = (DispatchHandleT**) calloc (2, sizeof(void*)); + dispatchHandle = DispatchLoadControl (controlConfig, eventsJ); + controlConfig->events[0]= dispatchHandle; + } else { + int length= json_object_array_length(eventsJ); + controlConfig->events = (DispatchHandleT**) calloc (length+1, sizeof(void*)); - err= wrap_json_unpack(eventsJ, "{so,s?s,so !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "actions",&actionsJ); - if (err) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:EVENTS Missing something label|[info]|actions in %s", json_object_get_string(eventsJ)); - goto OnErrorExit; - } - dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ); - if (!dispatchHandle->actions) { - AFB_ERROR ("DISPATCH-LOAD-CONFIG:EVENTS Error when parsing actions %s", dispatchHandle->label); - goto OnErrorExit; + for (int jdx=0; jdx< length; jdx++) { + json_object *eventJ = json_object_array_get_idx(eventsJ,jdx); + dispatchHandle = DispatchLoadControl (controlConfig, eventJ); + controlConfig->events[jdx]= dispatchHandle; } - controlConfig->events= dispatchHandle; + } } return controlConfig; @@ -377,14 +468,20 @@ OnErrorExit: return NULL; } + // Load default config file at init PUBLIC int DispatchInit () { - int index, err; + int index, err, luaLoaded=0; + char controlFile [CONTROL_MAXPATH_LEN]; + strncpy (controlFile,CONTROL_CONFIG_PRE, CONTROL_MAXPATH_LEN); + strncat (controlFile,"-", CONTROL_MAXPATH_LEN); + strncat (controlFile,GetBinderName(), CONTROL_MAXPATH_LEN); // search for default dispatch config file - json_object* responseJ = ScanForConfig(CONTROL_CONFIG_PATH, CTL_SCAN_RECURSIVE,"onload", "json"); - + json_object* responseJ = ScanForConfig(CONTROL_CONFIG_PATH, CTL_SCAN_RECURSIVE,controlFile, "json"); + + // We load 1st file others are just warnings for (index=0; index < json_object_array_length(responseJ); index++) { json_object *entryJ=json_object_array_get_idx(responseJ, index); @@ -394,24 +491,29 @@ PUBLIC int DispatchInit () { AFB_ERROR ("DISPATCH-INIT HOOPs invalid JSON entry= %s", json_object_get_string(entryJ)); goto OnErrorExit; } - - if (strcasestr(filename, CONTROL_CONFIG_FILE)) { - char filepath[CONTROL_MAXPATH_LEN]; - strncpy(filepath, fullpath, sizeof(filepath)); - strncat(filepath, "/", sizeof(filepath)); - strncat(filepath, filename, sizeof(filepath)); - configHandle = DispatchLoadConfig (filepath); - if (!configHandle) { - AFB_ERROR ("DISPATCH-INIT:ERROR No File to load [%s]", filepath); - goto OnErrorExit; + + 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)); + configHandle = DispatchLoadConfig (filepath); + if (!configHandle) { + AFB_ERROR ("DISPATCH-INIT:ERROR Fail loading [%s]", filepath); + goto OnErrorExit; + } + luaLoaded=1; + break; } - break; + } else { + AFB_WARNING ("DISPATCH-INIT:WARNING Secondary Control Config Ignored %s/%s", fullpath, filename); } } // no dispatch config found remove control API from binder - if (index == 0) { - AFB_WARNING ("DISPATCH-INIT:WARNING No Control dispatch file [%s]", CONTROL_CONFIG_FILE); + if (!luaLoaded) { + AFB_WARNING ("DISPATCH-INIT:WARNING Not Found Control dispatch file [%s]", controlFile); } AFB_NOTICE ("DISPATCH-INIT:SUCCES: Audio Control Dispatch Init"); diff --git a/Controler-afb/ctl-events.c b/Controler-afb/ctl-events.c index 6f710e3..f76feca 100644 --- a/Controler-afb/ctl-events.c +++ b/Controler-afb/ctl-events.c @@ -143,7 +143,7 @@ PUBLIC void ctlapi_event_test (afb_req request) { PUBLIC int TimerEvtInit () { // create binder event to send test pause/resume - afbevt = afb_daemon_make_event("request"); + afbevt = afb_daemon_make_event("control"); if (!afb_event_is_valid(afbevt)) { AFB_ERROR ("POLCTL_INIT: Cannot register ctl-events"); return 1; diff --git a/Controler-afb/ctl-lua.c b/Controler-afb/ctl-lua.c index 71ef8b0..c1bc5f3 100644 --- a/Controler-afb/ctl-lua.c +++ b/Controler-afb/ctl-lua.c @@ -17,12 +17,12 @@ * http://www.troubleshooters.com/codecorn/lua/lua_c_calls_lua.htm#_Anatomy_of_a_Lua_Call * http://acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/ * https://john.nachtimwald.com/2014/07/12/wrapping-a-c-library-in-lua/ + * https://gist.github.com/SONIC3D/10388137 */ #define _GNU_SOURCE #include #include -#include #include "lua.h" #include "lauxlib.h" @@ -31,15 +31,21 @@ #include "ctl-binding.h" #include "wrap-json.h" -#define LUA_FIRST_ARG 2 // when using luaL_newlib calllback receive libtable as 1st arg +#define LUA_FIST_ARG 2 // when using luaL_newlib calllback receive libtable as 1st arg #define LUA_MSG_MAX_LENGTH 255 static lua_State* luaState; - #define CTX_MAGIC 123456789 #define CTX_TOKEN "AFB_ctx" +typedef struct { + char *name; + int count; + afb_event event; +} LuaAfbEvent; +static LuaAfbEvent *luaDefaultEvt; + typedef struct { int ctxMagic; afb_req request; @@ -47,8 +53,8 @@ typedef struct { } LuaAfbContextT; typedef struct { - const char *callback; - const char *handle; + const char *callback; + json_object *context; } LuaCallServiceT; typedef enum { @@ -65,67 +71,6 @@ typedef enum { * https://stackoverflow.com/questions/45596493/lua-using-lua-newuserdata-from-lua-pcall */ -// List Avaliable Configuration Files -PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext) { - json_object *responseJ; - char *dirPath; - char* dirList= strdup(searchPath); - size_t extLen=0; - - void ScanDir (char *searchPath) { - DIR *dirHandle; - struct dirent *dirEnt; - dirHandle = opendir (searchPath); - if (!dirHandle) { - AFB_NOTICE ("CONFIG-SCANNING dir=%s not readable", searchPath); - return; - } - - //AFB_NOTICE ("CONFIG-SCANNING:ctl_listconfig scanning: %s", searchPath); - while ((dirEnt = readdir(dirHandle)) != NULL) { - - // recursively search embedded directories ignoring any directory starting by '.' or '_' - if (dirEnt->d_type == DT_DIR && mode == CTL_SCAN_RECURSIVE) { - char newpath[CONTROL_MAXPATH_LEN]; - if (dirEnt->d_name[0]=='.' || dirEnt->d_name[0]=='_') continue; - - strncpy(newpath, searchPath, sizeof(newpath)); - strncat(newpath, "/", sizeof(newpath)); - strncat(newpath, dirEnt->d_name, sizeof(newpath)); - ScanDir(newpath); - continue; - } - - // Unknown type is accepted to support dump filesystems - if (dirEnt->d_type == DT_REG || dirEnt->d_type == DT_UNKNOWN) { - - // check prefix and extention - size_t extIdx=strlen(dirEnt->d_name)-extLen; - if (extIdx <= 0) continue; - if (pre && !strcasestr (dirEnt->d_name, pre)) continue; - if (ext && strcasecmp (ext, &dirEnt->d_name[extIdx])) continue; - - struct json_object *pathJ = json_object_new_object(); - json_object_object_add(pathJ, "fullpath", json_object_new_string(searchPath)); - json_object_object_add(pathJ, "filename", json_object_new_string(dirEnt->d_name)); - json_object_array_add(responseJ, pathJ); - } - } - closedir(dirHandle); - } - - if (ext) extLen=strlen(ext); - responseJ = json_object_new_array(); - - // loop recursively on dir - for (dirPath= strtok(dirList, ":"); dirPath && *dirPath; dirPath=strtok(NULL,":")) { - ScanDir (dirPath); - } - - free (dirList); - return (responseJ); -} - STATIC LuaAfbContextT *LuaCtxCheck (lua_State *luaState, int index) { LuaAfbContextT *afbContext; //luaL_checktype(luaState, index, LUA_TUSERDATA); @@ -159,37 +104,80 @@ STATIC void LuaCtxFree (LuaAfbContextT *afbContext) { free (afbContext->info); } -STATIC int LuaPushArgument (json_object *arg) { - - switch (json_object_get_type(arg)) { - case json_type_object: + +STATIC void LuaDumpArgs(lua_State* luaState, int start) { + int count = lua_gettop(luaState); + + for (int idx=start; idx <= count; idx++) { + int luaType = lua_type(luaState, idx); + switch(luaType) { + case LUA_TNUMBER: + AFB_NOTICE ("idx=%d type=%s value=%d", idx, lua_typename(luaState, luaType), (int)lua_tonumber(luaState, idx)); + break; + case LUA_TBOOLEAN: + AFB_NOTICE ("idx=%d type=%s value=%d", idx, lua_typename(luaState, luaType), lua_toboolean(luaState, idx)); + break; + case LUA_TSTRING: + AFB_NOTICE ("idx=%d type=%s value=%s", idx, lua_typename(luaState, luaType), lua_tostring(luaState, idx)); + break; + case LUA_TTABLE: { + AFB_NOTICE ("-++-- START luatable idx=%d ", idx); + (void)LuaDumpArgs(luaState, idx+1); + AFB_NOTICE ("-++-- END luatable idx=%d ", idx); + break; + } + default: + AFB_NOTICE ("PopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType)); + } + } +} + +// Push a json structure on the stack as a LUA table +STATIC int LuaPushArgument (json_object *argsJ) { + + json_type jtype= json_object_get_type(argsJ); + switch (jtype) { + case json_type_object: { lua_newtable (luaState); - json_object_object_foreach (arg, key, val) { + json_object_object_foreach (argsJ, key, val) { int done = LuaPushArgument (val); if (done) { - lua_pushstring(luaState, key); // table.key = val - lua_settable(luaState, -3); + lua_setfield(luaState,-2, key); } } - break; + } + case json_type_array: { + int length= json_object_array_length(argsJ); + lua_newtable (luaState); + for (int idx=0; idx < length; idx ++) { + json_object *val=json_object_array_get_idx(argsJ, idx); + LuaPushArgument (val); + lua_seti (luaState,-2, idx); + } + break; + } case json_type_int: - lua_pushinteger(luaState, json_object_get_int(arg)); + lua_pushinteger(luaState, json_object_get_int(argsJ)); break; case json_type_string: - lua_pushstring(luaState, json_object_get_string(arg)); + lua_pushstring(luaState, json_object_get_string(argsJ)); break; case json_type_boolean: - lua_pushboolean(luaState, json_object_get_boolean(arg)); + lua_pushboolean(luaState, json_object_get_boolean(argsJ)); break; case json_type_double: - lua_pushnumber(luaState, json_object_get_double(arg)); + lua_pushnumber(luaState, json_object_get_double(argsJ)); break; + case json_type_null: + AFB_WARNING("LuaPushArgument: NULL object type %s", json_object_get_string(argsJ)); + return 0; + break; + default: - AFB_ERROR("LuaPushArgument: unsupported Json object type %s", json_object_get_string(arg)); + AFB_ERROR("LuaPushArgument: unsupported Json object type %s", json_object_get_string(argsJ)); return 0; - } - + } return 1; } @@ -251,7 +239,7 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) { json_object *responseJ; int stop = lua_gettop(luaState); - if(stop-start <=0) return NULL; + if(stop-start <0) return NULL; // start at 2 because we are using a function array lib if (start == stop) { @@ -267,15 +255,16 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) { return responseJ; } - STATIC void LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) { char *message; - json_object *responseJ= LuaPopArgs(luaState, LUA_FIRST_ARG); + json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG); if (!responseJ) { - message="--"; + message="-- Empty Message ???"; goto PrintMessage; - } + } + + AFB_NOTICE ("**** responseJ=%s", json_object_get_string(responseJ)); // if we have only on argument just return the value. if (json_object_get_type(responseJ)!=json_type_array || json_object_array_length(responseJ) <2) { @@ -297,15 +286,18 @@ STATIC void LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) { switch (format[++idx]) { case 'd': - targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%d", json_object_get_int(slotJ)); + if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%d", json_object_get_int(slotJ)); + else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"Nil"); break; case 'f': - targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%f", json_object_get_double(slotJ)); + if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%f", json_object_get_double(slotJ)); + else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"Nil"); break; case 's': default: - targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%s", json_object_get_string(slotJ)); + if (slotJ) targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"%s", json_object_get_string(slotJ)); + else targetIdx += snprintf (&message[targetIdx], LUA_MSG_MAX_LENGTH-targetIdx,"Nil"); } } else { @@ -359,11 +351,11 @@ STATIC int LuaPrintDebug(lua_State* luaState) { } STATIC int LuaAfbSuccess(lua_State* luaState) { - LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIRST_ARG); + LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG); if (!afbContext) goto OnErrorExit; // ignore context argument - json_object *responseJ= LuaPopArgs(luaState, LUA_FIRST_ARG+1); + json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1); afb_req_success(afbContext->request, responseJ, NULL); @@ -376,10 +368,10 @@ STATIC int LuaAfbSuccess(lua_State* luaState) { } STATIC int LuaAfbFail(lua_State* luaState) { - LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIRST_ARG); + LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG); if (!afbContext) goto OnErrorExit; - json_object *responseJ= LuaPopArgs(luaState, LUA_FIRST_ARG+1); + json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1); afb_req_fail(afbContext->request, afbContext->info, json_object_get_string(responseJ)); @@ -393,51 +385,43 @@ STATIC int LuaAfbFail(lua_State* luaState) { STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ) { LuaCallServiceT *contextCB= (LuaCallServiceT*)handle; + int count=1; - // load function (should exist in CONTROL_PATH_LUA lua_getglobal(luaState, contextCB->callback); - + // push error status & response lua_pushboolean(luaState, iserror); - (void)LuaPushArgument(responseJ); + count+= LuaPushArgument(responseJ); + count+= LuaPushArgument(contextCB->context); + + AFB_NOTICE ("*** context=%s", json_object_get_string(contextCB->context)); - int err=lua_pcall(luaState, 2, LUA_MULTRET, 0); + + 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) ); } } + STATIC int LuaAfbService(lua_State* luaState) { int count = lua_gettop(luaState); - // retrieve userdate context - LuaAfbContextT *afbContext= luaL_checkudata(luaState, 1, "CTX_TOKEN"); - if (!afbContext) { - lua_pushliteral (luaState, "LuaAfbServiceCall-Hoops no CTX_TOKEN"); - 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)) { - lua_pushliteral (luaState, "LuaAfbServiceCall-Syntax is AFB_service_call (api, verb, query, callback, handle"); + lua_pushliteral (luaState, "LuaAfbServiceCall-Syntax is AFB:service_call (api, verb, query, callback, handle ...."); 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); + LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT)); + contextCB->callback= lua_tostring(luaState, 5); + contextCB->context = LuaPopArgs(luaState, 6); - // get api/verb+query - const char *api = lua_tostring(luaState,1); - const char *verb= lua_tostring(luaState,2); - json_object *queryJ= LuaTableToJson(luaState, 3); - if (!queryJ) goto OnErrorExit; - - if (count >= 6) { - if (!lua_istable(luaState, 6)) { - lua_pushliteral (luaState, "LuaAfbServiceCall-Syntax optional handle should be a table"); - goto OnErrorExit; - } - contextCB->handle= lua_tostring(luaState, 5); - } - afb_service_call(api, verb, queryJ, LuaAfbServiceCB, contextCB); return 0; // no value return @@ -445,26 +429,84 @@ STATIC int LuaAfbService(lua_State* luaState) { OnErrorExit: lua_error(luaState); return 1; +} +STATIC int LuaAfbMakeEvent(lua_State* luaState) { + int count = lua_gettop(luaState); + LuaAfbEvent *afbevt=calloc(1,sizeof(LuaAfbEvent)); + + if (count != 1 || !lua_isstring(luaState, 1)) { + lua_pushliteral (luaState, "LuaAfbMakeEvent-Syntax is evtHandle= AFB:event ('myEventName')"); + goto OnErrorExit; + } + + // event name should be the only argument + afbevt->name= strdup (lua_tostring(luaState,1)); + + // create a new binder event + afbevt->event = afb_daemon_make_event(afbevt->name); + if (!afb_event_is_valid(afbevt->event)) { + lua_pushliteral (luaState, "LuaAfbMakeEvent-Fail to Create Binder event"); + goto OnErrorExit; + } + + // push event handler as a LUA opaque handle + lua_pushlightuserdata(luaState, afbevt); + return 1; + + OnErrorExit: + lua_error(luaState); + return 1; +} + +STATIC int LuaAfbPushEvent(lua_State* luaState) { + LuaAfbEvent *afbevt; + int index; + + // if no private event handle then use default binding event + if (lua_islightuserdata(luaState, 1)) { + afbevt = (LuaAfbEvent*) lua_touserdata(luaState, 1); + index=1; + } else { + index=2; + afbevt=luaDefaultEvt; + } + + if (!lua_isstring(luaState, index)) { + lua_pushliteral (luaState, "LuaAfbPushEvent-Syntax is AFB:signal ([evtHandle], 'myEventName', 'data-1', ... 'data-n')"); + goto OnErrorExit; + } + + // use every other arguments as event parameters + index++; + json_object *ctlEventJ= LuaTableToJson(luaState, index); + + int done = afb_event_push(afbevt->event, ctlEventJ); + if (!done) { + lua_pushliteral (luaState, "LuaAfbPushEvent-Fail to Push Binder event"); + AFB_ERROR ("LuaAfbPushEvent-Fail to Push Binder event=%s count=%d", afbevt->name, afbevt->count); + goto OnErrorExit; + } + afbevt->count++; + return 0; + + OnErrorExit: + lua_error(luaState); + return 1; } // Generated some fake event based on watchdog/counter -PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action) { +PUBLIC int LuaCallFunc (DispatchActionT *action, json_object *queryJ) { int err, count=0; - json_object* queryJ = afb_req_json(request); json_object* argsJ = action->argsJ; const char* func = action->call; // load function (should exist in CONTROL_PATH_LUA lua_getglobal(luaState, func); - // Push AFB client context on the stack - LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, func); - if (!afbContext) goto OnErrorExit; - // push argsJ on the stack if (json_object_get_type(argsJ) != json_type_array) { count+= LuaPushArgument (argsJ); @@ -473,7 +515,7 @@ PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action) { count += LuaPushArgument (json_object_array_get_idx(argsJ, idx)); } } - + // push queryJ on the stack if (json_object_get_type(queryJ) != json_type_array) { count+= LuaPushArgument (queryJ); @@ -483,8 +525,8 @@ PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action) { } } - // effectively exec LUA code (afb_reply/fail done later from callback) - err=lua_pcall(luaState, count+1, 1, 0); + // effectively exec LUA script code + err=lua_pcall(luaState, count, 1, 0); if (err) { AFB_ERROR("LuaCallFunc Fail calling %s error=%s", func, lua_tostring(luaState,-1)); goto OnErrorExit; @@ -498,7 +540,8 @@ PUBLIC int LuaCallFunc (afb_req request, DispatchActionT *action) { return -1; } -// Generated some fake event based on watchdog/counter + +// Execute LUA code from recieved API request STATIC void LuaDoAction (LuaDoActionT action, afb_req request) { int err, count=0; @@ -551,7 +594,7 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) { break; } - case LUA_DOSCRIPT: { + case LUA_DOSCRIPT: { // Fulup need to fix argument passing const char *script; json_object *args; int index; @@ -655,15 +698,24 @@ static const luaL_Reg afbFunction[] = { {"service", LuaAfbService}, {"success", LuaAfbSuccess}, {"fail" , LuaAfbFail}, + {"event" , LuaAfbMakeEvent}, + {"signal" , LuaAfbPushEvent}, + {NULL, NULL} /* sentinel */ }; // Create Binding Event at Init PUBLIC int LuaLibInit () { int err, index; - + // search for default policy config file - json_object *luaScriptPathJ = ScanForConfig(CONTROL_LUA_PATH , CTL_SCAN_RECURSIVE, "onload", "lua"); + char fullprefix[CONTROL_MAXPATH_LEN]; + strncpy (fullprefix, CONTROL_CONFIG_PRE, sizeof(fullprefix)); + strncat (fullprefix, "-", sizeof(fullprefix)); + strncat (fullprefix, GetBinderName(), sizeof(fullprefix)); + strncat (fullprefix, "-", sizeof(fullprefix)); + + json_object *luaScriptPathJ = ScanForConfig(CONTROL_LUA_PATH , CTL_SCAN_RECURSIVE, fullprefix, "lua"); // open a new LUA interpretor luaState = luaL_newstate(); @@ -679,6 +731,15 @@ PUBLIC int LuaLibInit () { luaL_newlib(luaState, afbFunction); lua_setglobal(luaState, "AFB"); + // 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;; + } + // load+exec any file found in LUA search path for (index=0; index < json_object_array_length(luaScriptPathJ); index++) { json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index); diff --git a/Controler-afb/ctl-misc.c b/Controler-afb/ctl-misc.c new file mode 100644 index 0000000..a022b38 --- /dev/null +++ b/Controler-afb/ctl-misc.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include "audio-common.h" +#include "ctl-binding.h" + + + +// List Avaliable Configuration Files +PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext) { + json_object *responseJ; + char *dirPath; + char* dirList= strdup(searchPath); + size_t extLen=0; + + void ScanDir (char *searchPath) { + DIR *dirHandle; + struct dirent *dirEnt; + dirHandle = opendir (searchPath); + if (!dirHandle) { + AFB_DEBUG ("CONFIG-SCANNING dir=%s not readable", searchPath); + return; + } + + //AFB_NOTICE ("CONFIG-SCANNING:ctl_listconfig scanning: %s", searchPath); + while ((dirEnt = readdir(dirHandle)) != NULL) { + + // recursively search embedded directories ignoring any directory starting by '.' or '_' + if (dirEnt->d_type == DT_DIR && mode == CTL_SCAN_RECURSIVE) { + char newpath[CONTROL_MAXPATH_LEN]; + if (dirEnt->d_name[0]=='.' || dirEnt->d_name[0]=='_') continue; + + strncpy(newpath, searchPath, sizeof(newpath)); + strncat(newpath, "/", sizeof(newpath)); + strncat(newpath, dirEnt->d_name, sizeof(newpath)); + ScanDir(newpath); + continue; + } + + // Unknown type is accepted to support dump filesystems + if (dirEnt->d_type == DT_REG || dirEnt->d_type == DT_UNKNOWN) { + + // check prefix and extention + size_t extIdx=strlen(dirEnt->d_name)-extLen; + if (extIdx <= 0) continue; + if (pre && !strcasestr (dirEnt->d_name, pre)) continue; + if (ext && strcasecmp (ext, &dirEnt->d_name[extIdx])) continue; + + struct json_object *pathJ = json_object_new_object(); + json_object_object_add(pathJ, "fullpath", json_object_new_string(searchPath)); + json_object_object_add(pathJ, "filename", json_object_new_string(dirEnt->d_name)); + json_object_array_add(responseJ, pathJ); + } + } + closedir(dirHandle); + } + + if (ext) extLen=strlen(ext); + responseJ = json_object_new_array(); + + // loop recursively on dir + for (dirPath= strtok(dirList, ":"); dirPath && *dirPath; dirPath=strtok(NULL,":")) { + ScanDir (dirPath); + } + + free (dirList); + return (responseJ); +} + +PUBLIC const char *GetBinderName() { + char psName[17]; + static char *binderName=NULL; + + if (binderName) return binderName; + + // retrieve binder name from process name afb-name-trailer + prctl(PR_GET_NAME, psName,NULL,NULL,NULL); + for (int idx=0; idx < sizeof(psName); idx++) { + int start; + if (psName[idx] == '-') { + start=idx+1; + for (int jdx=start; jdx < sizeof(psName); jdx++) { + if (psName[jdx] == '-') { + psName[jdx] = '\0'; + binderName=strdup(&psName[start]); + break; + } + } + break; + } + } + + return binderName; +} \ No newline at end of file diff --git a/Controler-afb/ctl-misc2.c b/Controler-afb/ctl-misc2.c new file mode 100644 index 0000000..dc225a4 --- /dev/null +++ b/Controler-afb/ctl-misc2.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE +#include +#include +#include + +#include "audio-common.h" +#include "ctl-binding.h" + + + +// Include Binding Stub generated from Json OpenAPI +#include "ctl-apidef.h" + + +PUBLIC void ctlapi_navigation (afb_req request) { + + ctlapi_dispatch ("NAVIGATION", request); +} + +PUBLIC void ctlapi_multimedia (afb_req request) { + + ctlapi_dispatch ("MULTIMEDIA", request); +} + +PUBLIC void ctlapi_emergency (afb_req request) { + + ctlapi_dispatch ("EMERGENCY", request); +} + +PUBLIC void ctlapi_monitor (afb_req request) { + + // subscribe Client to event + int err = afb_req_subscribe(request, TimerEvtGet()); + if (err != 0) { + afb_req_fail_f(request, "register-event", "Fail to subscribe binder event"); + goto OnErrorExit; + } + + afb_req_success(request, NULL, NULL); + + OnErrorExit: + return; +} + +// Create Binding Event at Init +PUBLIC int CtlBindingInit () { + + int errcount=0; + + errcount += TimerEvtInit(); + errcount += DispatchInit(); + errcount += LuaLibInit(); + + AFB_DEBUG ("Audio Policy Control Binding Done errcount=%d", errcount); + return errcount; +} + diff --git a/Controler-afb/ctl-plugin-sample.c b/Controler-afb/ctl-plugin-sample.c index ebcaee4..837ad9d 100644 --- a/Controler-afb/ctl-plugin-sample.c +++ b/Controler-afb/ctl-plugin-sample.c @@ -54,15 +54,19 @@ PUBLIC void* CtlPluginOnload(char* label, char* version, char* info) { return (void*)pluginCtx; } -PUBLIC int SamplePolicyInit (afb_req request, DispatchActionT *action, void *context) { +PUBLIC int SamplePolicyInit (DispatchActionT *action, json_object *argsJ, void *context) { MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context; + if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) { + AFB_ERROR("CONTROLER-PLUGIN-SAMPLE:SamplePolicyInit (Hoops) Invalid Sample Plugin Context"); + return -1; + }; pluginCtx->count = 0; AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:Init label=%s args=%s\n", action->label, jsonToString(action->argsJ)); return 0; } -PUBLIC int sampleControlMultimedia (afb_req request, DispatchActionT *action, void *context) { +PUBLIC int sampleControlMultimedia (DispatchActionT *action, json_object *queryJ, void *context) { MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context; if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) { @@ -70,11 +74,12 @@ PUBLIC int sampleControlMultimedia (afb_req request, DispatchActionT *action, vo return -1; }; pluginCtx->count++; - AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlMultimedia SamplePolicyCount action=%s args=%s count=%d", action->label, jsonToString(action->argsJ), pluginCtx->count); + AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlMultimedia SamplePolicyCount action=%s args=%s query=%s count=%d" + , action->label, jsonToString(action->argsJ), jsonToString(queryJ), pluginCtx->count); return 0; } -PUBLIC int sampleControlNavigation (afb_req request, DispatchActionT *action, void *context) { +PUBLIC int sampleControlNavigation (DispatchActionT *action, json_object *queryJ, void *context) { MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context; if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) { @@ -82,11 +87,12 @@ PUBLIC int sampleControlNavigation (afb_req request, DispatchActionT *action, vo return -1; }; pluginCtx->count++; - AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlNavigation SamplePolicyCount action=%s args=%s count=%d", action->label, jsonToString(action->argsJ), pluginCtx->count); + AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlNavigation SamplePolicyCount action=%s args=%s query=%s count=%d" + ,action->label, jsonToString(action->argsJ), jsonToString(queryJ), pluginCtx->count); return 0; } -PUBLIC int SampleControlEvent (afb_req request, DispatchActionT *action, void *context) { +PUBLIC int SampleControlEvent (DispatchActionT *action, json_object *queryJ, void *context) { MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context; if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) { @@ -94,6 +100,7 @@ PUBLIC int SampleControlEvent (afb_req request, DispatchActionT *action, void *c return -1; }; pluginCtx->count++; - AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlMultimedia SamplePolicyCount action=%s args=%s count=%d", action->label, jsonToString(action->argsJ), pluginCtx->count); + AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:sampleControlMultimedia SamplePolicyCount action=%s args=%s query=%s count=%d" + ,action->label, jsonToString(action->argsJ), jsonToString(queryJ), pluginCtx->count); return 0; } -- cgit 1.2.3-korg