summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastien Douheret <sebastien.douheret@iot.bzh>2018-04-12 09:42:39 +0200
committerSebastien Douheret <sebastien.douheret@iot.bzh>2018-07-10 23:59:53 +0200
commitd67d4335f05635d06b433f7d3fa0f6a4e401ec92 (patch)
treeb5d57ea1620278f65008f8faf34648f58d04da42
Initial commit
Change-Id: Ia434e5b4869ea19b0b78b1c586c44c15cb93c7e8 Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
-rw-r--r--.gitignore9
-rw-r--r--.gitmodules9
-rw-r--r--.vscode/.cmaketools.json10
-rw-r--r--.vscode/c_cpp_properties.json86
-rw-r--r--.vscode/launch.json40
-rw-r--r--.vscode/settings.json49
-rw-r--r--.vscode/tasks.json33
-rw-r--r--CMakeLists.txt3
-rw-r--r--LICENSE21
-rw-r--r--README.md58
m---------afb-helpers0
m---------conf.d/app-templates0
-rwxr-xr-xconf.d/autobuild/agl/autobuild67
-rwxr-xr-xconf.d/autobuild/linux/autobuild67
-rw-r--r--conf.d/cmake/config.cmake209
-rw-r--r--conf.d/packaging/agl-xds-service.dsc18
-rw-r--r--conf.d/packaging/agl-xds-service.spec66
-rw-r--r--conf.d/packaging/debian.agl-xds-service.install2
-rw-r--r--conf.d/packaging/debian.changelog5
-rw-r--r--conf.d/packaging/debian.compat1
-rw-r--r--conf.d/packaging/debian.control19
-rw-r--r--conf.d/packaging/debian.rules87
-rw-r--r--conf.d/wgt/config.xml.in17
-rw-r--r--htdocs/AFB-websock.js177
-rw-r--r--htdocs/CMakeLists.txt33
-rw-r--r--htdocs/assets/background_iot_bzh_light.jpgbin0 -> 40718 bytes
-rw-r--r--htdocs/assets/favicon.icobin0 -> 1150 bytes
-rw-r--r--htdocs/assets/iot-bzh-logo-small.pngbin0 -> 14449 bytes
-rw-r--r--htdocs/index.html48
-rw-r--r--htdocs/iotbzh-Binding.css59
-rw-r--r--htdocs/iotbzh-Binding.js149
-rw-r--r--xds-service/CMakeLists.txt42
-rw-r--r--xds-service/supervisor-service.c179
-rw-r--r--xds-service/supervisor-service.h51
-rw-r--r--xds-service/xds-service-api.c224
-rw-r--r--xds-service/xds-service-api.h24
-rw-r--r--xds-service/xds-service-apidef.h85
-rw-r--r--xds-service/xds-service-apidef.json152
38 files changed, 2099 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f8ce442
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+build*
+package
+nbproject/private
+.stfolder
+.*.sw*
+*.tar.gz
+__*
+htdocs/node_modules
+htdocs/package-lock.json
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..1900866
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,9 @@
+[submodule "conf.d/app-templates"]
+ path = conf.d/app-templates
+ url = https://gerrit.automotivelinux.org/gerrit/p/apps/app-templates.git
+[submodule "ctl-utilities"]
+ path = ctl-utilities
+ url = https://gerrit.automotivelinux.org/gerrit/apps/app-controller-submodule
+[submodule "afb-helpers"]
+ path = afb-helpers
+ url = https://gerrit.automotivelinux.org/gerrit/apps/app-afb-helpers-submodule
diff --git a/.vscode/.cmaketools.json b/.vscode/.cmaketools.json
new file mode 100644
index 0000000..0a3d8ea
--- /dev/null
+++ b/.vscode/.cmaketools.json
@@ -0,0 +1,10 @@
+{
+ "variant": {
+ "label": "Debug",
+ "keywordSettings": {
+ "buildType": "debug"
+ },
+ "description": "Emit debug information without performing optimizations"
+ },
+ "activeEnvironments": []
+} \ No newline at end of file
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000..1c01abe
--- /dev/null
+++ b/.vscode/c_cpp_properties.json
@@ -0,0 +1,86 @@
+{
+ "configurations": [
+ {
+ "name": "Mac",
+ "includePath": [
+ "/usr/include",
+ "/usr/local/include",
+ "${workspaceFolder}"
+ ],
+ "defines": [],
+ "intelliSenseMode": "clang-x64",
+ "browse": {
+ "path": [
+ "/usr/include",
+ "/usr/local/include",
+ "${workspaceFolder}"
+ ],
+ "limitSymbolsToIncludedHeaders": true,
+ "databaseFilename": ""
+ },
+ "macFrameworkPath": [
+ "/System/Library/Frameworks",
+ "/Library/Frameworks"
+ ]
+ },
+ {
+ "name": "Linux",
+ "includePath": [
+ "${workspaceFolder}",
+ "/opt/AGL/include",
+ "/usr/include/c++/4.8",
+ "/usr/include/c++/4.8/x86_64-suse-linux",
+ "/usr/include/c++/4.8/backward",
+ "/usr/lib64/gcc/x86_64-suse-linux/4.8/include",
+ "/usr/local/include",
+ "/usr/lib64/gcc/x86_64-suse-linux/4.8/include-fixed",
+ "/usr/x86_64-suse-linux/include",
+ "/usr/include",
+ "${workspaceFolder}/afb-helpers"
+ ],
+ "defines": [],
+ "intelliSenseMode": "clang-x64",
+ "browse": {
+ "path": [
+ "${workspaceFolder}",
+ "/opt/AGL/include",
+ "/usr/include/c++/4.8",
+ "/usr/include/c++/4.8/x86_64-suse-linux",
+ "/usr/include/c++/4.8/backward",
+ "/usr/lib64/gcc/x86_64-suse-linux/4.8/include",
+ "/usr/local/include",
+ "/usr/lib64/gcc/x86_64-suse-linux/4.8/include-fixed",
+ "/usr/x86_64-suse-linux/include",
+ "/usr/include"
+ ],
+ "limitSymbolsToIncludedHeaders": true,
+ "databaseFilename": ""
+ },
+ "compilerPath": "/usr/bin/gcc",
+ "cStandard": "c11",
+ "cppStandard": "c++14"
+ },
+ {
+ "name": "Win32",
+ "includePath": [
+ "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include",
+ "${workspaceFolder}"
+ ],
+ "defines": [
+ "_DEBUG",
+ "UNICODE",
+ "_UNICODE"
+ ],
+ "intelliSenseMode": "msvc-x64",
+ "browse": {
+ "path": [
+ "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*",
+ "${workspaceFolder}"
+ ],
+ "limitSymbolsToIncludedHeaders": true,
+ "databaseFilename": ""
+ }
+ }
+ ],
+ "version": 3
+} \ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..b6f6fc5
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,40 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "(gdb) Launch",
+ "type": "cppdbg",
+ "request": "launch",
+ "program": "/opt/AGL/bin/afb-daemon",
+ "args": [
+ "--port=5678",
+ "--ws-client=unix:/tmp/supervisor",
+ "--workdir=${workspaceRoot}/build/package/",
+ "--ldpaths=lib",
+ "--roothttp=htdocs",
+ "--token=",
+ "--tracereq=common",
+ "-vvv"
+ ],
+ "additionalSOLibSearchPath": "${workspaceRoot}/build/package/lib",
+ "stopAtEntry": false,
+ "cwd": "${workspaceRoot}/build/package",
+ "environment": [
+ ],
+ "externalConsole": false,
+ "MIMode": "gdb",
+ "setupCommands": [
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": true
+ }
+ ],
+ "showDisplayString": true,
+ "preLaunchTask": "Build"
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..d2877c4
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,49 @@
+{
+ "files.associations": {
+ "*.bb": "bat",
+ "*.inc": "bat",
+ "*.bbclass": "bat",
+ "*.rules": "shellscript",
+ "json.h": "c",
+ "afb-binding.h": "c",
+ "string.h": "c",
+ "stdio.h": "c",
+ "wrap-json.h": "c",
+ "curl-wrap.h": "c",
+ "afb-binding-v2.h": "c",
+ "afb-daemon-itf.h": "c",
+ "afb-service-itf.h": "c",
+ "afb-req.h": "c",
+ "afb-req-v2.h": "c",
+ "xds-service.h": "c",
+ "xds-service-api.h": "c",
+ "*.tcc": "c",
+ "functional": "c",
+ "array": "c",
+ "stdbool.h": "c",
+ "cstring": "c",
+ "xds-service-apidef.h": "c",
+ "tuple": "c",
+ "type_traits": "c",
+ "utility": "c",
+ "supervisor-service.h": "c",
+ "typeinfo": "c",
+ "istream": "c"
+ },
+
+ // Words to add to dictionary for a workspace.
+ "cSpell.words": [
+ "callbinder",
+ "gotevent",
+ "ldpaths",
+ "lightgreen",
+ "mysecret",
+ "onevent",
+ "openapi",
+ "outevt",
+ "replyerr",
+ "replyok",
+ "reqid",
+ "roothttp"
+ ]
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..d1709f7
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,33 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Initial Build",
+ "type": "shell",
+ "command": "rm -rf build && mkdir -p build && cd build && pwd && cmake ..",
+ "problemMatcher": [
+ "$gcc"
+ ]
+ },
+ {
+ "label": "Build",
+ "type": "shell",
+ "command": "clear && cd build && make",
+ "presentation": {
+ "echo": true,
+ "reveal": "always",
+ "focus": false,
+ "panel": "shared"
+ },
+ "problemMatcher": [
+ "$gcc"
+ ],
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
+ }
+ ]
+}
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..f757721
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,3 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/conf.d/cmake/config.cmake)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..338fd9d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 IoT.bzh
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..155cb10
--- /dev/null
+++ b/README.md
@@ -0,0 +1,58 @@
+# agl-service-xds
+
+An AGL binding used to control collected data. Those data may come from
+`agl-low-collector` or from AGL `supervision`.
+
+**UNDER DEVELOPMENT - this binding is not fully functional, it's a proof of concept for now**
+
+## Setup
+
+```bash
+git clone --recursive https://github.com/iotbzh/agl-server-xds
+cd agl-server-xds
+```
+
+## Build for AGL
+
+```bash
+#setup your build environement
+. /xdt/sdk/environment-setup-aarch64-agl-linux
+#build your application
+./conf.d/autobuild/agl/autobuild package
+```
+
+## Build for 'native' Linux distros (Fedora, openSUSE, Debian, Ubuntu, ...)
+
+```bash
+./conf.d/autobuild/linux/autobuild package
+```
+
+You can also use binary package from OBS: [opensuse.org/LinuxAutomotive][opensuse.org/LinuxAutomotive]
+
+## Test
+
+### Native setup
+
+Here are commands used to setup some bindings in order to test on `xds-service` natively on a Linux host:
+
+```bash
+afs-supervisor --port 1712 --token HELLO --ws-server=unix:/tmp/supervisor -vv
+
+cd $ROOT_DIR/app-framework-binder
+afb-daemon -t '' -p 5555 -M --roothttp test --ws-server unix:ave --name test_server -vv
+afb-daemon -t '' -p 4444 -M --roothttp test --no-ldpaths --ws-client unix:ave --name test_client -vv
+
+cd $ROOT_DIR/agl-service-harvester
+afb-daemon --port=1234 --workdir=./build/package --ldpaths=lib --roothttp=htdocs --token= --tracereq=common -vv --ws-server unix:/tmp/harvester
+
+cd $ROOT_DIR/agl-service-xds
+./conf.d/autobuild/linux/autobuild build
+afb-daemon --port=5678 --workdir=./build/package --ldpaths=lib --roothttp=htdocs --token= --ws-client=unix:/tmp/supervisor --ws-client=unix:/tmp/harvester -vv
+
+```
+
+## Deploy
+
+### AGL
+
+TBD
diff --git a/afb-helpers b/afb-helpers
new file mode 160000
+Subproject 9e880552ea9f375de636b535c04b4729aaa1fa9
diff --git a/conf.d/app-templates b/conf.d/app-templates
new file mode 160000
+Subproject a3c312ece0a77310a9d8ecde1dd0f1267646f4f
diff --git a/conf.d/autobuild/agl/autobuild b/conf.d/autobuild/agl/autobuild
new file mode 100755
index 0000000..83097ab
--- /dev/null
+++ b/conf.d/autobuild/agl/autobuild
@@ -0,0 +1,67 @@
+#!/usr/bin/make -f
+# Copyright (C) 2015, 2016 "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.
+
+THISFILE := $(lastword $(MAKEFILE_LIST))
+BUILD_DIR := $(abspath $(dir $(THISFILE)/../../../../..)/build)
+DEST := ${BUILD_DIR}/target
+
+.PHONY: all clean distclean configure build package help update
+
+all: help
+
+help:
+ @echo "List of targets available:"
+ @echo ""
+ @echo "- all"
+ @echo "- clean"
+ @echo "- distclean"
+ @echo "- configure"
+ @echo "- build: compilation, link and prepare files for package into a widget"
+ @echo "- package: output a widget file '*.wgt'"
+ @echo "- install: install in your ${CMAKE_INSTALL_DIR} directory"
+ @echo ""
+ @echo "Usage: ./conf.d/autobuild/agl/autobuild package DEST=${HOME}/opt"
+ @echo "Don't use your build dir as DEST as wgt file is generated at this location"
+
+update: configure
+ @cmake --build ${BUILD_DIR} --target autobuild
+
+clean:
+ @([ -d ${BUILD_DIR} ] && make -C ${BUILD_DIR} clean) || echo Nothing to clean
+
+distclean:
+ @rm -rf ${BUILD_DIR}
+
+configure: ${BUILD_DIR}/Makefile
+
+build: configure
+ @cmake --build ${BUILD_DIR} ${BUILD_ARGS} --target all
+
+package: build
+ @mkdir -p ${BUILD_DIR}/$@/bin
+ @mkdir -p ${BUILD_DIR}/$@/etc
+ @mkdir -p ${BUILD_DIR}/$@/lib
+ @mkdir -p ${BUILD_DIR}/$@/htdocs
+ @mkdir -p ${BUILD_DIR}/$@/var
+ @cmake --build ${BUILD_DIR} --target widget
+ @mkdir -p ${DEST} && cp ${BUILD_DIR}/*wgt ${DEST}
+
+install: build
+ @cmake --build ${BUILD_DIR} --target install
+
+${BUILD_DIR}/Makefile:
+ @[ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}
+ @[ -f ${BUILD_DIR}/Makefile ] || (cd ${BUILD_DIR} && cmake ${CONFIGURE_ARGS} ..)
diff --git a/conf.d/autobuild/linux/autobuild b/conf.d/autobuild/linux/autobuild
new file mode 100755
index 0000000..83097ab
--- /dev/null
+++ b/conf.d/autobuild/linux/autobuild
@@ -0,0 +1,67 @@
+#!/usr/bin/make -f
+# Copyright (C) 2015, 2016 "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.
+
+THISFILE := $(lastword $(MAKEFILE_LIST))
+BUILD_DIR := $(abspath $(dir $(THISFILE)/../../../../..)/build)
+DEST := ${BUILD_DIR}/target
+
+.PHONY: all clean distclean configure build package help update
+
+all: help
+
+help:
+ @echo "List of targets available:"
+ @echo ""
+ @echo "- all"
+ @echo "- clean"
+ @echo "- distclean"
+ @echo "- configure"
+ @echo "- build: compilation, link and prepare files for package into a widget"
+ @echo "- package: output a widget file '*.wgt'"
+ @echo "- install: install in your ${CMAKE_INSTALL_DIR} directory"
+ @echo ""
+ @echo "Usage: ./conf.d/autobuild/agl/autobuild package DEST=${HOME}/opt"
+ @echo "Don't use your build dir as DEST as wgt file is generated at this location"
+
+update: configure
+ @cmake --build ${BUILD_DIR} --target autobuild
+
+clean:
+ @([ -d ${BUILD_DIR} ] && make -C ${BUILD_DIR} clean) || echo Nothing to clean
+
+distclean:
+ @rm -rf ${BUILD_DIR}
+
+configure: ${BUILD_DIR}/Makefile
+
+build: configure
+ @cmake --build ${BUILD_DIR} ${BUILD_ARGS} --target all
+
+package: build
+ @mkdir -p ${BUILD_DIR}/$@/bin
+ @mkdir -p ${BUILD_DIR}/$@/etc
+ @mkdir -p ${BUILD_DIR}/$@/lib
+ @mkdir -p ${BUILD_DIR}/$@/htdocs
+ @mkdir -p ${BUILD_DIR}/$@/var
+ @cmake --build ${BUILD_DIR} --target widget
+ @mkdir -p ${DEST} && cp ${BUILD_DIR}/*wgt ${DEST}
+
+install: build
+ @cmake --build ${BUILD_DIR} --target install
+
+${BUILD_DIR}/Makefile:
+ @[ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}
+ @[ -f ${BUILD_DIR}/Makefile ] || (cd ${BUILD_DIR} && cmake ${CONFIGURE_ARGS} ..)
diff --git a/conf.d/cmake/config.cmake b/conf.d/cmake/config.cmake
new file mode 100644
index 0000000..face63f
--- /dev/null
+++ b/conf.d/cmake/config.cmake
@@ -0,0 +1,209 @@
+###########################################################################
+# Copyright 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.
+###########################################################################
+
+# Project Info
+# ------------------
+set(PROJECT_NAME xds-service)
+set(PROJECT_VERSION "1.0")
+set(PROJECT_PRETTY_NAME "XDS collector service for AGL")
+set(PROJECT_DESCRIPTION "Provide an AGL XDS collector Binding")
+set(PROJECT_URL "https://github.com/iotbzh/agl-service-xds")
+set(PROJECT_ICON "icon.png")
+set(PROJECT_AUTHOR "Sebastien Douheret")
+set(PROJECT_AUTHOR_MAIL "sebastien@iot.bzh")
+set(PROJECT_LICENSE "APL2.0")
+set(PROJECT_LANGUAGES "C")
+
+# Where are stored default templates files from submodule or subtree app-templates in your project tree
+# relative to the root project directory
+set(PROJECT_APP_TEMPLATES_DIR "conf.d/app-templates")
+
+# Where are stored your external libraries for your project. This is 3rd party library that you don't maintain
+# but used and must be built and linked.
+# set(PROJECT_LIBDIR "libs")
+
+# Where are stored data for your application. Pictures, static resources must be placed in that folder.
+# set(PROJECT_RESOURCES "data")
+
+# Which directories inspect to find CMakeLists.txt target files
+# set(PROJECT_SRC_DIR_PATTERN "*")
+
+# Compilation Mode (DEBUG, RELEASE)
+# ----------------------------------
+set(CMAKE_BUILD_TYPE "DEBUG")
+#set(USE_EFENCE 1)
+
+# Kernel selection if needed. You can choose between a
+# mandatory version to impose a minimal version.
+# Or check Kernel minimal version and just print a Warning
+# about missing features and define a preprocessor variable
+# to be used as preprocessor condition in code to disable
+# incompatibles features. Preprocessor define is named
+# KERNEL_MINIMAL_VERSION_OK.
+#
+# NOTE*** FOR NOW IT CHECKS KERNEL Yocto environment and
+# Yocto SDK Kernel version.
+# -----------------------------------------------
+#set (kernel_mandatory_version 4.8)
+#set (kernel_minimal_version 4.8)
+
+# Compiler selection if needed. Impose a minimal version.
+# -----------------------------------------------
+set (gcc_minimal_version 4.9)
+
+# PKG_CONFIG required packages
+# -----------------------------
+set (PKG_REQUIRED_LIST
+ json-c
+ libsystemd>=222
+ afb-daemon>=4.0
+ libmicrohttpd>=0.9.55
+)
+
+# Prefix path where will be installed the files
+# Default: /usr/local (need root permission to write in)
+# ------------------------------------------------------
+set(CMAKE_INSTALL_PREFIX $ENV{HOME}/opt)
+
+# Customize link option
+# -----------------------------
+#list(APPEND link_libraries -an-option)
+list(APPEND link_libraries afb-helpers)
+
+# Compilation options definition
+# Use CMake generator expressions to specify only for a specific language
+# Values are prefilled with default options that is currently used.
+# Either separate options with ";", or each options must be quoted separately
+# DO NOT PUT ALL OPTION QUOTED AT ONCE , COMPILATION COULD FAILED !
+# ----------------------------------------------------------------------------
+#set(COMPILE_OPTIONS
+# -Wall
+# -Wextra
+# -Wconversion
+# -Wno-unused-parameter
+# -Wno-sign-compare
+# -Wno-sign-conversion
+# -Werror=maybe-uninitialized
+# -Werror=implicit-function-declaration
+# -ffunction-sections
+# -fdata-sections
+# -fPIC
+# CACHE STRING "Compilation flags")
+#set(C_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C language.")
+#set(CXX_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C++ language.")
+#set(PROFILING_COMPILE_OPTIONS
+# -g
+# -O0
+# -pg
+# -Wp,-U_FORTIFY_SOURCE
+# CACHE STRING "Compilation flags for PROFILING build type.")
+#set(DEBUG_COMPILE_OPTIONS
+# -g
+# -ggdb
+# -Wp,-U_FORTIFY_SOURCE
+# CACHE STRING "Compilation flags for DEBUG build type.")
+#set(CCOV_COMPILE_OPTIONS
+# -g
+# -O2
+# --coverage
+# CACHE STRING "Compilation flags for CCOV build type.")
+#set(RELEASE_COMPILE_OPTIONS
+# -g
+# -O2
+# CACHE STRING "Compilation flags for RELEASE build type.")
+
+# (BUG!!!) as PKG_CONFIG_PATH does not work [should be an env variable]
+# ---------------------------------------------------------------------
+set(CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
+set(LD_LIBRARY_PATH ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib)
+
+# Optional location for config.xml.in
+# -----------------------------------
+#set(WIDGET_ICON "\"conf.d/wgt/${PROJECT_ICON}\"" CACHE PATH "Path to the widget icon")
+#set(WIDGET_CONFIG_TEMPLATE "\"${CMAKE_CURRENT_SOURCE_DIR}/conf.d/wgt/config.xml.in\"" CACHE PATH "Path to widget config file template (config.xml.in)")
+
+# Mandatory widget Mimetype specification of the main unit
+# --------------------------------------------------------------------------
+# Choose between :
+#- text/html : HTML application,
+# content.src designates the home page of the application
+#
+#- application/vnd.agl.native : AGL compatible native,
+# content.src designates the relative path of the binary.
+#
+# - application/vnd.agl.service: AGL service, content.src is not used.
+#
+#- ***application/x-executable***: Native application,
+# content.src designates the relative path of the binary.
+# For such application, only security setup is made.
+#
+set(WIDGET_TYPE application/vnd.agl.service)
+
+# Mandatory Widget entry point file of the main unit
+# --------------------------------------------------------------
+# This is the file that will be executed, loaded,
+# at launch time by the application framework.
+#
+set(WIDGET_ENTRY_POINT config.xml)
+
+# Optional dependencies order
+# ---------------------------
+#set(EXTRA_DEPENDENCIES_ORDER)
+
+# Optional Extra global include path
+# -----------------------------------
+#set(EXTRA_INCLUDE_DIRS)
+
+# Optional extra libraries
+# -------------------------
+#set(EXTRA_LINK_LIBRARIES)
+
+# Optional force binding installation
+# ------------------------------------
+# set(BINDINGS_INSTALL_PREFIX PrefixPath )
+
+# Optional force binding Linking flag
+# ------------------------------------
+# set(BINDINGS_LINK_FLAG LinkOptions )
+
+# Optional force package prefix generation, like widget
+# -----------------------------------------------------
+# set(PKG_PREFIX DestinationPath)
+
+# Optional Application Framework security token
+# and port use for remote debugging.
+#------------------------------------------------------------
+set(AFB_TOKEN "" CACHE PATH "Default binder security token")
+set(AFB_REMPORT "5678" CACHE PATH "Default binder listening port")
+
+# Print a helper message when every thing is finished
+# ----------------------------------------------------
+set(CLOSING_MESSAGE "Typical binding launch: afb-daemon --port=${AFB_REMPORT} --workdir=${CMAKE_BINARY_DIR}/package --ldpaths=lib --roothttp=htdocs --token=\"${AFB_TOKEN}\" --verbose --ws-client=unix:/tmp/supervisor --ws-client=unix:/tmp/harvester")
+set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt")
+
+# Optional schema validator about now only XML, LUA and JSON
+# are supported
+#------------------------------------------------------------
+#set(LUA_CHECKER "luac" "-p" CACHE STRING "LUA compiler")
+#set(XML_CHECKER "xmllint" CACHE STRING "XML linter")
+#set(JSON_CHECKER "json_verify" CACHE STRING "JSON linter")
+
+# This include is mandatory and MUST happens at the end
+# of this file, else you expose you to unexpected behavior
+# -----------------------------------------------------------
+include(${PROJECT_APP_TEMPLATES_DIR}/cmake/common.cmake)
diff --git a/conf.d/packaging/agl-xds-service.dsc b/conf.d/packaging/agl-xds-service.dsc
new file mode 100644
index 0000000..d99d92d
--- /dev/null
+++ b/conf.d/packaging/agl-xds-service.dsc
@@ -0,0 +1,18 @@
+Format: 1.0
+Source: agl-xds-service
+Binary: agl-xds-service-bin
+Architecture: any
+Version: 2.0-0
+Maintainer: Iot-Team <secretaria@iot.bzh>
+Standards-Version: 3.8.2
+Homepage: https://github.com/iotbzh/xds-service
+Build-Depends: debhelper (>= 5),
+ pkg-config,
+ cmake,
+ gcc,
+ g++,
+ libjson-c-dev ,
+ libsystemd-dev (>= 222),
+ agl-app-framework-binder-dev ,
+ agl-libmicrohttpd-dev (>= 0.9.55)
+Debtransform-Tar: agl-xds-service_1.0.orig.tar.gz
diff --git a/conf.d/packaging/agl-xds-service.spec b/conf.d/packaging/agl-xds-service.spec
new file mode 100644
index 0000000..b8b96ab
--- /dev/null
+++ b/conf.d/packaging/agl-xds-service.spec
@@ -0,0 +1,66 @@
+###########################################################################
+# Copyright 2018 IoT.bzh
+#
+# author: Iot-Team <secretaria@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.
+###########################################################################
+
+
+Name: agl-xds-service
+Version: 1.0
+Release: 1
+Group: AGL
+License: APL2.0
+Summary: Provide an AGL XDS collector Binding
+Url: https://github.com/iotbzh/xds-service
+Source0: %{name}_%{version}.orig.tar.gz
+
+BuildRequires: cmake
+BuildRequires: gcc gcc-c++
+BuildRequires: pkgconfig(json-c)
+BuildRequires: pkgconfig(libsystemd) >= 222
+BuildRequires: pkgconfig(afb-daemon)
+BuildRequires: pkgconfig(libmicrohttpd) >= 0.9.55
+
+
+BuildRoot: %{_tmppath}/%{name}-%{version}-build
+
+%define _prefix /opt/AGL/xds-service
+%define __cmake cmake
+
+%description
+Provide an AGL xds collector Binding
+
+%prep
+%setup -q
+
+%build
+%cmake -DCMAKE_INSTALL_PREFIX:PATH=%{_libdir}
+make %{?_smp_mflags}
+
+%install
+CURDIR=$(pwd)
+[ -d build ] && cd build
+make populate
+mkdir -p %{?buildroot}%{_prefix}
+cp -r package/* %{?buildroot}%{_prefix}
+
+cd $CURDIR
+find %{?buildroot}%{_prefix} -type d -exec echo "%dir {}" \;>> pkg_file
+find %{?buildroot}%{_prefix} -type f -exec echo "{}" \;>> pkg_file
+sed -i 's@%{?buildroot}@@g' pkg_file
+
+
+%files -f pkg_file
+%defattr(-,root,root)
diff --git a/conf.d/packaging/debian.agl-xds-service.install b/conf.d/packaging/debian.agl-xds-service.install
new file mode 100644
index 0000000..5858efd
--- /dev/null
+++ b/conf.d/packaging/debian.agl-xds-service.install
@@ -0,0 +1,2 @@
+/opt/AGL/*
+/etc/profile.d/*
diff --git a/conf.d/packaging/debian.changelog b/conf.d/packaging/debian.changelog
new file mode 100644
index 0000000..721428c
--- /dev/null
+++ b/conf.d/packaging/debian.changelog
@@ -0,0 +1,5 @@
+agl-xds-service (1.0-0) UNRELEASED; urgency=low
+
+ * init build
+
+ -- Iot-Team <secretaria@iot.bzh> Mon, 2 Apr 2018 10:50:38 +0100
diff --git a/conf.d/packaging/debian.compat b/conf.d/packaging/debian.compat
new file mode 100644
index 0000000..45a4fb7
--- /dev/null
+++ b/conf.d/packaging/debian.compat
@@ -0,0 +1 @@
+8
diff --git a/conf.d/packaging/debian.control b/conf.d/packaging/debian.control
new file mode 100644
index 0000000..aab9de9
--- /dev/null
+++ b/conf.d/packaging/debian.control
@@ -0,0 +1,19 @@
+Priority: optional
+Maintainer: Iot-Team <secretaria@iot.bzh>
+Source: agl-xds-service
+Build-Depends: debhelper (>= 5),
+ pkg-config,
+ cmake,
+ gcc,
+ g++,
+ libjson-c-dev ,
+ libsystemd-dev (>= 222),
+ agl-app-framework-binder-dev ,
+ agl-libmicrohttpd-dev (>= 0.9.55)
+Standards-Version: 3.8.2
+Homepage: https://github.com/iotbzh/xds-service
+
+Package: agl-xds-service
+Section: libs
+Architecture: any
+Description: Provide an AGL xds Binding
diff --git a/conf.d/packaging/debian.rules b/conf.d/packaging/debian.rules
new file mode 100644
index 0000000..7a5bcb6
--- /dev/null
+++ b/conf.d/packaging/debian.rules
@@ -0,0 +1,87 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Uncomment this to turn on verbose mode.
+export DH_VERBOSE=1
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -O0
+else
+ CFLAGS += -O2
+endif
+ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
+ INSTALL_PROGRAM += -s
+endif
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ #
+ touch configure-stamp
+
+build: build-stamp
+build-stamp: configure-stamp
+ dh_testdir
+ mkdir -p build
+ cd build;cmake ../ -DCMAKE_INSTALL_PREFIX:PATH=/opt/AGL/xds-service -DCMAKE_INSTALL_LIBDIR:PATH=lib/$(DEB_HOST_MULTIARCH);$(MAKE)
+ #
+ touch build-stamp
+
+clean:
+ #dh_testdir
+ dh_testroot
+ rm -f configure-stamp build-stamp
+ [ ! -f Makefile ] || $(MAKE) distclean
+ #dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_prep
+ dh_installdirs
+ # Add here commands to install the package into debian/tmp
+ mkdir -p debian/tmp/opt/AGL/xds-service;cd build;make populate;cp -r package/* ../debian/tmp/opt/AGL/xds-service/
+ mkdir -p debian/tmp/etc/profile.d
+ echo '#---------- AGL xds-service options Start ---------" ' > debian/tmp/etc/profile.d/AGL_xds-service.sh
+ echo '# Object: AGL cmake option for binder/bindings' >> debian/tmp/etc/profile.d/AGL_xds-service.sh
+ echo 'export LD_LIBRARY_PATH=/opt/AGL/xds-service/lib/$(DEB_HOST_MULTIARCH):$$LD_LIBRARY_PATH' >> debian/tmp/etc/profile.d/AGL_xds-service.sh
+ echo 'export LIBRARY_PATH=/opt/AGL/xds-service/lib/$(DEB_HOST_MULTIARCH):$$LIBRARY_PATH' >> debian/tmp/etc/profile.d/AGL_xds-service.sh
+ echo 'export PATH=/opt/AGL/xds-service/bin:$$PATH' >> debian/tmp/etc/profile.d/AGL_xds-service.sh
+ echo '#---------- AGL options End ---------' >> debian/tmp/etc/profile.d/AGL_xds-service.sh
+ # Move all files in their corresponding package
+ dh_install --list-missing -s --sourcedir=debian/tmp
+ # empty dependency_libs in .la files
+ #sed -i "/dependency_libs/ s/'.*'/''/" `find debian/ -name '*.la'`
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs
+ dh_installdocs
+ dh_installexamples
+ dh_installman
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_makeshlibs -V
+ dh_installdeb
+ dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
diff --git a/conf.d/wgt/config.xml.in b/conf.d/wgt/config.xml.in
new file mode 100644
index 0000000..7824795
--- /dev/null
+++ b/conf.d/wgt/config.xml.in
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" id="@PROJECT_NAME@" version="@PROJECT_VERSION@">
+ <name>@PROJECT_NAME@</name>
+ <icon src="@PROJECT_ICON@"/>
+ <content src="@WIDGET_ENTRY_POINT@" type="@WIDGET_TYPE@"/>
+ <description>@PROJECT_DESCRIPTION@</description>
+ <author>@PROJECT_AUTHOR@ &lt;@PROJECT_AUTHOR_MAIL@&gt;</author>
+ <license>@PROJECT_LICENSE@</license>
+ <feature name="urn:AGL:widget:provided-api">
+ <param name="xds-service" value="ws" />
+ </feature>
+ <feature name="urn:AGL:widget:required-api">
+ <param name="lib/afb-xds-service.so" value="local" />
+ <param name="harvester" value="ws" />
+ <param name="supervisor" value="ws" />
+ </feature>
+</widget>
diff --git a/htdocs/AFB-websock.js b/htdocs/AFB-websock.js
new file mode 100644
index 0000000..3d4831f
--- /dev/null
+++ b/htdocs/AFB-websock.js
@@ -0,0 +1,177 @@
+var urlWS;
+var urlhttp;
+
+AFB = function(base, initialtoken){
+
+urlWS = "ws://"+window.location.host+"/"+base;
+urlhttp = "http://"+window.location.host+"/"+base;
+
+/*********************************************/
+/**** ****/
+/**** AFB_context ****/
+/**** ****/
+/*********************************************/
+var AFB_context;
+{
+ var UUID = undefined;
+ var TOKEN = initialtoken;
+
+ var context = function(token, uuid) {
+ this.token = token;
+ this.uuid = uuid;
+ }
+
+ context.prototype = {
+ get token() {return TOKEN;},
+ set token(tok) {if(tok) TOKEN=tok;},
+ get uuid() {return UUID;},
+ set uuid(id) {if(id) UUID=id;}
+ };
+
+ AFB_context = new context();
+}
+/*********************************************/
+/**** ****/
+/**** AFB_websocket ****/
+/**** ****/
+/*********************************************/
+var AFB_websocket;
+{
+ var CALL = 2;
+ var RETOK = 3;
+ var RETERR = 4;
+ var EVENT = 5;
+
+ var PROTO1 = "x-afb-ws-json1";
+
+ AFB_websocket = function(onopen, onabort) {
+ var u = urlWS;
+ if (AFB_context.token) {
+ u = u + '?x-afb-token=' + AFB_context.token;
+ if (AFB_context.uuid)
+ u = u + '&x-afb-uuid=' + AFB_context.uuid;
+ }
+ this.ws = new WebSocket(u, [ PROTO1 ]);
+ this.pendings = {};
+ this.awaitens = {};
+ this.counter = 0;
+ this.ws.onopen = onopen.bind(this);
+ this.ws.onerror = onerror.bind(this);
+ this.ws.onclose = onclose.bind(this);
+ this.ws.onmessage = onmessage.bind(this);
+ this.onopen = onopen;
+ this.onabort = onabort;
+ this.onclose = onabort;
+ }
+
+ function onerror(event) {
+ var f = this.onabort;
+ if (f) {
+ delete this.onopen;
+ delete this.onabort;
+ f && f(this);
+ }
+ this.onerror && this.onerror(this);
+ }
+
+ function onopen(event) {
+ var f = this.onopen;
+ delete this.onopen;
+ delete this.onabort;
+ f && f(this);
+ }
+
+ function onclose(event) {
+ for (var id in this.pendings) {
+ var ferr = this.pendings[id].onerror;
+ ferr && ferr(null, this);
+ }
+ this.pendings = {};
+ this.onclose && this.onclose();
+ }
+
+ function fire(awaitens, name, data) {
+ var a = awaitens[name];
+ if (a)
+ a.forEach(function(handler){handler(data);});
+ var i = name.indexOf("/");
+ if (i >= 0) {
+ a = awaitens[name.substring(0,i)];
+ if (a)
+ a.forEach(function(handler){handler(data);});
+ }
+ a = awaitens["*"];
+ if (a)
+ a.forEach(function(handler){handler(data);});
+ }
+
+ function reply(pendings, id, ans, offset) {
+ if (id in pendings) {
+ var p = pendings[id];
+ delete pendings[id];
+ var f = p[offset];
+ f(ans);
+ }
+ }
+
+ function onmessage(event) {
+ var obj = JSON.parse(event.data);
+ var code = obj[0];
+ var id = obj[1];
+ var ans = obj[2];
+ AFB_context.token = obj[3];
+ switch (code) {
+ case RETOK:
+ reply(this.pendings, id, ans, 0);
+ break;
+ case RETERR:
+ reply(this.pendings, id, ans, 1);
+ break;
+ case EVENT:
+ default:
+ fire(this.awaitens, id, ans);
+ break;
+ }
+ }
+
+ function close() {
+ this.ws.close();
+ this.onabort();
+ }
+
+ function call(method, request) {
+ return new Promise((function(resolve, reject){
+ var id, arr;
+ do {
+ id = String(this.counter = 4095 & (this.counter + 1));
+ } while (id in this.pendings);
+ this.pendings[id] = [ resolve, reject ];
+ arr = [CALL, id, method, request ];
+ if (AFB_context.token) arr.push(AFB_context.token);
+ this.ws.send(JSON.stringify(arr));
+ }).bind(this));
+ }
+
+ function onevent(name, handler) {
+ var id = name;
+ var list = this.awaitens[id] || (this.awaitens[id] = []);
+ list.push(handler);
+ }
+
+ AFB_websocket.prototype = {
+ close: close,
+ call: call,
+ onevent: onevent
+ };
+}
+/*********************************************/
+/**** ****/
+/**** ****/
+/**** ****/
+/*********************************************/
+return {
+ context: AFB_context,
+ ws: AFB_websocket
+};
+};
+
diff --git a/htdocs/CMakeLists.txt b/htdocs/CMakeLists.txt
new file mode 100644
index 0000000..7aa0ce1
--- /dev/null
+++ b/htdocs/CMakeLists.txt
@@ -0,0 +1,33 @@
+###########################################################################
+# Copyright 2015, 2016, 2017 IoT.bzh
+#
+# author: Fulup Ar Foll <fulup@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###########################################################################
+
+
+
+##################################################
+# HTML Testing Files
+##################################################
+PROJECT_TARGET_ADD(htdocs)
+
+ file(GLOB SOURCE_FILES "*.html" "*.js" "*.jpg" "*.css" "assets")
+
+ add_input_files("${SOURCE_FILES}")
+
+ SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
+ LABELS "HTDOCS"
+ OUTPUT_NAME ${TARGET_NAME}
+ )
diff --git a/htdocs/assets/background_iot_bzh_light.jpg b/htdocs/assets/background_iot_bzh_light.jpg
new file mode 100644
index 0000000..f47d2ee
--- /dev/null
+++ b/htdocs/assets/background_iot_bzh_light.jpg
Binary files differ
diff --git a/htdocs/assets/favicon.ico b/htdocs/assets/favicon.ico
new file mode 100644
index 0000000..eeb7ab7
--- /dev/null
+++ b/htdocs/assets/favicon.ico
Binary files differ
diff --git a/htdocs/assets/iot-bzh-logo-small.png b/htdocs/assets/iot-bzh-logo-small.png
new file mode 100644
index 0000000..2c3b2ae
--- /dev/null
+++ b/htdocs/assets/iot-bzh-logo-small.png
Binary files differ
diff --git a/htdocs/index.html b/htdocs/index.html
new file mode 100644
index 0000000..28d58ab
--- /dev/null
+++ b/htdocs/index.html
@@ -0,0 +1,48 @@
+<html>
+
+<head>
+ <title>XDS data collector binding Test</title>
+ <link rel="stylesheet" href="iotbzh-Binding.css">
+ <link rel="icon" type="image/x-icon" href="assets/favicon.ico">
+ <script type="text/javascript" src="AFB-websock.js"></script>
+ <script type="text/javascript" src="iotbzh-Binding.js"></script>
+</head>
+
+<body class="page-content" onload="init()">
+
+ <img src="assets/iot-bzh-logo-small.png">
+
+ <h1>XDS data collector prototype Test</h1>
+
+ <button id="connected" onclick="init()">Binder WS Fail</button>
+ <button id="monitoring" onclick="window.open('/monitoring/monitor.html','_monitor_ctl')">Debug/Monitoring</a>
+ </button>
+
+ <br>
+ <br>
+
+ <div>
+ <button onclick="callbinder('xds-service','list' ,{});">List</button>
+ </li>
+
+ <button onclick="callbinder('xds-service','trace' ,{'ws': 'unix:ave'});">Trace ws unix:ave</button>
+ </li>
+
+ </div>
+
+ <br>
+
+ <div id="main" style="visibility:hidden">
+ <ol>
+ <li>Question
+ <pre id="question"></pre>
+ </li>
+ <li>Response
+ <pre id="output"></pre>
+ </li>
+ <li>Events:
+ <pre id="outevt"></pre>
+ </li>
+ </ol>
+ </div>
+</body>
diff --git a/htdocs/iotbzh-Binding.css b/htdocs/iotbzh-Binding.css
new file mode 100644
index 0000000..96a04cc
--- /dev/null
+++ b/htdocs/iotbzh-Binding.css
@@ -0,0 +1,59 @@
+body.page-content {
+ height: 100%;
+ width: auto;
+ margin-top: 20px;
+ background: url("assets/background_iot_bzh_light.jpg") 0 0 no-repeat;
+ background-size: cover;
+ background-position: center;
+}
+
+img {
+ float: right;
+}
+
+#question,
+#output,
+#outevt {
+ white-space: pre-wrap;
+}
+
+button {
+ margin-right: 10px;
+ padding: 6px 8px;
+ font-size: large;
+}
+
+pre {
+ outline: 1px solid #ccc;
+ padding: 5px;
+ margin: 5px;
+ background-color: white;
+ opacity: 0.85;
+ min-height: 5pc;
+ max-height: 10pc;
+ overflow: auto;
+}
+
+pre#output {
+ max-height: 30pc;
+}
+
+.string {
+ color: green;
+}
+
+.number {
+ color: darkorange;
+}
+
+.boolean {
+ color: blue;
+}
+
+.null {
+ color: magenta;
+}
+
+.key {
+ color: red;
+}
diff --git a/htdocs/iotbzh-Binding.js b/htdocs/iotbzh-Binding.js
new file mode 100644
index 0000000..ae32f83
--- /dev/null
+++ b/htdocs/iotbzh-Binding.js
@@ -0,0 +1,149 @@
+var afb = new AFB("api", "mysecret");
+var ws;
+var evtIdx = 0;
+var count = 0;
+
+
+//**********************************************
+// Logger
+//**********************************************
+var log = {
+ command: function (api, verb, query) {
+ console.log("subscribe api=" + api + " verb=" + verb + " query=", query);
+ var question = urlWS + "/" + api + "/" + verb + "?query=" + JSON.stringify(query);
+ log._write("question", count + ": " + log.syntaxHighlight(question));
+ },
+
+ event: function (obj) {
+ console.log("gotevent:" + JSON.stringify(obj));
+ log._write("outevt", (evtIdx++) + ": " + JSON.stringify(obj));
+ },
+
+ reply: function (obj) {
+ console.log("replyok:" + JSON.stringify(obj));
+ log._write("output", count + ": OK: " + log.syntaxHighlight(obj));
+ },
+
+ error: function (obj) {
+ console.log("replyerr:" + JSON.stringify(obj));
+ log._write("output", count + ": ERROR: " + log.syntaxHighlight(obj));
+ },
+
+ _write: function (element, msg) {
+ var el = document.getElementById(element);
+ el.innerHTML += msg + '\n';
+
+ // auto scroll down
+ setTimeout(function () {
+ el.scrollTop = el.scrollHeight;
+ }, 100);
+ },
+
+ syntaxHighlight: function (json) {
+ if (typeof json !== 'string') {
+ json = JSON.stringify(json, undefined, 2);
+ }
+ json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+ return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
+ var cls = 'number';
+ if (/^"/.test(match)) {
+ if (/:$/.test(match)) {
+ cls = 'key';
+ } else {
+ cls = 'string';
+ }
+ } else if (/true|false/.test(match)) {
+ cls = 'boolean';
+ } else if (/null/.test(match)) {
+ cls = 'null';
+ }
+ return '<span class="' + cls + '">' + match + '</span>';
+ });
+ },
+};
+
+//**********************************************
+// Generic function to call binder
+//***********************************************
+function callbinder(api, verb, query) {
+ log.command(api, verb, query);
+
+ // ws.call return a Promise
+ return ws.call(api + '/' + verb, query)
+ .then(function (res) {
+ log.reply(res);
+ count++;
+ return res;
+ })
+ .catch(function (err) {
+ log.reply(err);
+ count++;
+ throw err;
+ });
+};
+
+//**********************************************
+//
+//**********************************************
+var topo = null;
+
+function getTopo() {
+ callbinder('supervisor', 'list', null)
+ .then(list => {
+ var reqs = [];
+ for (pid in list.response) {
+ this.pid = pid;
+ reqs.push(
+ callbinder('supervisor', 'config', {
+ "pid": pid
+ })
+ .then((res) => {
+ return {
+ 'pid': this.pid,
+ 'ws_servers': res.response.ws_servers,
+ 'ws_clients': res.response.ws_clients
+ }
+ })
+ );
+ };
+ return Promise.all(reqs);
+ })
+ .then(daemons => {
+ console.log("daemons count ", daemons.length);
+ daemons.forEach(dd => {
+ console.log(dd);
+ });
+ topo = daemons;
+ })
+ .catch(err => {
+ console.log()
+ });
+};
+
+
+
+
+
+//**********************************************
+// Init - establish Websocket connection
+//**********************************************
+function init(elemID, api, verb, query) {
+
+ function onopen() {
+ // Request initial authorization
+ callbinder('xds-service', 'auth', '');
+
+ document.getElementById("main").style.visibility = "visible";
+ document.getElementById("connected").innerHTML = "Binder WS Active";
+ document.getElementById("connected").style.background = "lightgreen";
+ ws.onevent("*", log.event);
+ }
+
+ function onabort() {
+ document.getElementById("main").style.visibility = "hidden";
+ document.getElementById("connected").innerHTML = "Connected Closed";
+ document.getElementById("connected").style.background = "red";
+ }
+
+ ws = new afb.ws(onopen, onabort);
+}
diff --git a/xds-service/CMakeLists.txt b/xds-service/CMakeLists.txt
new file mode 100644
index 0000000..9ce0b81
--- /dev/null
+++ b/xds-service/CMakeLists.txt
@@ -0,0 +1,42 @@
+###########################################################################
+# 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-service)
+
+ # Define project Targets
+ file(GLOB sourcelist "*.c")
+
+ # Define project Targets
+ ADD_LIBRARY(${TARGET_NAME} MODULE ${sourcelist})
+
+ 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}
+ )
+
+ TARGET_LINK_LIBRARIES(${TARGET_NAME}
+ afb-helpers
+ ${link_libraries}
+ )
diff --git a/xds-service/supervisor-service.c b/xds-service/supervisor-service.c
new file mode 100644
index 0000000..96955fa
--- /dev/null
+++ b/xds-service/supervisor-service.c
@@ -0,0 +1,179 @@
+/*
+ * 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 "supervisor-service.h"
+#include "xds-service-api.h"
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "curl-wrap.h"
+#include "wrap-json.h"
+
+#define SRV_SUPERVISOR_NAME "supervisor"
+
+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";
+
+static void decode_daemons_cb(void* closure, json_object* obj,
+ const char* resp)
+{
+ 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;
+ DAEMONS_T* daemons = (DAEMONS_T*)closure;
+ DAEMON_T* daemon = calloc(sizeof(DAEMON_T), 1);
+
+ if (!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_INFO("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_service_call_sync(SRV_SUPERVISOR_NAME, "config", j_query, &j_response);
+ if (rc < 0) {
+ AFB_ERROR("Cannot get config of pid %d", cred.pid);
+ return;
+ }
+
+ AFB_DEBUG("%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_ERROR("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);
+ 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_service_call_sync(SRV_SUPERVISOR_NAME, "do", j_query, &j_response);
+ if (rc < 0) {
+ AFB_ERROR("Cannot get apis of pid %d", cred.pid);
+ return;
+ } else {
+ //AFB_DEBUG("%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;
+ }
+ }
+ daemons->daemons[daemons->count] = daemon;
+ daemons->count++;
+}
+
+int getDaemons(DAEMONS_T** daemons)
+{
+ int rc;
+ json_object *j_response, *j_daemons = NULL;
+
+ *daemons = calloc(sizeof(DAEMONS_T), 1);
+
+ if ((rc = afb_service_call_sync(SRV_SUPERVISOR_NAME, "discover", NULL,
+ &j_response))
+ < 0) {
+ return rc;
+ }
+
+ if ((rc = afb_service_call_sync(SRV_SUPERVISOR_NAME, "list", NULL,
+ &j_response))
+ < 0) {
+ return rc;
+ }
+
+ AFB_DEBUG("%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)) {
+ wrap_json_object_for_all(j_daemons, &decode_daemons_cb, *daemons);
+ }
+
+ return 0;
+}
+
+int trace_exchange(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_service_call_sync(SRV_SUPERVISOR_NAME, "trace", j_query,
+ &j_response))
+ < 0) {
+ AFB_ERROR("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_service_call_sync(SRV_SUPERVISOR_NAME, "trace", j_query,
+ &j_response))
+ < 0) {
+ AFB_ERROR("ERROR trace %d result: %s", cli->pid,
+ json_object_to_json_string(j_response));
+ return rc;
+ }
+
+ return 0;
+}
+
+void supervisor_service_init(void) {}
diff --git a/xds-service/supervisor-service.h b/xds-service/supervisor-service.h
new file mode 100644
index 0000000..84fe36c
--- /dev/null
+++ b/xds-service/supervisor-service.h
@@ -0,0 +1,51 @@
+/*
+ * 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"
+
+// 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(DAEMONS_T **daemons);
+extern int trace_exchange(DAEMON_T *svr, DAEMON_T *cli);
+extern void supervisor_service_init(void);
diff --git a/xds-service/xds-service-api.c b/xds-service/xds-service-api.c
new file mode 100644
index 0000000..08e6a59
--- /dev/null
+++ b/xds-service/xds-service-api.c
@@ -0,0 +1,224 @@
+/*
+ * 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 "xds-service-api.h"
+#include "supervisor-service.h"
+#include "xds-service-apidef.h"
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#define SRV_SUPERVISOR_NAME "supervisor"
+#define SRV_HARVESTER_NAME "harvester"
+
+typedef struct metric_t {
+ char* name;
+ json_object* data;
+ struct timespec timestamp;
+} METRIC_T;
+
+void list(struct afb_req request)
+{
+ json_object *result, *item = NULL;
+ DAEMONS_T* daemons = NULL;
+
+ getDaemons(&daemons);
+ if (daemons == NULL) {
+ afb_req_fail(request, "failed", "");
+ return;
+ }
+
+ 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_req_success(request, result, NULL);
+}
+
+void trace(struct afb_req request)
+{
+ int rc;
+ json_object* req_args = afb_req_json(request);
+ json_object* result = NULL;
+ DAEMONS_T* daemons = NULL;
+ const char* ws_name;
+ const char* wsn;
+
+ if (wrap_json_unpack(req_args, "{s:?s}", "ws", &ws_name)) {
+ afb_req_fail(request, "Failed", "Error processing arguments.");
+ return;
+ }
+ AFB_INFO("Trace ws: %s", ws_name);
+
+ getDaemons(&daemons);
+ if (daemons == NULL || daemons->count <= 0) {
+ afb_req_fail(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_DEBUG("_DEBUG_ svr %s",
+ json_object_to_json_string(daemons->daemons[i]->ws_servers));
+ AFB_DEBUG("_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(pid_s, pid_c)) < 0) {
+ afb_req_fail_f(request, "failed", "Trace error %d", rc);
+ }
+ break;
+ }
+ }
+
+ if (pid_s == NULL || pid_c == NULL) {
+ afb_req_fail(request, "failed", "Cannot determine Server or Client");
+ return;
+ }
+
+ afb_req_success_f(request, result, "Tracing Server pid=%d <-> Client pid=%d",
+ pid_s->pid, pid_c->pid);
+}
+
+static int harvester_post_data(METRIC_T* metric)
+{
+
+ int rc;
+ json_object *j_res, *j_query;
+
+ if (!metric->timestamp.tv_sec && !metric->timestamp.tv_nsec) {
+ clock_gettime(CLOCK_MONOTONIC, &metric->timestamp);
+ }
+
+ rc = wrap_json_pack(&j_query, "{s:s s:i s:{ s:s s:o s:i } }", "host",
+ "localhost", "port", 8086, "metric", "name", metric->name,
+ "value", metric->data, "timestamp",
+ metric->timestamp.tv_sec);
+ if (rc < 0) {
+ AFB_ERROR("Error packing metric, rc=%d", rc);
+ return rc;
+ }
+
+ AFB_DEBUG("%s write: %s", SRV_HARVESTER_NAME,
+ json_object_to_json_string(j_query));
+
+ rc = afb_service_call_sync(SRV_HARVESTER_NAME, "write", j_query, &j_res);
+ if (rc < 0) {
+ AFB_ERROR("Error %s write : rc=%d, j_res=%s", SRV_HARVESTER_NAME, rc,
+ json_object_to_json_string(j_res));
+ return rc;
+ }
+ return 0;
+}
+
+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);
+ }
+ }
+}
+
+void auth(struct afb_req request)
+{
+ afb_req_session_set_LOA(request, 1);
+ afb_req_success(request, NULL, NULL);
+}
+
+int init()
+{
+
+#if 0 // DEBUG
+ DAEMONS_T *daemons = NULL;
+ getDaemons(&daemons);
+
+ if (daemons) {
+ if (daemons->count) {
+ AFB_DEBUG("_DEBUG_ daemons->count %d", daemons->count);
+ for (int i = 0; i < daemons->count; i++) {
+ AFB_DEBUG("pid %d : isServer %d, isClient %d, %s %s",
+ daemons->daemons[i]->pid, daemons->daemons[i]->isServer,
+ daemons->daemons[i]->isClient,
+ json_object_to_json_string(daemons->daemons[i]->ws_servers),
+ json_object_to_json_string(daemons->daemons[i]->ws_clients));
+ }
+ free(daemons);
+ } else {
+ AFB_DEBUG("_DEBUG_ no dameons detected !");
+ }
+ }
+#endif
+
+ supervisor_service_init();
+
+ return 0;
+}
diff --git a/xds-service/xds-service-api.h b/xds-service/xds-service-api.h
new file mode 100644
index 0000000..8a95f77
--- /dev/null
+++ b/xds-service/xds-service-api.h
@@ -0,0 +1,24 @@
+/*
+ * 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
+
+#define AFB_BINDING_VERSION 2
+#include <afb/afb-binding.h>
+#include "wrap-json.h"
+
+extern void xds_event_cb(const char *evtname, json_object *j_event);
+extern int init();
diff --git a/xds-service/xds-service-apidef.h b/xds-service/xds-service-apidef.h
new file mode 100644
index 0000000..5d53d89
--- /dev/null
+++ b/xds-service/xds-service-apidef.h
@@ -0,0 +1,85 @@
+
+static const char _afb_description_v2_xds_service[] =
+ "{\"openapi\":\"3.0.0\",\"$schema\":\"http://iot.bzh/download/openapi/sch"
+ "ema-3.0/default-schema.json\",\"info\":{\"description\":\"TBD - TODO\",\""
+ "title\":\"xds-service\",\"version\":\"4.0\",\"x-binding-c-generator\":{\""
+ "api\":\"xds-service\",\"version\":2,\"prefix\":\"\",\"postfix\":\"\",\"s"
+ "tart\":null,\"onevent\":\"xds_event_cb\",\"init\":\"init\",\"scope\":\"\""
+ ",\"private\":false}},\"servers\":[{}],\"components\":{\"schemas\":{\"afb"
+ "-reply\":{\"$ref\":\"#/components/schemas/afb-reply-v2\"},\"afb-event\":"
+ "{\"$ref\":\"#/components/schemas/afb-event-v2\"},\"afb-reply-v2\":{\"tit"
+ "le\":\"Generic response.\",\"type\":\"object\",\"required\":[\"jtype\",\""
+ "request\"],\"properties\":{\"jtype\":{\"type\":\"string\",\"const\":\"af"
+ "b-reply\"},\"request\":{\"type\":\"object\",\"required\":[\"status\"],\""
+ "properties\":{\"status\":{\"type\":\"string\"},\"info\":{\"type\":\"stri"
+ "ng\"},\"token\":{\"type\":\"string\"},\"uuid\":{\"type\":\"string\"},\"r"
+ "eqid\":{\"type\":\"string\"}}},\"response\":{\"type\":\"object\"}}},\"af"
+ "b-event-v2\":{\"type\":\"object\",\"required\":[\"jtype\",\"event\"],\"p"
+ "roperties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-event\"},\"e"
+ "vent\":{\"type\":\"string\"},\"data\":{\"type\":\"object\"}}}},\"x-permi"
+ "ssions\":{\"list\":{\"permission\":\"urn:AGL:permission::platform:can:li"
+ "st \"},\"trace\":{\"permission\":\"urn:AGL:permission::platform:can:trac"
+ "e \"}},\"responses\":{\"200\":{\"description\":\"A complex object array "
+ "response\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/c"
+ "omponents/schemas/afb-reply\"}}}}}},\"paths\":{\"/auth\":{\"description\""
+ ":\"Authenticate session to raise Level Of Assurance of the session\",\"g"
+ "et\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/list\"},\""
+ "responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/lis"
+ "t\":{\"description\":\"list \",\"get\":{\"x-permissions\":{\"LOA\":1},\""
+ "parameters\":[],\"responses\":{\"200\":{\"$ref\":\"#/components/response"
+ "s/200\"}}}},\"/trace\":{\"description\":\"trace \",\"get\":{\"x-permissi"
+ "ons\":{\"LOA\":1},\"parameters\":[{\"in\":\"query\",\"name\":\"ws\",\"re"
+ "quired\":true,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":"
+ "{\"$ref\":\"#/components/responses/200\"}}}}}}"
+;
+
+static const struct afb_auth _afb_auths_v2_xds_service[] = {
+ { .type = afb_auth_Permission, .text = "urn:AGL:permission::platform:can:list " }
+};
+
+ void auth(struct afb_req req);
+ void list(struct afb_req req);
+ void trace(struct afb_req req);
+
+static const struct afb_verb_v2 _afb_verbs_v2_xds_service[] = {
+ {
+ .verb = "auth",
+ .callback = auth,
+ .auth = &_afb_auths_v2_xds_service[0],
+ .info = "Authenticate session to raise Level Of Assurance of the session",
+ .session = AFB_SESSION_NONE_V2
+ },
+ {
+ .verb = "list",
+ .callback = list,
+ .auth = NULL,
+ .info = "list ",
+ .session = AFB_SESSION_LOA_1_V2
+ },
+ {
+ .verb = "trace",
+ .callback = trace,
+ .auth = NULL,
+ .info = "trace ",
+ .session = AFB_SESSION_LOA_1_V2
+ },
+ {
+ .verb = NULL,
+ .callback = NULL,
+ .auth = NULL,
+ .info = NULL,
+ .session = 0
+ }
+};
+
+const struct afb_binding_v2 afbBindingV2 = {
+ .api = "xds-service",
+ .specification = _afb_description_v2_xds_service,
+ .info = "TBD - TODO",
+ .verbs = _afb_verbs_v2_xds_service,
+ .preinit = NULL,
+ .init = init,
+ .onevent = xds_event_cb,
+ .noconcurrency = 0
+};
+
diff --git a/xds-service/xds-service-apidef.json b/xds-service/xds-service-apidef.json
new file mode 100644
index 0000000..76e35b7
--- /dev/null
+++ b/xds-service/xds-service-apidef.json
@@ -0,0 +1,152 @@
+{
+ "openapi": "3.0.0",
+ "$schema": "http://iot.bzh/download/openapi/schema-3.0/default-schema.json",
+ "info": {
+ "description": "TBD - TODO",
+ "title": "xds-service",
+ "version": "4.0",
+ "x-binding-c-generator": {
+ "api": "xds-service",
+ "version": 2,
+ "prefix": "",
+ "postfix": "",
+ "start": null,
+ "onevent": "xds_event_cb",
+ "init": "init",
+ "scope": "",
+ "private": false
+ }
+ },
+ "servers": [{}],
+ "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"
+ }
+ }
+ }
+ }
+ }
+}