diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 45 | ||||
-rw-r--r-- | src/plugins/CMakeLists.txt | 42 | ||||
-rw-r--r-- | src/plugins/supervisor-api.c | 164 | ||||
-rw-r--r-- | src/plugins/supervisor-api.h | 36 | ||||
-rw-r--r-- | src/plugins/supervisor.c | 194 | ||||
-rw-r--r-- | src/plugins/supervisor.h | 53 | ||||
-rw-r--r-- | src/utils/list.c | 112 | ||||
-rw-r--r-- | src/utils/list.h | 37 | ||||
-rw-r--r-- | src/xds-apidef.json | 154 | ||||
-rw-r--r-- | src/xds-binding.c | 157 | ||||
-rw-r--r-- | src/xds-binding.h | 32 |
11 files changed, 1026 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..df8cae1 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,45 @@ +########################################################################### +# Copyright 2018 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. +########################################################################### + +# Add target to project dependency list +PROJECT_TARGET_ADD(xds) + + # Define project Targets + add_library(${TARGET_NAME} MODULE + ${TARGET_NAME}-binding.c + ) + + set(OPENAPI_DEF "xds-apidef" CACHE STRING "name and path to the JSON API definition without extension") + + target_compile_options(${TARGET_NAME} + PUBLIC -Wno-unused-variable + ) + + # Binder exposes a unique public entry point + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + PREFIX "afb-" + LABELS "BINDINGV2" + LINK_FLAGS ${BINDINGS_LINK_FLAG} + OUTPUT_NAME ${TARGET_NAME} + ) + + # Library dependencies (include updates automatically) + TARGET_LINK_LIBRARIES(${TARGET_NAME} + afb-helpers + ctl-utilities + ${link_libraries}) + +add_subdirectory("plugins") diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt new file mode 100644 index 0000000..1c1c557 --- /dev/null +++ b/src/plugins/CMakeLists.txt @@ -0,0 +1,42 @@ +########################################################################### +# Copyright 2015, 2016, 2017 IoT.bzh +# +# author: Romain Forlot <romain.forlot@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. +########################################################################### + +PROJECT_TARGET_ADD(supervisor) + + # Define targets + ADD_LIBRARY(${TARGET_NAME} MODULE + ${TARGET_NAME}-api.c + ${TARGET_NAME}.c + ../utils/list.c) + + # Alsa Plugin properties + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + LABELS "PLUGIN" + PREFIX "" + SUFFIX ".ctlso" + OUTPUT_NAME ${TARGET_NAME} + ) + + # Library dependencies (include updates automatically) + TARGET_LINK_LIBRARIES(${TARGET_NAME} + afb-helpers + ${link_libraries} + ) + + target_include_directories(${TARGET_NAME} + PRIVATE "${CMAKE_SOURCE_DIR}/app-controller/ctl-lib") diff --git a/src/plugins/supervisor-api.c b/src/plugins/supervisor-api.c new file mode 100644 index 0000000..0c1a5bc --- /dev/null +++ b/src/plugins/supervisor-api.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author "Sebastien Douheret" <sebastien@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 <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "ctl-plugin.h" +#include "supervisor-api.h" +#include "supervisor.h" +#include "wrap-json.h" + +CTLP_CAPI_REGISTER("supervisor"); + +CTLP_ONLOAD(plugin, ret) +{ + return 0; +} + +CTLP_CAPI(list, source, argsJ, eventJ) +{ + json_object *result, *item = NULL; + DAEMONS_T* daemons = NULL; + + getDaemons(source->api, &daemons); + if (daemons == NULL) { + AFB_ApiError(source->api, "failed"); + return ERROR; + } + + result = json_object_new_array(); + + for (int i = 0; i < daemons->count; i++) { + wrap_json_pack(&item, "{si ss sb sb so so so}", + "pid", daemons->daemons[i]->pid, + "name", daemons->daemons[i]->name, + "isServer", daemons->daemons[i]->isServer, + "isClient", daemons->daemons[i]->isClient, + "ws_servers", daemons->daemons[i]->ws_servers, + "ws_clients", daemons->daemons[i]->ws_clients, + "apis", daemons->daemons[i]->apis); + //, "config", daemons->daemons[i]->config); + json_object_array_add(result, item); + } + AFB_ReqSucess(source->request, result, NULL); + return 0; +} + +CTLP_CAPI(trace, source, argsJ, eventJ) +{ + int rc; + json_object* result = NULL; + DAEMONS_T* daemons = NULL; + const char* ws_name; + const char* wsn; + + if (wrap_json_unpack(argsJ, "{s:?s}", "ws", &ws_name)) { + AFB_ReqFail(source->request, "Failed", "Error processing arguments."); + return ERROR; + } + AFB_ApiNotice(source->api, "Trace ws: %s", ws_name); + + getDaemons(source->api, &daemons); + if (daemons == NULL || daemons->count <= 0) { + AFB_ReqFail(source->request, "failed", "No daemon found"); + } + + // search server and client pid + DAEMON_T *pid_s = NULL, *pid_c = NULL; + for (int i = 0; i < daemons->count; i++) { + AFB_ApiDebug(source->api, "_DEBUG_ svr %s", + json_object_to_json_string(daemons->daemons[i]->ws_servers)); + AFB_ApiDebug(source->api, "_DEBUG_ cli %s", + json_object_to_json_string(daemons->daemons[i]->ws_clients)); + + json_object* ws_servers = daemons->daemons[i]->ws_servers; + for (int j = 0; j < json_object_array_length(ws_servers); j++) { + + wsn = json_object_get_string(json_object_array_get_idx(ws_servers, j++)); + if (wsn && strstr(wsn, ws_name) != NULL) { + pid_s = daemons->daemons[i]; + break; + } + } + + json_object* ws_clients = daemons->daemons[i]->ws_clients; + for (int j = 0; j < json_object_array_length(ws_clients); j++) { + wsn = json_object_get_string(json_object_array_get_idx(ws_clients, j++)); + if (wsn && strstr(wsn, ws_name) != NULL) { + pid_c = daemons->daemons[i]; + break; + } + } + + if (pid_s != NULL && pid_c != NULL) { + if ((rc = trace_exchange(source->api, pid_s, pid_c)) < 0) { + AFB_ReqFailF(source->request, "failed", "Trace error %d", rc); + } + break; + } + } + + if (pid_s == NULL || pid_c == NULL) { + AFB_ReqFail(source->request, "failed", "Cannot determine Server or Client"); + return ERROR; + } + + AFB_ReqSucessF(source->request, result, "Tracing Server pid=%d <-> Client pid=%d", pid_s->pid, pid_c->pid); + + return 0; +} + +/* SEB TODO +void xds_event_cb(const char* evtname, json_object* j_event) +{ + int rc; + METRIC_T metric; + const char* type = NULL; + struct json_object* request = NULL; + + AFB_NOTICE("RECV Event %s : %s", evtname, + json_object_to_json_string(j_event)); + + if (strcmp(evtname, "supervisor/trace") != 0) { + return; + } + + if ((rc = wrap_json_unpack(j_event, "{s:?s}", "type", &type)) < 0) { + AFB_ERROR("Cannot decode event type"); + return; + } + + if (strcmp(type, "request") == 0) { + + if (!json_object_object_get_ex(j_event, "request", &request)) { + AFB_ERROR("Cannot decode event request"); + return; + } + metric.name = "trace"; + metric.data = request; + + rc = harvester_post_data(&metric); + if (rc < 0) { + AFB_ERROR("ERROR harvester_post_data: rc %d", rc); + } + } +} +*/ diff --git a/src/plugins/supervisor-api.h b/src/plugins/supervisor-api.h new file mode 100644 index 0000000..beadeca --- /dev/null +++ b/src/plugins/supervisor-api.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author "Sebastien Douheret" <sebastien@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. + */ +#pragma once + +#include <stdbool.h> +#include "wrap-json.h" +#include "filescan-utils.h" + +#define SRV_HARVESTER_NAME "harvester" + +#define META_SOURCENAME GetBinderName(); +#define META_IDENTITY "" // FIXME + +#ifndef ERROR + #define ERROR -1 +#endif + +typedef struct metric_t { + char* name; + json_object* data; + struct timespec timestamp; +} METRIC_T; diff --git a/src/plugins/supervisor.c b/src/plugins/supervisor.c new file mode 100644 index 0000000..649713e --- /dev/null +++ b/src/plugins/supervisor.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2018 "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 <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "ctl-plugin.h" +#include "supervisor-api.h" +#include "supervisor.h" +#include "wrap-json.h" + +struct afb_cred { + int refcount; + uid_t uid; + gid_t gid; + pid_t pid; + const char* user; + const char* label; + const char* id; +}; + +static const char* null_str = "null"; + +struct decode_daemon_str { + DAEMONS_T* daemons; + AFB_ApiT api; + const char* ignored_daemon; +}; + +static void decode_daemons_cb(void* closure, json_object* obj, const char* fName) +{ + int rc; + struct afb_cred cred; + json_object *j_response, *j_query, *j_config, *j_ws_servers, *j_ws_clients; + json_object *j_name, *j_apis; + struct decode_daemon_str* clStr = (struct decode_daemon_str*)closure; + DAEMON_T* daemon = calloc(sizeof(DAEMON_T), 1); + + if (!clStr->daemons) + return; + + if ((rc = wrap_json_unpack(obj, "{si si si ss ss ss}", "pid", &cred.pid, + "uid", &cred.uid, "gid", &cred.gid, "id", &cred.id, + "label", &cred.label, "user", &cred.user)) + < 0) { + // TODO + return; + } + + AFB_ApiInfo(clStr->api, "Get config of pid %d", cred.pid); + daemon->pid = cred.pid; + + // Get config + wrap_json_pack(&j_query, "{s:i}", "pid", cred.pid); + rc = AFB_ServiceSync(clStr->api, SRV_SUPERVISOR_NAME, "config", j_query, &j_response); + if (rc < 0) { + AFB_ApiError(clStr->api, "Cannot get config of pid %d", cred.pid); + return; + } + + AFB_ApiDebug(clStr->api, "%s config result, res=%s", SRV_SUPERVISOR_NAME, + json_object_to_json_string(j_response)); + + if (json_object_object_get_ex(j_response, "response", &j_config)) { + // FIXME : implement free + daemon->config = j_config; + + rc = wrap_json_unpack(j_config, "{s:o s:o s:o}", + "name", &j_name, + "ws_servers", &j_ws_servers, + "ws_clients", &j_ws_clients); + if (rc < 0) { + AFB_ApiError(clStr->api, "Error decoding config response %s", wrap_json_get_error_string(rc)); + return; + } + + daemon->name = json_object_is_type(j_name, json_type_null) ? null_str : json_object_get_string(j_name); + + // ignored some daemon + if (clStr->ignored_daemon != NULL && strstr(daemon->name, clStr->ignored_daemon) != NULL) { + free(daemon); + return; + } + + daemon->ws_servers = j_ws_servers; + daemon->isServer = (json_object_array_length(j_ws_servers) > 0); + daemon->ws_clients = j_ws_clients; + daemon->isClient = (json_object_array_length(j_ws_clients) > 0); + } + + // Get apis + // '{"pid":6262,"api":"monitor","verb":"get","args":{"apis":true}} + wrap_json_pack(&j_query, "{si ss ss s {sb}}", + "pid", cred.pid, + "api", "monitor", + "verb", "get", + "args", "apis", true); + rc = AFB_ServiceSync(clStr->api, SRV_SUPERVISOR_NAME, "do", j_query, &j_response); + if (rc < 0) { + AFB_ApiError(clStr->api, "Cannot get apis of pid %d", cred.pid); + return; + } else { + AFB_ApiDebug(clStr->api, "%s do ...get apis result, res=%s", SRV_SUPERVISOR_NAME, json_object_to_json_string(j_response)); + + if (json_object_object_get_ex(j_response, "response", &j_config) && json_object_object_get_ex(j_config, "apis", &j_apis)) { + daemon->apis = j_apis; + } + } + clStr->daemons->daemons[clStr->daemons->count] = daemon; + clStr->daemons->count++; +} + +int getDaemons(AFB_ApiT apiHandle, DAEMONS_T** daemons) +{ + int rc; + json_object *j_response, *j_daemons = NULL; + + *daemons = calloc(sizeof(DAEMONS_T), 1); + + if ((rc = AFB_ServiceSync(apiHandle, SRV_SUPERVISOR_NAME, "discover", NULL, + &j_response)) + < 0) { + return rc; + } + + if ((rc = AFB_ServiceSync(apiHandle, SRV_SUPERVISOR_NAME, "list", NULL, + &j_response)) + < 0) { + return rc; + } + + AFB_ApiDebug(apiHandle, "%s list result, res=%s", SRV_SUPERVISOR_NAME, json_object_to_json_string(j_response)); + + if (json_object_object_get_ex(j_response, "response", &j_daemons)) { + struct decode_daemon_str str = { + *daemons, + apiHandle, + GetBinderName() + }; + wrap_json_object_for_all(j_daemons, decode_daemons_cb, &str); + } + + return 0; +} + +int trace_exchange(AFB_ApiT apiHandle, DAEMON_T* svr, DAEMON_T* cli) +{ + int rc; + json_object *j_response, *j_query; + + if (svr == NULL || cli == NULL) { + return -1; + } + + wrap_json_pack(&j_query, "{s:i, s:{s:s}}", "pid", svr->pid, "add", + "request", "common"); + if ((rc = AFB_ServiceSync(apiHandle, SRV_SUPERVISOR_NAME, "trace", j_query, + &j_response)) + < 0) { + AFB_ApiError(apiHandle, "ERROR trace %d result: %s", svr->pid, + json_object_to_json_string(j_response)); + return rc; + } + + wrap_json_pack(&j_query, "{s:i}", "pid", cli->pid); + if ((rc = AFB_ServiceSync(apiHandle, SRV_SUPERVISOR_NAME, "trace", j_query, + &j_response)) + < 0) { + AFB_ApiError(apiHandle, "ERROR trace %d result: %s", cli->pid, + json_object_to_json_string(j_response)); + return rc; + } + + return 0; +} + +int supervisor_init(void) +{ + return 0; +} diff --git a/src/plugins/supervisor.h b/src/plugins/supervisor.h new file mode 100644 index 0000000..3311734 --- /dev/null +++ b/src/plugins/supervisor.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author "Sebastien Douheret" <sebastien@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. + */ +#pragma once + +#include <stdbool.h> +#include "wrap-json.h" + +#define SRV_SUPERVISOR_NAME "supervisor" + +// FIXME Use chained list instead of static array +#define MAX_CLIENTS 32 +#define MAX_SERVERS 32 +#define MAX_DAEMONS 1024 + + +typedef struct daemon +{ + int pid; + const char* name; + bool isServer; + bool isClient; + //char *ws_clients[MAX_CLIENTS]; + //char *ws_servers[MAX_SERVERS]; + json_object *ws_clients; + json_object *ws_servers; + json_object *config; + json_object *apis; +} DAEMON_T; + +typedef struct daemons_result_ +{ + int count; + DAEMON_T *daemons[MAX_DAEMONS]; +} DAEMONS_T; + + +extern int getDaemons(AFB_ApiT apiHandle, DAEMONS_T **daemons); +extern int trace_exchange(AFB_ApiT apiHandle, DAEMON_T *svr, DAEMON_T *cli); +extern int supervisor_init(void); diff --git a/src/utils/list.c b/src/utils/list.c new file mode 100644 index 0000000..d47f761 --- /dev/null +++ b/src/utils/list.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author "Romain Forlot" <romain.forlot@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. + */ + +#include "list.h" +#include "string.h" + +void destroy_list(struct list *l) +{ + struct list *save; + while(l != NULL) { + save = l->next; + free(l); + l = save; + } +} + +void add_elt(struct list **l, const char *key, json_object *value) +{ + struct list *new_elt = malloc(sizeof(struct list)); + new_elt->key = key; + new_elt->value = value; + new_elt->next = NULL; + + if(*l) { + while((*l)->next != NULL) { + *l = (*l)->next; + } + (*l)->next = new_elt; + } + else { + *l = new_elt; + } +} + +void add_key(struct list **l, const char *key) +{ + struct list *new_elt = malloc(sizeof(struct list)); + new_elt->key = key; + new_elt->value = NULL; + new_elt->next = NULL; + + if(*l) { + while((*l)->next != NULL) { + *l = (*l)->next; + } + (*l)->next = new_elt; + } + else { + *l = new_elt; + } +} + +int set_value(struct list *l, json_object *val, int index) +{ + int i; + + for (i = 0; i < index; i++) { + l = l->next; + if ( l == NULL ) + return -1; + } + + l->value = val; + return 0; +} + +struct list *get_elt(struct list *l, int index) +{ + int i; + + for (i = 0; i < index; i++) { + l = l->next; + if ( l == NULL ) + return NULL; + } + + return l; +} + +struct list *find_elt_from_key(struct list *l, const char *key) +{ + while(l != NULL) { + if(strcasecmp(l->key, key) == 0) + return l; + l = l->next; + } + return NULL; +} + +json_object *find_key_value(struct list *l, const char *key) +{ + while(l != NULL) { + if(strcasecmp(l->key, key) == 0) + return l->value; + l = l->next; + } + return NULL; +} diff --git a/src/utils/list.h b/src/utils/list.h new file mode 100644 index 0000000..9f93cb6 --- /dev/null +++ b/src/utils/list.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author "Romain Forlot" <romain.forlot@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 _LIST_H_ +#define _LIST_H_ + +#include <stdlib.h> +#include <json-c/json.h> + +struct list { + const char *key; + json_object *value; + struct list *next; +}; + +void destroy_list(struct list *l); +void add_elt(struct list **l, const char *key, json_object *value); +void add_key(struct list **l, const char *key); +int set_value(struct list *l, json_object *val, int index); +struct list *get_elt(struct list *l, int index); +struct list *find_elt_from_key(struct list *l, const char *key); +json_object *find_key_value(struct list *l, const char *key); + +#endif diff --git a/src/xds-apidef.json b/src/xds-apidef.json new file mode 100644 index 0000000..949e3e8 --- /dev/null +++ b/src/xds-apidef.json @@ -0,0 +1,154 @@ +{ + "openapi": "3.0.0", + "$schema": "http://iot.bzh/download/openapi/schema-3.0/default-schema.json", + "info": { + "description": "", + "title": "xds", + "version": "4.0", + "x-binding-c-generator": { + "api": "xds", + "version": 2, + "prefix": "afv_", + "postfix": "", + "start": null , + "onevent": null, + "init": "init", + "scope": "", + "private": false + } + }, + "servers": [ + { + "url": "ws://{host}:{port}/api/monitor", + "description": "TS caching binding", + "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": { + "list": { + "permission": "urn:AGL:permission::platform:can:list " + }, + "trace": { + "permission": "urn:AGL:permission::platform:can:trace " + } + }, + "responses": { + "200": { + "description": "A complex object array response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/afb-reply" + } + } + } + } + } + }, + "paths": { + "/auth": { + "description": "Authenticate session to raise Level Of Assurance of the session", + "get": { + "x-permissions": { + "$ref": "#/components/x-permissions/list" + }, + "responses": { + "200": { + "$ref": "#/components/responses/200" + } + } + } + }, + "/list": { + "description": "list ", + "get": { + "x-permissions": { + "LOA": 1 + }, + "parameters": [], + "responses": { + "200": { + "$ref": "#/components/responses/200" + } + } + } + }, + "/trace": { + "description": "trace ", + "get": { + "x-permissions": { + "LOA": 1 + }, + "parameters": [{ + "in": "query", + "name": "ws", + "required": true, + "schema": { + "type": "string" + } + }], + "responses": { + "200": { + "$ref": "#/components/responses/200" + } + } + } + } + } +} diff --git a/src/xds-binding.c b/src/xds-binding.c new file mode 100644 index 0000000..4f7971f --- /dev/null +++ b/src/xds-binding.c @@ -0,0 +1,157 @@ +/* +* Copyright (C) 2016 "IoT.bzh" +* Author Fulup Ar Foll <fulup@iot.bzh> +* Author Romain Forlot <romain@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 "xds-binding.h" + + +// default api to print log when apihandle not avaliable +afb_dynapi *AFB_default; + +// Config Section definition (note: controls section index should match handle +// retrieval in HalConfigExec) +static CtlSectionT ctrlSections[] = { + {.key = "plugins" , .loadCB = PluginConfig}, + {.key = "onload" , .loadCB = OnloadConfig}, + {.key = "controls", .loadCB = ControlConfig}, + {.key = "events" , .loadCB = EventConfig}, + {.key = NULL} +}; + +static void ctrlapi_ping(AFB_ReqT request) { + static int count = 0; + + count++; + AFB_ReqNotice(request, "Controller:ping count=%d", count); + AFB_ReqSucess(request, json_object_new_int(count), NULL); + + return; +} + +void ctrlapi_auth(AFB_ReqT request) +{ + AFB_ReqSetLOA(request, 1); + AFB_ReqSucess(request, NULL, NULL); +} + +static AFB_ApiVerbs CtrlApiVerbs[] = { + /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */ + {.verb = "ping", .callback = ctrlapi_ping, .info = "ping test for API"}, + {.verb = "auth", .callback = ctrlapi_auth, .info = "Authenticate session to raise Level Of Assurance of the session"}, + {.verb = NULL} /* marker for end of the array */ +}; + +static int CtrlLoadStaticVerbs(afb_dynapi *apiHandle, AFB_ApiVerbs *verbs) { + int errcount = 0; + + for (int idx = 0; verbs[idx].verb; idx++) { + errcount += afb_dynapi_add_verb( + apiHandle, CtrlApiVerbs[idx].verb, NULL, CtrlApiVerbs[idx].callback, + (void *)&CtrlApiVerbs[idx], CtrlApiVerbs[idx].auth, 0); + } + + return errcount; +}; + +static int CtrlInitOneApi(AFB_ApiT apiHandle) { + int err = 0; + AFB_default = apiHandle; // hugely hack to make all V2 AFB_DEBUG to work in fileutils + + // retrieve section config from api handle + CtlConfigT *ctrlConfig = (CtlConfigT *)afb_dynapi_get_userdata(apiHandle); + err = CtlConfigExec(apiHandle, ctrlConfig); + if(err) { + AFB_ApiError(apiHandle, "Error at CtlConfigExec step"); + return err; + } + + return err; +} + +// next generation dynamic API-V3 mode +#include <signal.h> + +static int CtrlLoadOneApi(void *cbdata, AFB_ApiT apiHandle) { + CtlConfigT *ctrlConfig = (CtlConfigT *)cbdata; + + // save closure as api's data context + afb_dynapi_set_userdata(apiHandle, ctrlConfig); + + // add static controls verbs + int err = CtrlLoadStaticVerbs(apiHandle, CtrlApiVerbs); + if (err) { + AFB_ApiError(apiHandle, "CtrlLoadSection fail to register static V2 verbs"); + return ERROR; + } + + // load section for corresponding API + err = CtlLoadSections(apiHandle, ctrlConfig, ctrlSections); + + // declare an event event manager for this API; + afb_dynapi_on_event(apiHandle, CtrlDispatchApiEvent); + + // init API function (does not receive user closure ??? + afb_dynapi_on_init(apiHandle, CtrlInitOneApi); + + afb_dynapi_seal(apiHandle); + return err; +} + +int afbBindingVdyn(afb_dynapi *apiHandle) { + + AFB_default = apiHandle; + AFB_ApiNotice(apiHandle, "Controller in afbBindingVdyn"); + + const char *dirList = getenv("CONTROL_CONFIG_PATH"); + if (!dirList) + dirList = CONTROL_CONFIG_PATH; + + const char *configPath = CtlConfigSearch(apiHandle, dirList, ""); + if (!configPath) { + AFB_ApiError(apiHandle, "CtlPreInit: No %s* config found in %s ", GetBinderName(), dirList); + return ERROR; + } + + // load config file and create API + CtlConfigT *ctrlConfig = CtlLoadMetaData(apiHandle, configPath); + if (!ctrlConfig) { + AFB_ApiError(apiHandle, + "CtrlBindingDyn No valid control config file in:\n-- %s", + configPath); + return ERROR; + } + + if (!ctrlConfig->api) { + AFB_ApiError(apiHandle, + "CtrlBindingDyn API Missing from metadata in:\n-- %s", + configPath); + return ERROR; + } + + AFB_ApiNotice(apiHandle, "Controller API='%s' info='%s'", ctrlConfig->api, + ctrlConfig->info); + + // create one API per config file (Pre-V3 return code ToBeChanged) + int status = afb_dynapi_new_api(apiHandle, ctrlConfig->api, ctrlConfig->info, 1, CtrlLoadOneApi, ctrlConfig); + + return status; +} diff --git a/src/xds-binding.h b/src/xds-binding.h new file mode 100644 index 0000000..7ac00a0 --- /dev/null +++ b/src/xds-binding.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll <fulup@iot.bzh> + * Author Romain Forlot <romain@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 _CTL_BINDING_INCLUDE_ +#define _CTL_BINDING_INCLUDE_ + +#include <stdio.h> +#include <ctl-config.h> +#include <filescan-utils.h> +#include <wrap-json.h> + +#ifndef ERROR + #define ERROR -1 +#endif + +#endif /* _CTL_BINDING_INCLUDE_ */ |