aboutsummaryrefslogtreecommitdiffstats
path: root/Controler-afb/ctl-dispatch.c
diff options
context:
space:
mode:
authorfulup <fulup.arfoll@iot.bzh>2017-08-11 19:44:21 +0200
committerfulup <fulup.arfoll@iot.bzh>2017-08-11 19:44:21 +0200
commitb65178642727536972d0c04e53b2310be58beb2e (patch)
treef06f8773ce44f8320e9e86cee60e59e1597d6b78 /Controler-afb/ctl-dispatch.c
parentc13952824e2cc110b9405e1bc9017801dd938ac0 (diff)
Almost working version with Json Config, Lua script and sharelib callbacks.
Diffstat (limited to 'Controler-afb/ctl-dispatch.c')
-rw-r--r--Controler-afb/ctl-dispatch.c209
1 files changed, 154 insertions, 55 deletions
diff --git a/Controler-afb/ctl-dispatch.c b/Controler-afb/ctl-dispatch.c
index 4fa1844..8fdf46e 100644
--- a/Controler-afb/ctl-dispatch.c
+++ b/Controler-afb/ctl-dispatch.c
@@ -31,7 +31,6 @@ typedef void*(*DispatchPluginInstallCbT)(const char* label, const char*version,
typedef struct {
const char* label;
const char *info;
- const char *version;
DispatchActionT *actions;
} DispatchHandleT;
@@ -44,17 +43,83 @@ typedef struct {
void *dlHandle;
DispatchHandleT *onload;
DispatchHandleT *events;
- DispatchHandleT *controls;
+ DispatchHandleT **controls;
} DispatchConfigT;
-STATIC DispatchConfigT *ctlHandle = NULL;
+// global config handle
+STATIC DispatchConfigT *configHandle = NULL;
-PUBLIC void ctlapi_dispatch (DispatchCtlEnumT control, afb_req request) {
- json_object*tmpJ;
+STATIC int DispatchControlToIndex(char* controlLabel) {
+ DispatchHandleT **controls=configHandle->controls;
+ for (int idx=0; controls[idx]; idx++) {
+ if (!strcasecmp(controlLabel, controls[idx]->label)) return idx;
+ }
+ return 0;
+}
+
+PUBLIC void ctlapi_dispatch (char* controlLabel, afb_req request) {
+ DispatchHandleT **controls=configHandle->controls;
+ 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;
+ }
- json_object* argsJ= afb_req_json(request);
- int done=json_object_object_get_ex(argsJ, "closing", &tmpJ);
- if (done) return;
+ int index=DispatchControlToIndex(controlLabel);
+ if (!index || !controls[index]->actions) {
+ AFB_ERROR ("DISPATCH-CTL-API:NotFound label=%s index=%d", controlLabel, index);
+ goto OnErrorExit;
+ } else {
+ AFB_NOTICE("DISPATCH-CTL-API:Found Control=%s", controls[index]->label);
+ }
+
+ // loop on action for this control
+ DispatchActionT *actions=controls[index]->actions;
+ for (int idx=0; actions[idx].label; idx++) {
+
+ 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) {
+ AFB_NOTICE ("DISPATCH-CTL-MODE:Api api=%s verb=%s args=%s", actions[idx].api, actions[idx].call, actions[idx].label);
+ afb_req_fail_f(request, "DISPATCH-CTL-MODE:Api", "label=%s api=%s verb=%s", actions[idx].label, actions[idx].api, actions[idx].call);
+ goto OnErrorExit;
+ }
+ break;
+ }
+
+ case CTL_MODE_LUA:
+ err= LuaCallFunc (request, &actions[idx]);
+ if (err) {
+ afb_req_fail_f(request, "DISPATCH-CTL-MODE:Lua", "func=%s args=%s", actions[idx].call, json_object_get_string(actions[idx].argsJ));
+ goto OnErrorExit;
+ }
+ break;
+
+ case CTL_MODE_CB:
+ err= (*actions[idx].actionCB) (request, &actions[idx], configHandle->context);
+ if (err) {
+ afb_req_fail_f(request, "DISPATCH-CTL-MODE:Cb", "func=%s args=%s", actions[idx].call, json_object_get_string(actions[idx].argsJ));
+ goto OnErrorExit;
+ }
+ break;
+
+ default:
+ AFB_ERROR ("DISPATCH-CTL-API:control=%s action=%s", controls[index]->label, actions[idx].label);
+ afb_req_fail_f(request, "DISPATCH-CTL-MODE:Unknown", "control=%s action=%s", controls[index]->label, actions[idx].label);
+ }
+ }
+
+ // everything when fine
+ afb_req_success(request,NULL,controls[index]->label);
+ return;
+
+ OnErrorExit:
+ return;
}
// List Avaliable Configuration Files
@@ -83,12 +148,12 @@ PUBLIC void ctlapi_config (struct afb_req request) {
}
// unpack individual action object
-STATIC int DispatchLoadOneAction (json_object *actionJ, DispatchActionT *action) {
- char *api, *verb, *callback, *lua;
+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?o,s?s,s?s,s?s !}"
- , "label",&action->label, "info",&action->info, "callback",&callback, "lua", &lua, "args",&action->argsJ, "api",&api, "verb", &verb);
+ 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;
@@ -107,26 +172,26 @@ STATIC int DispatchLoadOneAction (json_object *actionJ, DispatchActionT *action
modeCount++;
}
- if (callback) {
+ if (callback && controlConfig->dlHandle) {
action->mode = CTL_MODE_CB;
action->call=callback;
modeCount++;
- action->actionCB = dlsym(ctlHandle->dlHandle, callback);
+ action->actionCB = dlsym(controlConfig->dlHandle, callback);
if (!action->actionCB) {
- AFB_ERROR ("DISPATCH-LOAD-ACTION fail to find calbback=%s in %s", callback, ctlHandle->plugin);
+ 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 Missing something lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
+ 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 lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
+ AFB_ERROR ("DISPATCH-LOAD-ACTION:ToMany arguments lua|callback|(api+verb) in %s", json_object_get_string(actionJ));
goto OnErrorExit;
}
return 0;
@@ -135,7 +200,7 @@ OnErrorExit:
return -1;
};
-STATIC DispatchActionT *DispatchLoadActions (json_object *actionsJ) {
+STATIC DispatchActionT *DispatchLoadActions (DispatchConfigT *controlConfig, json_object *actionsJ) {
int err;
DispatchActionT *actions;
@@ -146,13 +211,13 @@ STATIC DispatchActionT *DispatchLoadActions (json_object *actionsJ) {
for (int idx=0; idx < count; idx++) {
json_object *actionJ = json_object_array_get_idx(actionsJ, idx);
- err = DispatchLoadOneAction (actionJ, &actions[idx]);
+ err = DispatchLoadOneAction (controlConfig, actionJ, &actions[idx]);
if (err) goto OnErrorExit;
}
} else {
actions = calloc (2, sizeof(DispatchActionT));
- err = DispatchLoadOneAction (actionsJ, &actions[0]);
+ err = DispatchLoadOneAction (controlConfig, actionsJ, &actions[0]);
if (err) goto OnErrorExit;
}
@@ -165,25 +230,28 @@ STATIC DispatchActionT *DispatchLoadActions (json_object *actionsJ) {
STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) {
- json_object *dispatchConfigJ, *ignoreJ;
+ json_object *controlConfigJ, *ignoreJ;
int err;
// Load JSON file
- dispatchConfigJ= json_object_from_file(filepath);
- if (!dispatchConfigJ) goto OnErrorExit;
+ 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, *onloadJ=NULL, *controlsJ=NULL, *eventsJ=NULL;
- err= wrap_json_unpack(dispatchConfigJ, "{s?o,so,s?o,s?o,s?o !}", "$schema", &ignoreJ, "metadata",&metadataJ, "onload",&onloadJ, "controls",&controlsJ, "events",&eventsJ);
+ err= wrap_json_unpack(controlConfigJ, "{s?o,so,s?o,s?o,s?o !}", "$schema", &ignoreJ, "metadata",&metadataJ, "onload",&onloadJ, "controls",&controlsJ, "events",&eventsJ);
if (err) {
- AFB_ERROR ("DISPATCH-LOAD-CONFIG Missing something metadata|[onload]|[controls]|[events] in %s", json_object_get_string(dispatchConfigJ));
+ AFB_ERROR ("DISPATCH-LOAD-CONFIG Missing something metadata|[onload]|[controls]|[events] in %s", json_object_get_string(controlConfigJ));
goto OnErrorExit;
}
- DispatchConfigT *dispatchConfig = calloc (1, sizeof(DispatchConfigT));
+ DispatchConfigT *controlConfig = calloc (1, sizeof(DispatchConfigT));
if (metadataJ) {
- err= wrap_json_unpack(metadataJ, "{ss,s?s,ss !}", "label", &dispatchConfig->label, "info",&dispatchConfig->info, "version",&dispatchConfig->version);
+ 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;
@@ -193,19 +261,18 @@ STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) {
if (onloadJ) {
json_object * actionsJ;
DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT));
-
- err= wrap_json_unpack(onloadJ, "{so,s?s,s?s,s?o !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "plugin", &dispatchConfig->plugin, "actions",&actionsJ);
+ err= wrap_json_unpack(onloadJ, "{so,s?s,s?s,s?o !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "plugin", &controlConfig->plugin, "actions",&actionsJ);
if (err) {
AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Missing something label|[info]|[plugin]|[actions] in %s", json_object_get_string(onloadJ));
goto OnErrorExit;
}
- if (dispatchConfig->plugin) {
+ if (controlConfig->plugin) {
// search for default policy config file
- json_object *pluginPathJ = ScanForConfig(CONTROL_PLUGIN_PATH , CTL_SCAN_RECURSIVE, dispatchConfig->plugin, NULL);
+ 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", dispatchConfig->plugin, CONTROL_PLUGIN_PATH);
+ AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLUGIN Missing plugin=%s in path=%s", controlConfig->plugin, CONTROL_PLUGIN_PATH);
goto OnErrorExit;
}
@@ -224,39 +291,67 @@ STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) {
strncpy(pluginpath, fullpath, sizeof(pluginpath));
strncat(pluginpath, "/", sizeof(pluginpath));
strncat(pluginpath, filename, sizeof(pluginpath));
- dispatchConfig->dlHandle = dlopen(pluginpath, RTLD_NOW);
- if (!dispatchConfig->dlHandle) {
- AFB_ERROR ("DISPATCH-LOAD-CONFIG:PLIUGIN Fail to load pluginpath=%s err= %s", pluginpath, dlerror());
+ 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;
}
- ulong *ctlPluginMagic = (ulong*)dlsym(dispatchConfig->dlHandle, "CtlPluginMagic");
- if (!ctlPluginMagic || *ctlPluginMagic != CTL_PLUGIN_MAGIC) {
- AFB_ERROR("DISPATCH-LOAD-CONFIG:PLIUGIN symbol'CtlPluginMagic' missing or != CTL_PLUGIN_MAGIC plugin=%s", pluginpath);
+ 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);
}
- DispatchPluginInstallCbT ctlPluginInstall = dlsym(dispatchConfig->dlHandle, "CtlPluginOnload");
- if (ctlPluginInstall) {
- dispatchConfig->context = (*ctlPluginInstall) (dispatchConfig->label, dispatchConfig->version, dispatchConfig->info);
+ // 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(actionsJ);
- dispatchConfig->onload= dispatchHandle;
+ dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ);
+ if (!dispatchHandle->actions) {
+ AFB_ERROR ("DISPATCH-LOAD-CONFIG:ONLOAD Error when parsing actions %s", dispatchHandle->label);
+ goto OnErrorExit;
+ }
+ controlConfig->onload= dispatchHandle;
+
}
if (controlsJ) {
json_object * actionsJ;
- DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT));
- err= wrap_json_unpack(controlsJ, "{so,s?s,so !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "actions",&actionsJ);
- if (err) {
- AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS Missing something label|[info]|actions in %s", json_object_get_string(controlsJ));
- goto OnErrorExit;
+ if (json_object_get_type(controlsJ) != json_type_array) {
+ AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS invalid JSON array in %s", json_object_get_string(controlsJ));
+ goto OnErrorExit;
+ }
+
+ int length= json_object_array_length(controlsJ);
+ controlConfig->controls = (DispatchHandleT**) calloc (length+1, sizeof(void*));
+
+ for (int jdx=0; jdx< length; jdx++) {
+ DispatchHandleT *dispatchHandle = calloc (1, sizeof(DispatchHandleT));
+ json_object *controlJ = json_object_array_get_idx(controlsJ,jdx);
+ err= wrap_json_unpack(controlJ, "{ss,s?s,so !}", "label",&dispatchHandle->label, "info",&dispatchHandle->info, "actions",&actionsJ);
+ if (err) {
+ AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS Missing something label|[info]|actions in %s", json_object_get_string(controlJ));
+ goto OnErrorExit;
+ }
+
+ dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ);
+ if (!dispatchHandle->actions) {
+ AFB_ERROR ("DISPATCH-LOAD-CONFIG:CONTROLS Error when parsing actions %s", dispatchHandle->label);
+ goto OnErrorExit;
+ }
+ controlConfig->controls[jdx]= dispatchHandle;
}
- dispatchHandle->actions= DispatchLoadActions(actionsJ);
- dispatchConfig->onload= dispatchHandle;
+
}
if (eventsJ) {
@@ -268,11 +363,15 @@ STATIC DispatchConfigT *DispatchLoadConfig (const char* filepath) {
AFB_ERROR ("DISPATCH-LOAD-CONFIG:EVENTS Missing something label|[info]|actions in %s", json_object_get_string(eventsJ));
goto OnErrorExit;
}
- dispatchHandle->actions= DispatchLoadActions(actionsJ);
- dispatchConfig->onload= dispatchHandle;
+ dispatchHandle->actions= DispatchLoadActions(controlConfig, actionsJ);
+ if (!dispatchHandle->actions) {
+ AFB_ERROR ("DISPATCH-LOAD-CONFIG:EVENTS Error when parsing actions %s", dispatchHandle->label);
+ goto OnErrorExit;
+ }
+ controlConfig->events= dispatchHandle;
}
- return dispatchConfig;
+ return controlConfig;
OnErrorExit:
return NULL;
@@ -301,8 +400,8 @@ PUBLIC int DispatchInit () {
strncpy(filepath, fullpath, sizeof(filepath));
strncat(filepath, "/", sizeof(filepath));
strncat(filepath, filename, sizeof(filepath));
- ctlHandle = DispatchLoadConfig (filepath);
- if (!ctlHandle) {
+ configHandle = DispatchLoadConfig (filepath);
+ if (!configHandle) {
AFB_ERROR ("DISPATCH-INIT:ERROR No File to load [%s]", filepath);
goto OnErrorExit;
}