summaryrefslogtreecommitdiffstats
path: root/Controler-afb
diff options
context:
space:
mode:
authorfulup <fulup.arfoll@iot.bzh>2017-08-13 16:50:34 +0200
committerfulup <fulup.arfoll@iot.bzh>2017-08-13 17:31:30 +0200
commit9777a02c7540fdec145feb948b4bbf1cd44c3352 (patch)
tree85f64445ef292938839092696c449d1b7c63216e /Controler-afb
parentb65178642727536972d0c04e53b2310be58beb2e (diff)
Fix AFB_MESSAGE with null arguments
Diffstat (limited to 'Controler-afb')
-rw-r--r--Controler-afb/CMakeLists.txt4
-rw-r--r--Controler-afb/ctl-apidef.h123
-rw-r--r--Controler-afb/ctl-apidef.json50
-rw-r--r--Controler-afb/ctl-binding.c3
-rw-r--r--Controler-afb/ctl-binding.h19
-rw-r--r--Controler-afb/ctl-dispatch.c396
-rw-r--r--Controler-afb/ctl-events.c2
-rw-r--r--Controler-afb/ctl-lua.c325
-rw-r--r--Controler-afb/ctl-misc.c115
-rw-r--r--Controler-afb/ctl-misc2.c74
-rw-r--r--Controler-afb/ctl-plugin-sample.c21
11 files changed, 782 insertions, 350 deletions
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);
@@ -92,6 +98,13 @@ static const struct afb_verb_v2 _afb_verbs_v2_control[] = {
.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,
.auth = &_afb_auths_v2_control[0],
@@ -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 <stdio.h>
#include <string.h>
-#include <dirent.h>
#include "lua.h"
#include "lauxlib.h"
@@ -31,24 +31,30 @@
#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;
char *info;
} 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 <fulup@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/prctl.h>
+#include <dirent.h>
+
+#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 <fulup@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "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;
}