summaryrefslogtreecommitdiffstats
path: root/Controler-afb
diff options
context:
space:
mode:
Diffstat (limited to 'Controler-afb')
-rw-r--r--Controler-afb/CMakeLists.txt79
-rw-r--r--Controler-afb/README.md234
-rw-r--r--Controler-afb/ctl-apidef.h129
-rw-r--r--Controler-afb/ctl-apidef.json281
-rw-r--r--Controler-afb/ctl-binding.c78
-rw-r--r--Controler-afb/ctl-binding.h96
-rw-r--r--Controler-afb/ctl-dispatch.c527
-rw-r--r--Controler-afb/ctl-events.c155
-rw-r--r--Controler-afb/ctl-lua.c828
-rw-r--r--Controler-afb/ctl-plugin-sample.c106
-rw-r--r--Controler-afb/ctl-policy.c221
11 files changed, 0 insertions, 2734 deletions
diff --git a/Controler-afb/CMakeLists.txt b/Controler-afb/CMakeLists.txt
deleted file mode 100644
index 78e66c8..0000000
--- a/Controler-afb/CMakeLists.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-###########################################################################
-# Copyright 2015, 2016, 2017 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.
-###########################################################################
-
-
-# Generate API-v2 hat from OpenAPI json definition
-macro(SET_TARGET_GENSKEL TARGET_NAME API_DEF_NAME)
- add_custom_command(OUTPUT ${API_DEF_NAME}.h
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- DEPENDS ${API_DEF_NAME}.json
- COMMAND afb-genskel ${API_DEF_NAME}.json >${API_DEF_NAME}.h
- )
- add_custom_target(${API_DEF_NAME}_OPENAPI DEPENDS ${API_DEF_NAME}.h)
- add_dependencies(${TARGET_NAME} ${API_DEF_NAME}_OPENAPI)
-
-endmacro(SET_TARGET_GENSKEL)
-
-# Add target to project dependency list
-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)
-
- # Generate API-v2 hat from OpenAPI json definition
- SET_TARGET_GENSKEL(${TARGET_NAME} ctl-apidef)
-
- # Binder exposes a unique public entry point
- SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
- PREFIX "afb-"
- LABELS "BINDING"
- LINK_FLAGS ${BINDINGS_LINK_FLAG}
- OUTPUT_NAME ${TARGET_NAME}
- )
-
- # Library dependencies (include updates automatically)
- TARGET_LINK_LIBRARIES(${TARGET_NAME}
- audio-common
- ${link_libraries}
- )
-
- # installation directory
- INSTALL(TARGETS ${TARGET_NAME}
- LIBRARY DESTINATION CMAKE_INSTALL_PREFIX )
-
-PROJECT_TARGET_ADD(audio-plugin-sample)
-
- # Define targets
- ADD_LIBRARY(${TARGET_NAME} MODULE ctl-plugin-sample.c)
-
- # Alsa Plugin properties
- SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
- PREFIX ${CTL_PLUGIN_PRE}
- SUFFIX ${CTL_PLUGIN_EXT}
- OUTPUT_NAME ${TARGET_NAME}
- )
-
- # Library dependencies (include updates automatically)
- TARGET_LINK_LIBRARIES(${TARGET_NAME}
- audio-common
- ${link_libraries}
- )
-
- # installation directory
- INSTALL(TARGETS ${TARGET_NAME}
- LIBRARY DESTINATION ${BINDINGS_INSTALL_DIR}/controler)
diff --git a/Controler-afb/README.md b/Controler-afb/README.md
deleted file mode 100644
index 3274ede..0000000
--- a/Controler-afb/README.md
+++ /dev/null
@@ -1,234 +0,0 @@
-Controler AAAA(AGL Advance Audio Controler) and more.
-------------------------------------------------------------
-
- * Object: Generic Controler to handle Policy,Small Business Logic, Glue in between components, ...
- * Status: Release Candidate
- * Author: Fulup Ar Foll fulup@iot.bzh
- * Date : August-2017
-
-## Functionalities:
- - Create an application dedicate controller from a JSON config file
- - Each controls (eg: navigation, multimedia, ...) is a suite of actions. When all actions succeed control is granted, if one fail control acces is denied.
- - Actions can either be:
- + Invocation to an other binding API, either internal or external (eg: a policy service, Alsa UCM, ...)
- + C routines from a user provider plugin (eg: policy routine, proprietary code, ...)
- + LUA script function. LUA provides access to every AGL appfw functionalities and can be extended from C user provided plugins.
-
-## Installation
- - Controler is a native part of AGL Advance Audio Framework but may be used independently with any other service or application binder.
- - Dependencies: the only dependencies are audio-common for JSON-WRAP and Filescan-utils capabilities.
- - Controler relies on LUA-5.3, when not needed LUA might be removed at compilation time.
-
-## Config
-
-Configuration is loaded dynamically during startup time. The controller scans CONTROL_CONFIG_PATH for a file corresponding to pattern
-"onload-bindername-xxxxx.json". When controller runs within AAAA binder it searches for "onload-audio-xxxx.json". First file found in the path the loaded
-any other files corresponding to the same pather are ignored and only generate a warning.
-
-Each bloc in the configuration file are defined with
- * label: must be provided is used either for debugging or as input for the action (eg: signal name, control name, ...)
- * info: optional used for documentation purpose only
-
-### Config is organised in 4 sections:
-
- * metadata
- * onload defines the set of action to be executed at startup time
- * control defines the set of controls with corresponding actions
- * event define the set of actions to be executed when receiving a given signal
-
-### Metadata
-
-As today matadata is only used for documentation purpose.
- * label + version mandatory
- * info optional
-
-### OnLoad section
-
-Defines startup time configuration. Onload may provide multiple initialisation profiles, each with a different label.
- * label is mandatory. Label is used to select onload profile at initialisation through DispatchOneOnLoad("onload-label") API;
- * info is optional
- * plugin provides optional unique plugin name. Plugin should follow "onload-bindername-xxxxx.ctlso" patern
- and are search into CONTROL_PLUGIN_PATH. When defined controller will execute user provided function context=CTLP_ONLOAD(label,version,info).
- The context returned by this routine is provided back to any C routines call later by the controller.
- * lua2c list of LUA commands shipped with provided plugin.
- * require list of binding that should be initialised before the controller starts. Note that some listed requirer binding might be absent,
- nevertheless any present binding from this list will be started before controller binding, missing ones generate a warning.
- * action the list of action to execute during loadtime. Any failure in action will prevent controller binding from starting.
-
-### Control section
-
-Defines a list of controls that are accessible through (api="control", verb="request", control="control-label").
-
- * label mandatory
- * info optional
- * privileges needed privileges to request this control
- * action the list of actions
-
-### Event section
-
-Defines a list of actions to be executed on event reception. Even can do anything a controller can (change state,
-send back signal, ...) eg: if a controller subscribes to vehicule speed, then speed-event may ajust master-volume to speed.
-
- * label mandatory
- * info optional
- * action the list of actions
-
-### Actions Categories
-
-Controler support tree categories of actions. Each action return a status status where 0=success and 1=failure.
- * AppFw API, Provides a generic model to request other bindings. Requested binding can be local (eg: ALSA/UCM) or
- external (eg: vehicle signalling).
- * api provides requested binding API name
- * verb provides verb to requested binding
- * args optionally provides a jsonc object for targeted binding API. Note that 'args' are statically defined
- in JSON configuration file. Controler client may also provided its own arguments from the query list. Targeted
- binding receives both arguments defined in the config file and the argument provided by controller client.
- * C-API, when defined in the onload section, the plugin may provided C native API with CTLP-CAPI(apiname, label, args, query, context).
- Plugin may also create LUA command with CTLP-LUA2C(LuaFuncName, label, args, query, context). Where args+query are JSONC object
- and context the value return from CTLP_ONLOAD function. Any missing value is set to NULL.
- * LUA-API, when compiled with LUA option, the controller support action defined directly in LUA script. During "onload" phase the
- controller search in CONTROL_LUA_PATH file with pattern "onload-bindername-xxxx.lua". Any file corresponding to this pattern
- is automatically loaded. Any function defined in those LUA script can be called through a controller action. LUA functions receive
- three parameters (label, args, query).
-
-## Config Sample
-
-Here after a simple configuration sample.
-
-```
-{
- "$schema": "ToBeDone",
- "metadata": {
- "label": "sample-audio-control",
- "info": "Provide Default Audio Policy for Multimedia, Navigation and Emergency",
- "version": "1.0"
- },
- "onload": [{
- "label": "onload-default",
- "info": "onload initialisation config",
- "plugin": "ctl-audio-plugin-sample.ctlso",
- "require": ["intel-hda", "jabra-usb", "scarlett-usb"],
- "actions": [
- {
- "label": "onload-sample-cb",
- "info": "Call control sharelib install entrypoint",
- "callback": "SamplePolicyInit",
- "args": {
- "arg1": "first_arg",
- "nextarg": "second arg value"
- }
- }, {
- "label": "onload-sample-api",
- "info": "Assert AlsaCore Presence",
- "api": "alsacore",
- "verb": "ping",
- "args": "test"
- }, {
- "label": "onload-hal-lua",
- "info": "Load avaliable HALs",
- "lua": "Audio_Init_Hal"
- }
- ]
- }],
- "controls":
- [
- {
- "label": "multimedia",
- "actions": {
- "label": "multimedia-control-lua",
- "info": "Call Lua Script function Test_Lua_Engin",
- "lua": "Audio_Set_Multimedia"
- }
- }, {
- "label": "navigation",
- "actions": {
- "label": "navigation-control-lua",
- "info": "Call Lua Script to set Navigation",
- "lua": "Audio_Set_Navigation"
- }
- }, {
- "label": "emergency",
- "actions": {
- "label": "emergency-control-ucm",
- "lua": "Audio_Set_Emergency"
- }
- }, {
- "label": "multi-step-sample",
- "info" : "all actions must succeed for control to be accepted",
- "actions": [{
- "label": "multimedia-control-cb",
- "info": "Call Sharelib Sample Callback",
- "callback": "sampleControlNavigation",
- "args": {
- "arg1": "snoopy",
- "arg2": "toto"
- }
- }, {
- "label": "navigation-control-ucm",
- "api": "alsacore",
- "verb": "ping",
- "args": {
- "test": "navigation"
- }
- }, {
- "label": "navigation-control-lua",
- "info": "Call Lua Script to set Navigation",
- "lua": "Audio_Set_Navigation"
- }]
- }
- ],
- "events":
- [
- {
- "label": "Vehicle-Speed",
- "info": "Action when Vehicule speed change",
- "actions": [
- {
- "label": "speed-action-1",
- "callback": "Blink-when-over-130",
- "args": {
- "speed": 130
- "blink-speed": 1000
- }
- }, {
- "label": "Adjust-Volume",
- "lua": "Adjust_Volume_To_Speed",
- }
- ]
- },
- {
- "label": "Reverse-Engage",
- "info": "When Reverse Gear is Engage",
- "actions": [
- {
- "label": "Display-Rear-Camera",
- "callback": "Display-Rear-Camera",
- }, {
- "label": "Prevent-Phone-Call",
- "api" : "phone",
- "verb" : "status",
- "args": {
- "call-accepted": false
- }
- }
- ]
- },
- {
- "label": "Neutral-Engage",
- "info": "When Reverse Neutral is Engage",
- "actions": [
- {
- "label": "Authorize-Video",
- "api" : "video",
- "verb" : "status",
- "args": {
- "tv-accepted": true
- }
- }
- ]
- }
- ]
-}
-
-```
-
diff --git a/Controler-afb/ctl-apidef.h b/Controler-afb/ctl-apidef.h
deleted file mode 100644
index 83b3308..0000000
--- a/Controler-afb/ctl-apidef.h
+++ /dev/null
@@ -1,129 +0,0 @@
-
-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\":\"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\"}}}},\"/select\":{\"description\":\"Request Access to Naviga"
- "tion Audio Channel.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/component"
- "s/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"name\""
- ":\"zone\",\"required\":false,\"schema\":{\"type\":\"string\"}}],\"respon"
- "ses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/lua_docal"
- "l\":{\"description\":\"Execute LUA string script.\",\"get\":{\"x-permiss"
- "ions\":{\"$ref\":\"#/components/x-permissions/navigation\"},\"parameters"
- "\":[{\"in\":\"query\",\"name\":\"func\",\"required\":true,\"schema\":{\""
- "type\":\"string\"}},{\"in\":\"query\",\"name\":\"args\",\"required\":fal"
- "se,\"schema\":{\"type\":\"array\"}}],\"responses\":{\"200\":{\"$ref\":\""
- "#/components/responses/200\"}}}},\"/lua_dostring\":{\"description\":\"Ex"
- "ecute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/comp"
- "onents/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"r"
- "equired\":true,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\""
- ":{\"$ref\":\"#/components/responses/200\"}}}},\"/lua_doscript\":{\"descr"
- "iption\":\"Execute LUA string script.\",\"get\":{\"x-permissions\":{\"$r"
- "ef\":\"#/components/x-permissions/navigation\"},\"parameters\":[{\"in\":"
- "\"query\",\"name\":\"filename\",\"required\":true,\"schema\":{\"type\":\""
- "string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/20"
- "0\"}}}}}}"
-;
-
-static const struct afb_auth _afb_auths_v2_control[] = {
- { .type = afb_auth_Permission, .text = "urn:AGL:permission:audio:public:monitor" }
-};
-
- void ctlapi_monitor(struct afb_req req);
- void ctlapi_event_test(struct afb_req req);
- void ctlapi_select(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);
-
-static const struct afb_verb_v2 _afb_verbs_v2_control[] = {
- {
- .verb = "monitor",
- .callback = ctlapi_monitor,
- .auth = &_afb_auths_v2_control[0],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "event_test",
- .callback = ctlapi_event_test,
- .auth = &_afb_auths_v2_control[0],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "select",
- .callback = ctlapi_select,
- .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],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "lua_dostring",
- .callback = ctlapi_lua_dostring,
- .auth = &_afb_auths_v2_control[0],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "lua_doscript",
- .callback = ctlapi_lua_doscript,
- .auth = &_afb_auths_v2_control[0],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- { .verb = NULL }
-};
-
-const struct afb_binding_v2 afbBindingV2 = {
- .api = "control",
- .specification = _afb_description_v2_control,
- .info = NULL,
- .verbs = _afb_verbs_v2_control,
- .preinit = NULL,
- .init = CtlBindingInit,
- .onevent = DispatchOneEvent,
- .noconcurrency = 0
-};
-
diff --git a/Controler-afb/ctl-apidef.json b/Controler-afb/ctl-apidef.json
deleted file mode 100644
index 818dd80..0000000
--- a/Controler-afb/ctl-apidef.json
+++ /dev/null
@@ -1,281 +0,0 @@
-{
- "openapi": "3.0.0",
- "$schema": "http:iot.bzh/download/openapi/schema-3.0/default-schema.json",
- "info": {
- "description": "",
- "title": "controler",
- "version": "1.0",
- "x-binding-c-generator": {
- "api": "control",
- "version": 2,
- "prefix": "ctlapi_",
- "postfix": "",
- "start": null,
- "onevent": "DispatchOneEvent",
- "init": "CtlBindingInit",
- "scope": "",
- "private": false
- }
- },
- "servers": [
- {
- "url": "ws://{host}:{port}/api/polctl",
- "description": "Unicens2 API.",
- "variables": {
- "host": {
- "default": "localhost"
- },
- "port": {
- "default": "1234"
- }
- },
- "x-afb-events": [
- {
- "$ref": "#/components/schemas/afb-event"
- }
- ]
- }
- ],
- "components": {
- "schemas": {
- "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": {
- "type": "string"
- },
- "token": {
- "type": "string"
- },
- "uuid": {
- "type": "string"
- },
- "reqid": {
- "type": "string"
- }
- }
- },
- "response": {
- "type": "object"
- }
- }
- },
- "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:audio:public:monitor"
- },
- "multimedia": {
- "permission": "urn:AGL:permission:audio:public:monitor"
- },
- "navigation": {
- "permission": "urn:AGL:permission:audio:public: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"
- },
- "parameters": [
- {
- "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-permissions/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"
- }
- }
- }
- },
- "/select": {
- "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": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/navigation"
- },
- "parameters": [
- {
- "in": "query",
- "name": "func",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "in": "query",
- "name": "args",
- "required": false,
- "schema": {
- "type": "array"
- }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200"
- }
- }
- }
- },
- "/lua_dostring": {
- "description": "Execute LUA string script.",
- "get": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/navigation"
- },
- "parameters": [
- {
- "in": "query",
- "required": true,
- "schema": {
- "type": "string"
- }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200"
- }
- }
- }
- },
- "/lua_doscript": {
- "description": "Execute LUA string script.",
- "get": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/navigation"
- },
- "parameters": [
- {
- "in": "query",
- "name": "filename",
- "required": true,
- "schema": {
- "type": "string"
- }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200"
- }
- }
- }
- }
- }
-}
diff --git a/Controler-afb/ctl-binding.c b/Controler-afb/ctl-binding.c
deleted file mode 100644
index 554199b..0000000
--- a/Controler-afb/ctl-binding.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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();
-
- // now that everything is initialised execute the onload action
- if (!errcount)
- 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
deleted file mode 100644
index a2cedbf..0000000
--- a/Controler-afb/ctl-binding.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-
-#ifndef CONTROLER_BINDING_INCLUDE
-#define CONTROLER_BINDING_INCLUDE
-
-#define AFB_BINDING_VERSION 2
-#include <afb/afb-binding.h>
-#include <json-c/json.h>
-#include <filescan-utils.h>
-#include <wrap-json.h>
-
-#ifndef PUBLIC
- #define PUBLIC
-#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;
- char *label;
-} CtlPluginMagicT;
-
-#define CTL_PLUGIN_REGISTER(pluglabel) CtlPluginMagicT CtlPluginMagic={.magic=CTL_PLUGIN_MAGIC,.label=pluglabel}; struct afb_binding_data_v2;
-
-
-// polctl-binding.c
-PUBLIC int CtlBindingInit ();
-
-// ctl-timerevt.c
-// ----------------------
-PUBLIC int TimerEvtInit (void);
-PUBLIC afb_event TimerEvtGet(void);
-PUBLIC void ctlapi_event_test (afb_req request);
-
-// ctl-policy
-// -----------
-
-typedef enum {
- CTL_MODE_NONE=0,
- CTL_MODE_API,
- CTL_MODE_CB,
- CTL_MODE_LUA,
-} CtlRequestModeT;
-
-typedef struct DispatchActionS{
- const char *info;
- const char* label;
- CtlRequestModeT mode;
- const char* api;
- const char* call;
- json_object *argsJ;
- int timeout;
- 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
-
-typedef enum {
- LUA_DOCALL,
- LUA_DOSTRING,
- LUA_DOSCRIPT,
-} LuaDoActionT;
-
-PUBLIC int LuaLibInit ();
-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);
-
-#endif
diff --git a/Controler-afb/ctl-dispatch.c b/Controler-afb/ctl-dispatch.c
deleted file mode 100644
index 0594952..0000000
--- a/Controler-afb/ctl-dispatch.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author Fulup Ar Foll <fulup@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, something express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Reference:
- * Json load using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <dlfcn.h>
-
-#include "ctl-binding.h"
-
-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;
- DispatchActionT *actions;
-} DispatchHandleT;
-
-typedef struct {
- const char* label;
- const char *info;
- const char *version;
- void *context;
- char *plugin;
- void *dlHandle;
- DispatchHandleT **onloads;
- DispatchHandleT **events;
- DispatchHandleT **controls;
-} DispatchConfigT;
-
-// global config handle
-STATIC DispatchConfigT *configHandle = NULL;
-
-STATIC int DispatchControlToIndex(DispatchHandleT **controls, const char* controlLabel) {
-
- for (int idx=0; controls[idx]; idx++) {
- if (!strcasecmp(controlLabel, controls[idx]->label)) return idx;
- }
- return -1;
-}
-
-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;
- }
-
- 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;
- }
-
- // loop on action for this control
- DispatchActionT *actions=controls[index]->actions;
- for (int idx=0; actions[idx].label; idx++) {
-
- switch (actions[idx].mode) {
- case CTL_MODE_API: {
- json_object *returnJ;
-
- 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) {
- 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 (&actions[idx], queryJ);
- if (err) {
- static const char*format= "DispatchOneControl(Lua) label=%s func=%s args=%s";
- if (afb_req_is_valid(request)) afb_req_fail_f(request, "DISPATCH-CTL-MODE:Lua", format, actions[idx].label, actions[idx].call, json_object_get_string(actions[idx].argsJ));
- else AFB_ERROR (format, actions[idx].label, actions[idx].call, json_object_get_string(actions[idx].argsJ));
- goto OnErrorExit;
- }
- break;
-
- case CTL_MODE_CB:
- err= (*actions[idx].actionCB) (&actions[idx], queryJ, configHandle->context);
- if (err) {
- static const char*format="DispatchOneControl(Callback) label%s func=%s args=%s";
- if (afb_req_is_valid(request)) afb_req_fail_f(request, "DISPATCH-CTL-MODE:Cb", format, actions[idx].label, actions[idx].call, json_object_get_string(actions[idx].argsJ));
- else AFB_ERROR (format, actions[idx].label, actions[idx].call, json_object_get_string(actions[idx].argsJ));
- goto OnErrorExit;
- }
- break;
-
- default:{
- static const char*format="DispatchOneControl(unknown) mode control=%s action=%s";
- AFB_ERROR (format, controls[index]->label);
- if (afb_req_is_valid(request))afb_req_fail_f(request, "DISPATCH-CTL-MODE:Unknown", format, controls[index]->label);
- }
- }
- }
-
- // everything when fine
- if(afb_req_is_valid(request))afb_req_success(request,NULL,controls[index]->label);
- return 0;
-
- 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* 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);
- AFB_NOTICE ("CONFIG-MISSING: use default CONTROL_CONFIG_PATH=%s", CONTROL_CONFIG_PATH);
- }
-
- // get list of config file
- struct json_object *responseJ = ScanForConfig(dirList, CTL_SCAN_RECURSIVE, "onload", "json");
-
- if (json_object_array_length(responseJ) == 0) {
- afb_req_fail(request, "CONFIGPATH:EMPTY", "No Config Found in CONTROL_CONFIG_PATH");
- } else {
- afb_req_success(request, responseJ, NULL);
- }
-
- return;
-}
-
-// unpack individual action object
-STATIC int DispatchLoadOneAction (DispatchConfigT *controlConfig, json_object *actionJ, DispatchActionT *action) {
- char *api=NULL, *verb=NULL, *callback=NULL, *lua=NULL;
- int err, modeCount=0;
-
- err= wrap_json_unpack(actionJ, "{ss,s?s,s?s,s?s,s?s,s?s,s?o !}"
- , "label",&action->label, "info",&action->info, "callback",&callback, "lua", &lua, "api",&api, "verb", &verb, "args",&action->argsJ);
- if (err) {
- AFB_ERROR ("DISPATCH-LOAD-ACTION Missing something label|info|callback|lua|(api+verb)|args in %s", json_object_get_string(actionJ));
- goto OnErrorExit;
- }
-
- if (lua) {
- action->mode = CTL_MODE_LUA;
- action->call=lua;
- modeCount++;
- }
-
- if (api && verb) {
- action->mode = CTL_MODE_API;
- action->api=api;
- action->call=verb;
- modeCount++;
- }
-
- if (callback && controlConfig->dlHandle) {
- action->mode = CTL_MODE_CB;
- action->call=callback;
- modeCount++;
-
- action->actionCB = dlsym(controlConfig->dlHandle, callback);
- if (!action->actionCB) {
- AFB_ERROR ("DISPATCH-LOAD-ACTION fail to find calbback=%s in %s", callback, controlConfig->plugin);
- goto OnErrorExit;
- }
- }
-
- // make sure at least one mode is selected
- if (modeCount == 0) {
- AFB_ERROR ("DISPATCH-LOAD-ACTION No Action Selected lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
- goto OnErrorExit;
- }
-
- if (modeCount > 1) {
- AFB_ERROR ("DISPATCH-LOAD-ACTION:ToMany arguments lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
- goto OnErrorExit;
- }
- return 0;
-
-OnErrorExit:
- return -1;
-};
-
-STATIC DispatchActionT *DispatchLoadActions (DispatchConfigT *controlConfig, json_object *actionsJ) {
- int err;
- DispatchActionT *actions;
-
- // action array is close with a nullvalue;
- if (json_object_get_type(actionsJ) == json_type_array) {
- int count = json_object_array_length(actionsJ);
- actions = calloc (count+1, sizeof(DispatchActionT));
-
- for (int idx=0; idx < count; idx++) {
- json_object *actionJ = json_object_array_get_idx(actionsJ, idx);
- err = DispatchLoadOneAction (controlConfig, actionJ, &actions[idx]);
- if (err) goto OnErrorExit;
- }
-
- } else {
- actions = calloc (2, sizeof(DispatchActionT));
- err = DispatchLoadOneAction (controlConfig, actionsJ, &actions[0]);
- if (err) goto OnErrorExit;
- }
-
- return actions;
-
- OnErrorExit:
- return NULL;
-
-}
-
-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;
- int err;
-
- // Load JSON file
- controlConfigJ= json_object_from_file(filepath);
- if (!controlConfigJ) {
- AFB_ERROR ("DISPATCH-LOAD-CONFIG:JsonLoad invalid JSON %s ", filepath);
- goto OnErrorExit;
- }
-
- AFB_INFO ("DISPATCH-LOAD-CONFIG: loading config filepath=%s", filepath);
-
- 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;
- }
-
- DispatchConfigT *controlConfig = calloc (1, sizeof(DispatchConfigT));
- if (metadataJ) {
- err= wrap_json_unpack(metadataJ, "{ss,s?s,ss !}", "label", &controlConfig->label, "info",&controlConfig->info, "version",&controlConfig->version);
- if (err) {
- AFB_ERROR ("DISPATCH-LOAD-CONFIG:METADATA Missing something label|version|[label] in %s", json_object_get_string(metadataJ));
- goto OnErrorExit;
- }
- }
-
- if (onloadsJ) {
- DispatchHandleT *dispatchHandle;
-
- 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;
- }
- }
- }
-
- if (controlsJ) {
- DispatchHandleT *dispatchHandle;
-
- 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;
- }
- }
- }
-
- if (eventsJ) {
- 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*));
-
- 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;
- }
- }
- }
-
- return controlConfig;
-
-OnErrorExit:
- return NULL;
-}
-
-
-// Load default config file at init
-PUBLIC int DispatchInit () {
- 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,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);
-
- char *filename; char*fullpath;
- err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename);
- if (err) {
- AFB_ERROR ("DISPATCH-INIT HOOPs invalid JSON entry= %s", json_object_get_string(entryJ));
- 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;
- }
- } else {
- AFB_WARNING ("DISPATCH-INIT:WARNING Secondary Control Config Ignored %s/%s", fullpath, filename);
- }
- }
-
- // no dispatch config found remove control API from binder
- if (!luaLoaded) {
- AFB_WARNING ("DISPATCH-INIT:WARNING Not Found Control dispatch file [%s]", controlFile);
- }
-
- AFB_NOTICE ("DISPATCH-INIT:SUCCES: Audio Control Dispatch Init");
- return 0;
-
-OnErrorExit:
- AFB_NOTICE ("DISPATCH-INIT:ERROR: Audio Control Dispatch Init");
- return 1;
-}
-
-
-
diff --git a/Controler-afb/ctl-events.c b/Controler-afb/ctl-events.c
deleted file mode 100644
index 18aac53..0000000
--- a/Controler-afb/ctl-events.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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 <systemd/sd-event.h>
-
-#include "ctl-binding.h"
-
-#define DEFAULT_PAUSE_DELAY 3000
-#define DEFAULT_TEST_COUNT 1
-typedef int (*timerCallbackT)(void *context);
-typedef struct {
- int value;
- const char *label;
-} AutoTestCtxT;
-
-typedef struct TimerHandleS {
- int count;
- int delay;
- AutoTestCtxT *context;
- timerCallbackT callback;
- sd_event_source *evtSource;
-} TimerHandleT;
-
-static afb_event afbevt;
-
-STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
- TimerHandleT *timerHandle = (TimerHandleT*) handle;
- int done;
- uint64_t usec;
-
- // Rearm timer if needed
- timerHandle->count --;
- if (timerHandle->count == 0) sd_event_source_unref(source);
- else {
- // otherwise validate timer for a new run
- sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec);
- sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
- sd_event_source_set_time(source, usec + timerHandle->delay);
- }
-
- done= timerHandle->callback(timerHandle->context);
- if (!done) goto OnErrorExit;
-
- return 0;
-
-OnErrorExit:
- AFB_WARNING("TimerNext Callback Fail Tag=%s", timerHandle->context->label);
- return -1;
-}
-
-
-STATIC int DoSendEvent (void *context) {
- AutoTestCtxT *ctx= (AutoTestCtxT*)context;
- json_object *ctlEventJ;
-
- if (ctx->value) ctx->value =0;
- else ctx->value =1;
-
- ctlEventJ = json_object_new_object();
- json_object_object_add(ctlEventJ,"signal", json_object_new_string(ctx->label));
- json_object_object_add(ctlEventJ,"value" , json_object_new_int(ctx->value));
- int done = afb_event_push(afbevt, ctlEventJ);
-
- AFB_NOTICE ("DoSendEvent {action: '%s', value:%d} status=%d", ctx->label, ctx->value, done);
-
- return (done);
-}
-
-STATIC void TimerEvtStart(TimerHandleT *timerHandle, void *context) {
- uint64_t usec;
-
- // populate CB handle
- timerHandle->callback=DoSendEvent;
- timerHandle->context=context;
-
- // set a timer with ~250us accuracy
- sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec);
- sd_event_add_time(afb_daemon_get_event_loop(), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay, 250, TimerNext, timerHandle);
-}
-
-PUBLIC afb_event TimerEvtGet(void) {
- return afbevt;
-}
-
-
-// Generated some fake event based on watchdog/counter
-PUBLIC void ctlapi_event_test (afb_req request) {
- json_object *queryJ, *tmpJ;
- TimerHandleT *timerHandle = malloc (sizeof (TimerHandleT));
- AutoTestCtxT *context = calloc (1, sizeof (AutoTestCtxT));
- int done;
-
- queryJ= afb_req_json(request);
-
- // Closing call only has one parameter
- done=json_object_object_get_ex(queryJ, "closing", &tmpJ);
- if (done) return;
-
- done=json_object_object_get_ex(queryJ, "label", &tmpJ);
- if (!done) {
- afb_req_fail_f(request, "TEST-LABEL-MISSING", "label is mandatory for event_test");
- goto OnErrorExit;
- }
- context->label = strdup(json_object_get_string (tmpJ));
-
- json_object_object_get_ex(queryJ, "delay", &tmpJ);
- timerHandle->delay = json_object_get_int (tmpJ) * 1000;
- if (timerHandle->delay == 0) timerHandle->delay=DEFAULT_PAUSE_DELAY * 1000;
-
- json_object_object_get_ex(queryJ, "count", &tmpJ);
- timerHandle->count = json_object_get_int (tmpJ);
- if (timerHandle->count == 0) timerHandle->count=DEFAULT_TEST_COUNT;
-
- // start a lool timer
- TimerEvtStart (timerHandle, context);
-
- afb_req_success(request, NULL, NULL);
- return;
-
- OnErrorExit:
- return;
-}
-
-// Create Binding Event at Init
-PUBLIC int TimerEvtInit () {
-
- // create binder event to send test pause/resume
- afbevt = afb_daemon_make_event("control");
- if (!afb_event_is_valid(afbevt)) {
- AFB_ERROR ("POLCTL_INIT: Cannot register ctl-events");
- return 1;
- }
-
- AFB_DEBUG ("Audio Control-Events Init Done");
- return 0;
-}
-
diff --git a/Controler-afb/ctl-lua.c b/Controler-afb/ctl-lua.c
deleted file mode 100644
index bf02a31..0000000
--- a/Controler-afb/ctl-lua.c
+++ /dev/null
@@ -1,828 +0,0 @@
-/*
- * 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.
- * ref:
- * 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 "lua.h"
-#include "lauxlib.h"
-#include "lualib.h"
-
-#include "ctl-binding.h"
-#include "wrap-json.h"
-
-#define LUA_FIST_ARG 2 // when using luaL_newlib calllback receive libtable as 1st arg
-#define LUA_MSG_MAX_LENGTH 255
-#define JSON_ERROR (json_object*)-1
-
-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;
- json_object *context;
-} LuaCallServiceT;
-
-typedef enum {
- AFB_MSG_INFO,
- AFB_MSG_WARNING,
- AFB_MSG_NOTICE,
- AFB_MSG_DEBUG,
- AFB_MSG_ERROR,
-} LuaAfbMessageT;
-
-/*
- * Note(Fulup): I fail to use luaL_setmetatable and replaced it with a simple opaque
- * handle while waiting for someone smarter than me to find a better solution
- * https://stackoverflow.com/questions/45596493/lua-using-lua-newuserdata-from-lua-pcall
- */
-
-STATIC LuaAfbContextT *LuaCtxCheck (lua_State *luaState, int index) {
- LuaAfbContextT *afbContext;
- //luaL_checktype(luaState, index, LUA_TUSERDATA);
- //afbContext = (LuaAfbContextT *)luaL_checkudata(luaState, index, CTX_TOKEN);
- luaL_checktype(luaState, index, LUA_TLIGHTUSERDATA);
- afbContext = (LuaAfbContextT *) lua_touserdata(luaState, index);
- if (afbContext == NULL && afbContext->ctxMagic != CTX_MAGIC) {
- luaL_error(luaState, "Fail to retrieve user data context=%s", CTX_TOKEN);
- AFB_ERROR ("afbContextCheck error retrieving afbContext");
- return NULL;
- }
- return afbContext;
-}
-
-STATIC LuaAfbContextT *LuaCtxPush (lua_State *luaState, afb_req request, const char* info) {
- // LuaAfbContextT *afbContext = (LuaAfbContextT *)lua_newuserdata(luaState, sizeof(LuaAfbContextT));
- // luaL_setmetatable(luaState, CTX_TOKEN);
- LuaAfbContextT *afbContext = (LuaAfbContextT *)calloc(1, sizeof(LuaAfbContextT));
- lua_pushlightuserdata(luaState, afbContext);
- if (!afbContext) {
- AFB_ERROR ("LuaCtxPush fail to allocate user data context");
- return NULL;
- }
- afbContext->ctxMagic=CTX_MAGIC;
- afbContext->info=strdup(info);
- afbContext->request= request;
- return afbContext;
-}
-
-STATIC void LuaCtxFree (LuaAfbContextT *afbContext) {
- free (afbContext->info);
-}
-
-// Push a json structure on the stack as a LUA table
-STATIC int LuaPushArgument (json_object *argsJ) {
-
- //AFB_NOTICE("LuaPushArgument argsJ=%s", json_object_get_string(argsJ));
-
- json_type jtype= json_object_get_type(argsJ);
- switch (jtype) {
- case json_type_object: {
- lua_newtable (luaState);
- json_object_object_foreach (argsJ, key, val) {
- int done = LuaPushArgument (val);
- if (done) {
- 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(argsJ));
- break;
- case json_type_string:
- lua_pushstring(luaState, json_object_get_string(argsJ));
- break;
- case json_type_boolean:
- lua_pushboolean(luaState, json_object_get_boolean(argsJ));
- break;
- case json_type_double:
- 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(argsJ));
- return 0;
- }
- return 1;
-}
-
-STATIC json_object *PopOneArg (lua_State* luaState, int idx);
-
-STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
- int idx;
-
- json_object *tableJ= json_object_new_object();
- const char *key;
- char number[3];
- lua_pushnil(luaState); // 1st key
- for (idx=1; lua_next(luaState, index) != 0; idx++) {
-
- // uses 'key' (at index -2) and 'value' (at index -1)
- if (lua_type(luaState,-2) == LUA_TSTRING) key= lua_tostring(luaState, -2);
- else {
- snprintf(number, sizeof(number),"%d", idx);
- key=number;
- }
- json_object *argJ= PopOneArg(luaState, -1);
- json_object_object_add(tableJ, key, argJ);
- lua_pop(luaState, 1); // removes 'value'; keeps 'key' for next iteration
- }
-
- // Query is empty free empty json object
- if (idx == 1) {
- json_object_put(tableJ);
- return NULL;
- }
- return tableJ;
-}
-
-STATIC json_object *PopOneArg (lua_State* luaState, int idx) {
- json_object *value=NULL;
-
- int luaType = lua_type(luaState, idx);
- switch(luaType) {
- case LUA_TNUMBER: {
- lua_Number number= lua_tonumber(luaState, idx);;
- int nombre = (int)number; // evil trick to determine wether n fits in an integer. (stolen from ltcl.c)
- if (number == nombre) {
- value= json_object_new_int((int)number);
- } else {
- value= json_object_new_double(number);
- }
- break;
- }
- case LUA_TBOOLEAN:
- value= json_object_new_boolean(lua_toboolean(luaState, idx));
- break;
- case LUA_TSTRING:
- value= json_object_new_string(lua_tostring(luaState, idx));
- break;
- case LUA_TTABLE: {
- if (idx > 0) {
- value= LuaTableToJson(luaState, idx);
- } else {
- value= json_object_new_string("UNSUPPORTED_Lua_Nested_Table");
- }
- break;
- }
- case LUA_TNIL:
- value=json_object_new_string("nil") ;
- break;
-
- default:
- AFB_NOTICE ("PopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType));
- value=NULL;
- }
-
- return value;
-}
-
-static json_object *LuaPopArgs (lua_State* luaState, int start) {
- json_object *responseJ;
-
- int stop = lua_gettop(luaState);
- if(stop-start <0) return NULL;
-
- // start at 2 because we are using a function array lib
- if (start == stop) {
- responseJ=PopOneArg (luaState, start);
- } else {
- // loop on remaining return arguments
- responseJ= json_object_new_array();
- for (int idx=start; idx <= stop; idx++) {
- json_object *argJ=PopOneArg (luaState, idx);
- if (!argJ) goto OnErrorExit;
- json_object_array_add(responseJ, argJ);
- }
- }
-
- return responseJ;
-
- OnErrorExit:
- return NULL;
-}
-
-
-STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
- char *message;
-
- json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG);
-
- if (!responseJ) {
- luaL_error(luaState,"LuaFormatMessage empty message");
- goto OnErrorExit;
- }
-
- // 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) {
- message= (char*)json_object_get_string(responseJ);
- goto PrintMessage;
- }
-
- // extract format and push all other parameter on the stack
- message = alloca (LUA_MSG_MAX_LENGTH);
- const char *format = json_object_get_string(json_object_array_get_idx(responseJ, 0));
-
- int arrayIdx=1;
- int targetIdx=0;
-
- for (int idx=0; format[idx] !='\0'; idx++) {
-
- if (format[idx]=='%' && format[idx] !='\0') {
- json_object *slotJ= json_object_array_get_idx(responseJ, arrayIdx);
- //if (slotJ) AFB_NOTICE("**** idx=%d slotJ=%s", arrayIdx, json_object_get_string(slotJ));
-
-
- switch (format[++idx]) {
- case 'd':
- 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");
- arrayIdx++;
- break;
- case 'f':
- 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");
- arrayIdx++;
- break;
-
- case'%':
- message[targetIdx]='%';
- targetIdx++;
- break;
-
- case 's':
- default:
- 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");
- arrayIdx++;
- }
-
- } else {
- message[targetIdx++] = format[idx];
- }
- }
- message[targetIdx]='\0';
-
-PrintMessage:
- switch (action) {
- case AFB_MSG_WARNING:
- AFB_WARNING (message);
- break;
- case AFB_MSG_NOTICE:
- AFB_NOTICE (message);
- break;
- case AFB_MSG_DEBUG:
- AFB_DEBUG (message);
- break;
- case AFB_MSG_INFO:
- AFB_INFO (message);
- break;
- case AFB_MSG_ERROR:
- default:
- AFB_ERROR (message);
- }
- return 0; // nothing return to lua
-
- OnErrorExit: // on argument to return (the error message)
- return 1;
-}
-
-STATIC int LuaPrintInfo(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_INFO);
- return err;
-}
-
-STATIC int LuaPrintError(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_ERROR);
- return err; // no value return
-}
-
-STATIC int LuaPrintWarning(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_WARNING);
- return err;
-}
-
-STATIC int LuaPrintNotice(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_NOTICE);
- return err;
-}
-
-STATIC int LuaPrintDebug(lua_State* luaState) {
- int err=LuaFormatMessage (luaState, AFB_MSG_DEBUG);
- return err;
-}
-
-STATIC int LuaAfbSuccess(lua_State* luaState) {
- LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
- if (!afbContext) goto OnErrorExit;
-
- // ignore context argument
- json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
- if (responseJ == JSON_ERROR) return 1;
-
- afb_req_success(afbContext->request, responseJ, NULL);
-
- LuaCtxFree(afbContext);
- return 0;
-
- OnErrorExit:
- lua_error(luaState);
- return 1;
-}
-
-STATIC int LuaAfbFail(lua_State* luaState) {
- LuaAfbContextT *afbContext= LuaCtxCheck(luaState, LUA_FIST_ARG);
- if (!afbContext) goto OnErrorExit;
-
- json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
- if (responseJ == JSON_ERROR) return 1;
-
- afb_req_fail(afbContext->request, afbContext->info, json_object_get_string(responseJ));
-
- LuaCtxFree(afbContext);
- return 0;
-
- OnErrorExit:
- lua_error(luaState);
- return 1;
-}
-
-STATIC void LuaAfbServiceCB(void *handle, int iserror, struct json_object *responseJ) {
- LuaCallServiceT *contextCB= (LuaCallServiceT*)handle;
- int count=1;
-
- lua_getglobal(luaState, contextCB->callback);
-
- // push error status & response
- lua_pushboolean(luaState, iserror);
- count+= LuaPushArgument(responseJ);
- count+= LuaPushArgument(contextCB->context);
-
- int err=lua_pcall(luaState, count, LUA_MULTRET, 0);
- if (err) {
- AFB_ERROR ("LUA-SERICE-CB:FAIL response=%s err=%s", json_object_get_string(responseJ), lua_tostring(luaState,-1) );
- }
-}
-
-
-STATIC int LuaAfbService(lua_State* luaState) {
- int count = lua_gettop(luaState);
-
- // 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 ....");
- 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);
- if (queryJ == JSON_ERROR) return 1;
-
- LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT));
- contextCB->callback= lua_tostring(luaState, 5);
- contextCB->context = LuaPopArgs(luaState, 6);
-
- afb_service_call(api, verb, queryJ, LuaAfbServiceCB, contextCB);
-
- return 0; // no value return
-
- OnErrorExit:
- lua_error(luaState);
- return 1;
-}
-
-STATIC int LuaAfbServiceSync(lua_State* luaState) {
- int count = lua_gettop(luaState);
- json_object *responseJ;
-
- // note: argument start at 2 because of AFB: table
- if (count <3 || !lua_isstring(luaState, 2) || !lua_isstring(luaState, 3) || !lua_istable(luaState, 4)) {
- lua_pushliteral (luaState, "LuaAfbServiceSync-Syntax is error,data=AFB:service_call (api, verb, query)");
- 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);
-
- int iserror=afb_service_call_sync (api, verb, queryJ, &responseJ);
-
- // push error status & response
- count=1; lua_pushboolean(luaState, iserror);
- count+= LuaPushArgument(responseJ);
-
- return count; // return count values
-
- 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 (DispatchActionT *action, json_object *queryJ) {
-
- int err, count;
-
- json_object* argsJ = action->argsJ;
- const char* func = action->call;
-
- // load function (should exist in CONTROL_PATH_LUA
- lua_getglobal(luaState, func);
-
- // push argsJ on the stack
- count=0;
- if (!argsJ) {
- lua_pushnil(luaState);
- count++;
- } else {
- count+= LuaPushArgument (argsJ);
- }
-
- // push queryJ on the stack
- if (!queryJ) {
- lua_pushnil(luaState);
- count++;
- } else {
- count+= LuaPushArgument (queryJ);
- }
-
- // effectively exec LUA script code
- err=lua_pcall(luaState, count, 1, 0);
- if (err) {
- AFB_ERROR("LuaCallFunc Fail calling %s error=%s", func, lua_tostring(luaState,-1));
- goto OnErrorExit;
- }
-
- // return LUA script value
- int rc= (int)lua_tointeger(luaState, -1);
- return rc;
-
- OnErrorExit:
- return -1;
-}
-
-
-// Execute LUA code from received API request
-STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
-
- int err, count=0;
- const char *middleName=NULL;
-
- json_object* queryJ = afb_req_json(request);
-
- switch (action) {
-
- case LUA_DOSTRING: {
- const char *script = json_object_get_string(queryJ);
- err=luaL_loadstring(luaState, script);
- if (err) {
- AFB_ERROR ("LUA-DO-COMPILE:FAIL String=%s err=%s", script, lua_tostring(luaState,-1) );
- goto OnErrorExit;
- }
- // Push AFB client context on the stack
- LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, script);
- if (!afbContext) goto OnErrorExit;
-
- break;
- }
-
- case LUA_DOCALL: {
- const char *func;
- json_object *argsJ=NULL;
-
- err= wrap_json_unpack (queryJ, "{s:s, s?o !}", "func", &func, "args", &argsJ);
- if (err) {
- AFB_ERROR ("LUA-DOCALL-SYNTAX missing func|args query=%s", json_object_get_string(queryJ));
- goto OnErrorExit;
- }
-
- // 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 query on the stack
- if (!argsJ) {
- lua_pushnil(luaState);
- count++;
- } else {
- count+= LuaPushArgument (argsJ);
- }
-
- break;
- }
-
- case LUA_DOSCRIPT: { // Fulup need to fix argument passing
- const char *script;
- char*func;
- char *filename; char*fullpath;
- char luaScriptPath[CONTROL_MAXPATH_LEN];
- json_object *argsJ;
- int index;
-
- // scan luascript search path once
- static json_object *luaScriptPathJ =NULL;
- if (!luaScriptPathJ) luaScriptPathJ= ScanForConfig(CONTROL_LUA_PATH , CTL_SCAN_RECURSIVE, CONTROL_DOSCRIPT_PRE, "lua");
-
- err= wrap_json_unpack (queryJ, "{s:s, s?s s?o s?o !}", "script", &script,"func", &func, "arg", &argsJ);
- if (err) {
- AFB_ERROR ("LUA-DOSCRIPT-SYNTAX:missing script|(args,arg) query=%s", json_object_get_string(queryJ));
- goto OnErrorExit;
- }
-
- // search for filename=script in CONTROL_LUA_PATH
- for (index=0; index < json_object_array_length(luaScriptPathJ); index++) {
- json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index);
-
- err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename);
- if (err) {
- AFB_ERROR ("LUA-DOSCRIPT-SCAN:HOOPs invalid config file path = %s", json_object_get_string(entryJ));
- goto OnErrorExit;
- }
-
- if (!middleName && !strcmp (filename, script)) {
- middleName= GetMidleName(script);
- strncpy (luaScriptPath, fullpath, sizeof(luaScriptPath));
- strncat (luaScriptPath, "/", sizeof(luaScriptPath));
- strncat (luaScriptPath, filename, sizeof(luaScriptPath));
-
- } else {
- AFB_WARNING("LUA-DOSCRIPT-SCAN:Ignore second script=%s path=%s", filename, fullpath);
- }
- }
-
- // script was loaded we need to parse to make it executable
- err=lua_pcall(luaState, 0, 0, 0);
- if (err) {
- AFB_ERROR ("LUA-DOSCRIPT:FAIL to load %s", luaScriptPath);
- goto OnErrorExit;
- }
-
- // if no func name given try to deduct from filename
- if (!func) func= (char*)GetMidleName(filename);
- if (!func) {
- AFB_ERROR ("LUA-DOSCRIPT:FAIL to deduct funcname from %s", filename);
- goto OnErrorExit;
- }
-
- // 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 function arguments
- if (!argsJ) {
- lua_pushnil(luaState);
- count++;
- } else {
- count+= LuaPushArgument (argsJ);
- }
-
- break;
- }
-
- default:
- AFB_ERROR ("LUA-DOSCRIPT-ACTION unknown query=%s", json_object_get_string(queryJ));
- goto OnErrorExit;
- }
-
- // effectively exec LUA code (afb_reply/fail done later from callback)
- err=lua_pcall(luaState, count+1, 0, 0);
- if (err) {
- AFB_ERROR ("LUA-DO-EXEC:FAIL query=%s err=%s", json_object_get_string(queryJ), lua_tostring(luaState,-1) );
- goto OnErrorExit;
- }
- return;
-
- OnErrorExit:
- afb_req_fail(request,"LUA:ERROR", lua_tostring(luaState,-1));
- return;
-}
-
-PUBLIC void ctlapi_lua_dostring (afb_req request) {
- LuaDoAction (LUA_DOSTRING, request);
-}
-
-PUBLIC void ctlapi_lua_docall (afb_req request) {
- LuaDoAction (LUA_DOCALL, request);
-}
-
-PUBLIC void ctlapi_lua_doscript (afb_req request) {
- LuaDoAction (LUA_DOSCRIPT, request);
-}
-
-static const luaL_Reg afbFunction[] = {
- {"notice" , LuaPrintNotice},
- {"info" , LuaPrintInfo},
- {"warning", LuaPrintWarning},
- {"debug" , LuaPrintDebug},
- {"error" , LuaPrintError},
- {"callsync", LuaAfbServiceSync},
- {"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
- 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();
- if (!luaState) {
- AFB_ERROR ("LUA_INIT: Fail to open lua interpretor");
- goto OnErrorExit;
- }
-
- // load auxiliary libraries
- luaL_openlibs(luaState);
-
- // redirect print to AFB_NOTICE
- 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);
-
- char *filename; char*fullpath;
- err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename);
- if (err) {
- AFB_ERROR ("LUA-INIT HOOPs invalid config file path = %s", json_object_get_string(entryJ));
- goto OnErrorExit;
- }
-
- char filepath[CONTROL_MAXPATH_LEN];
- strncpy(filepath, fullpath, sizeof(filepath));
- strncat(filepath, "/", sizeof(filepath));
- strncat(filepath, filename, sizeof(filepath));
- err= luaL_loadfile(luaState, filepath);
- if (err) {
- AFB_ERROR ("LUA-LOAD HOOPs Error in LUA loading scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
- goto OnErrorExit;
- }
-
- // exec/compil script
- err = lua_pcall(luaState, 0, 0, 0);
- if (err) {
- AFB_ERROR ("LUA-LOAD HOOPs Error in LUA exec scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
- goto OnErrorExit;
- }
- }
-
- // no policy config found remove control API from binder
- if (index == 0) {
- AFB_WARNING ("POLICY-INIT:WARNING No Control LUA file in path=[%s]", CONTROL_LUA_PATH);
- }
-
- AFB_DEBUG ("Audio control-LUA Init Done");
- return 0;
-
- OnErrorExit:
- return 1;
-}
- \ No newline at end of file
diff --git a/Controler-afb/ctl-plugin-sample.c b/Controler-afb/ctl-plugin-sample.c
deleted file mode 100644
index 837ad9d..0000000
--- a/Controler-afb/ctl-plugin-sample.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.
- *
- * Sample plugin for Controller
- */
-
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-
-#include "ctl-binding.h"
-
-#define MY_PLUGIN_MAGIC 987654321
-
-typedef struct {
- int magic;
- int count;
-} MyPluginCtxT;
-
-// Declare this sharelib as a Controller Plugin
-CTL_PLUGIN_REGISTER("MyCtlSamplePlugin");
-
-STATIC const char* jsonToString (json_object *valueJ) {
- const char *value;
- if (valueJ)
- value=json_object_get_string(valueJ);
- else
- value="NULL";
-
- return value;
-}
-
-// Call at initialisation time
-PUBLIC void* CtlPluginOnload(char* label, char* version, char* info) {
- MyPluginCtxT *pluginCtx= (MyPluginCtxT*)calloc (1, sizeof(MyPluginCtxT));
- pluginCtx->magic = MY_PLUGIN_MAGIC;
- pluginCtx->count = -1;
-
- AFB_NOTICE ("CONTROLER-PLUGIN-SAMPLE:Onload label=%s version=%s info=%s", label, info, version);
- return (void*)pluginCtx;
-}
-
-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 (DispatchActionT *action, json_object *queryJ, void *context) {
- MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context;
-
- if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) {
- AFB_ERROR("CONTROLER-PLUGIN-SAMPLE:sampleControlMultimedia (Hoops) Invalid Sample Plugin Context");
- return -1;
- };
- 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 (DispatchActionT *action, json_object *queryJ, void *context) {
- MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context;
-
- if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) {
- AFB_ERROR("CONTROLER-PLUGIN-SAMPLE:sampleControlNavigation (Hoops) Invalid Sample Plugin Context");
- return -1;
- };
- 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 (DispatchActionT *action, json_object *queryJ, void *context) {
- MyPluginCtxT *pluginCtx= (MyPluginCtxT*)context;
-
- if (!context || pluginCtx->magic != MY_PLUGIN_MAGIC) {
- AFB_ERROR("CONTROLER-PLUGIN-SAMPLE:cousampleControlMultimediant (Hoops) Invalid Sample Plugin Context");
- return -1;
- };
- 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;
-}
diff --git a/Controler-afb/ctl-policy.c b/Controler-afb/ctl-policy.c
deleted file mode 100644
index e9798b3..0000000
--- a/Controler-afb/ctl-policy.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author Fulup Ar Foll <fulup@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, something express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <dirent.h>
-#include <json-c/json_object.h>
-
-#include "wrap-json.h"
-#include "ctl-binding.h"
-
-STATIC PolicyCtlConfigT *ctlHandle = NULL;
-
-// List Avaliable Configuration Files
-STATIC json_object* ScanForConfig (char* searchPath) {
- json_object *responseJ;
- DIR *dirHandle;
- char *dirPath;
- char* dirList= strdup(searchPath);
-
- responseJ = json_object_new_array();
- for (dirPath= strtok(dirList, ":"); dirPath && *dirPath; dirPath=strtok(NULL,":")) {
- struct dirent *dirEnt;
-
- dirHandle = opendir (dirPath);
- if (!dirHandle) {
- AFB_NOTICE ("CONFIG-SCANNING dir=%s not readable", dirPath);
- continue;
- }
-
- AFB_NOTICE ("CONFIG-SCANNING:ctl_listconfig scanning: %s", dirPath);
- while ((dirEnt = readdir(dirHandle)) != NULL) {
- // Unknown type is accepted to support dump filesystems
- if (dirEnt->d_type == DT_REG || dirEnt->d_type == DT_UNKNOWN) {
- struct json_object *pathJ = json_object_new_object();
- json_object_object_add(pathJ, "dirpath", json_object_new_string(dirPath));
- json_object_object_add(pathJ, "filename", json_object_new_string(dirEnt->d_name));
- json_object_array_add(responseJ, pathJ);
- }
- }
- }
-
- free (dirList);
- return (responseJ);
-}
-
-PUBLIC void ctlapi_authorize (PolicyCtlEnumT control, afb_req request) {
- json_object*tmpJ;
-
- json_object* queryJ= afb_req_json(request);
- int done=json_object_object_get_ex(queryJ, "closing", &tmpJ);
- if (done) return;
-
-}
-
-
-// List Avaliable Configuration Files
-PUBLIC void ctlapi_config (struct afb_req request) {
- json_object*tmpJ;
- char *dirList;
-
- 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);
- AFB_NOTICE ("CONFIG-MISSING: use default CONTROL_CONFIG_PATH=%s", CONTROL_CONFIG_PATH);
- }
-
- // get list of config file
- struct json_object *responseJ = ScanForConfig(dirList);
-
- if (json_object_array_length(responseJ) == 0) {
- afb_req_fail(request, "CONFIGPATH:EMPTY", "No Config Found in CONTROL_CONFIG_PATH");
- } else {
- afb_req_success(request, responseJ, NULL);
- }
-
- return;
-}
-
-STATIC PolicyActionT **PolicyLoadActions (json_object *actionsJ) {
- int err;
- PolicyActionT ** actions;
-
- // unpack individual action object
- int actionUnpack (json_object *actionJ, PolicyActionT *action) {
-
- err= wrap_json_unpack(actionJ, "{ss,s?s,s?s,s?s,s?s,s?s !}"
- , "label",&action->label, "info",&action->info, "callback",&action->callback, "query",&queryJ, "api",&action->api, "verb", &action->verb);
- if (err) {
- AFB_ERROR ("POLICY-LOAD-ACTION Missing something label|info|callback|api|verb|query in %s", json_object_get_string(actionJ));
- return -1;
- }
- if (!action->callback || !(action->api && action->verb)) {
- AFB_ERROR ("POLICY-LOAD-ACTION Missing something callback|(api+verb) in %s", json_object_get_string(actionJ));
- return -1;
- }
- return 0;
- };
-
- // action array is close with a nullvalue;
- if (json_object_get_type(actionsJ) == json_type_array) {
- int count = json_object_array_length(actionsJ);
- actions = calloc (count+1, sizeof(PolicyActionT));
-
- for (int idx=0; idx < count; idx++) {
- json_object *actionJ = json_object_array_get_idx(actionsJ, idx);
- err = actionUnpack (actionJ, &actions[idx]);
- if (err) goto OnErrorExit;
- }
-
- } else {
- actions = calloc (2, sizeof(PolicyActionT));
- err = actionUnpack (actionsJ, &actions[0]);
- if (err) goto OnErrorExit;
- }
-
- return actions;
-
- OnErrorExit:
- return NULL;
-
-}
-
-// load control policy from file using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values
-STATIC PolicyCtlConfigT *PolicyLoadConfig (const char* filepath) {
- json_object *policyConfigJ, *ignoreJ, *actionsJ;
- PolicyCtlConfigT *policyConfig = calloc (1, sizeof(PolicyCtlConfigT));
- int err;
-
- // Load JSON file
- policyConfigJ= json_object_from_file(filepath);
- if (!policyConfigJ) goto OnErrorExit;
-
- json_object *metadataJ, *onloadJ, *controlsJ, *eventsJ;
- err= wrap_json_unpack(policyConfigJ, "{s?o,so,s?o,so,so !}", "$schema", &ignoreJ, "metadata",&metadataJ, "onload",&onloadJ, "controls",&controlsJ, "events",&eventsJ);
- if (err) {
- AFB_ERROR ("POLICY-LOAD-ERRROR Missing something metadata|onload|controls|events in %s", json_object_get_string(policyConfigJ));
- goto OnErrorExit;
- }
-
- PolicyHandleT *policyHandle = calloc (1, sizeof(PolicyHandleT));
- err= wrap_json_unpack(metadataJ, "{so,s?s,s?s !}", "label", &policyHandle->label, "info",&policyHandle->info, "version",&policyHandle->version);
- if (err) {
- AFB_ERROR ("POLICY-LOAD-CONFIG Missing something label|info|version in %s", json_object_get_string(metadataJ));
- goto OnErrorExit;
- }
-
- if (onloadJ) {
- err= wrap_json_unpack(onloadJ, "{s?o,s?s,s?s !}", "info",&ignoreJ, "label",&ignoreJ, "actions",&actionsJ);
- if (err) {
- AFB_ERROR ("POLICY-LOAD-CONFIG Missing something label|info|plugin|actions in %s", json_object_get_string(metadataJ));
- goto OnErrorExit;
- }
- policyConfig->onload = PolicyLoadActions (actionsJ);
- }
-
- return policyControl;
-
-OnErrorExit:
- return NULL;
-}
-
-// Load default config file at init
-PUBLIC int PolicyInit () {
- int index, err;
-
-
- // search for default policy config file
- json_object* responseJ = ScanForConfig(CONTROL_CONFIG_PATH);
-
- for (index=0; index < json_object_array_length(responseJ); index++) {
- json_object *entryJ=json_object_array_get_idx(responseJ, index);
-
- char *filename; char*dirpath;
- err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "dirpath", &dirpath,"filename", &filename);
- if (err) {
- AFB_ERROR ("POLICY-INIT HOOPs invalid config file path = %s", json_object_get_string(entryJ));
- goto OnErrorExit;
- }
-
- if (strcasestr(filename, CONTROL_CONFIG_FILE)) {
- char filepath[255];
- strncpy(filepath, dirpath, sizeof(filepath));
- strncat(filepath, "/", sizeof(filepath));
- strncat(filepath, filename, sizeof(filepath));
- ctlHandle = PolicyLoadConfig (filepath);
- if (!ctlHandle) goto OnErrorExit;
- break;
- }
- }
-
- // no policy config found remove control API from binder
- if (index == 0) goto OnErrorExit;
-
- AFB_NOTICE ("SUCCES: Audio Control Policy Init");
- return 0;
-
-OnErrorExit:
- AFB_NOTICE ("ERROR: Audio Control Policy Init");
- return 1;
-}
-
-
-