diff options
author | Romain Forlot <romain.forlot@iot.bzh> | 2017-08-21 10:23:18 +0200 |
---|---|---|
committer | Romain Forlot <romain.forlot@iot.bzh> | 2017-08-21 10:23:18 +0200 |
commit | 88d0b8c02eaaac8843f184e379fc5a19250295e5 (patch) | |
tree | 4893d2b5cb0fdbddf0357ebd7d32009e73856cec /Controler-afb/ctl-dispatch.c | |
parent | ba709f088f5a4718b7096003ab19083af4681155 (diff) | |
parent | d51d083be8e34000cd00ce979445eacb45a16e97 (diff) |
Merge branch 'fulup-dev'
Change-Id: I7dc6859767ac5919cf383e33bd2cf3a98698d9b4
Diffstat (limited to 'Controler-afb/ctl-dispatch.c')
-rw-r--r-- | Controler-afb/ctl-dispatch.c | 527 |
1 files changed, 0 insertions, 527 deletions
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; -} - - - |