aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt45
-rw-r--r--src/plugins/CMakeLists.txt42
-rw-r--r--src/plugins/supervisor-api.c164
-rw-r--r--src/plugins/supervisor-api.h36
-rw-r--r--src/plugins/supervisor.c194
-rw-r--r--src/plugins/supervisor.h53
-rw-r--r--src/utils/list.c112
-rw-r--r--src/utils/list.h37
-rw-r--r--src/xds-apidef.json154
-rw-r--r--src/xds-binding.c157
-rw-r--r--src/xds-binding.h32
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_ */