summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan-Simon Möller <jsmoeller@linuxfoundation.org>2017-11-17 06:07:15 +0100
committerJan-Simon Möller <jsmoeller@linuxfoundation.org>2017-11-17 06:16:27 +0100
commit653278b62e5bbea89467787d110d6abb6fccdba2 (patch)
tree18927f3fb39581101e2b6f2da41fd241dcc99807
parent0d53841e3381c60cd6901aaae14bad181ae5fa4d (diff)
Initial upload of genskel as host toolHEADmaster
This change exports the genskel tool from the af-binder repo into its own source tree. The tools is a generator that needs to execute on the compile host. Bug-AGL: SPEC-941 Signed-off-by: Jan-Simon Möller <jsmoeller@linuxfoundation.org>
-rw-r--r--.gitignore11
-rw-r--r--.gitreview5
-rw-r--r--CMakeLists.txt69
-rw-r--r--LICENSE-2.0.txt202
-rw-r--r--genskel/CMakeLists.txt31
-rw-r--r--genskel/exprefs.c198
-rw-r--r--genskel/genskel.c708
-rw-r--r--genskel/json2c.c174
-rw-r--r--genskel/monitor-api.json400
9 files changed, 1798 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5e902eb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+autom4te.cache
+config.log
+build/*
+!.gitignore
+.dep.inc
+CMakeFiles/
+CMakeCache.txt
+Makefile
+cmake_install.cmake
+*.so
+.vscode
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..fb96bf2
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,5 @@
+[gerrit]
+host=gerrit.automotivelinux.org
+port=29418
+project=src/app-framework-host-utilities
+defaultbranch=master \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..8264fcb
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,69 @@
+###########################################################################
+# Copyright 2017 Jan-Simon Möller dl9pf@gmx.de
+#
+# author: Jan-Simon Möller <dl9pf@gmx.de>
+#
+# 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.
+###########################################################################
+
+CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
+
+PROJECT(af-host-utils C CXX)
+
+SET(PROJECT_NAME "APPFW HOST UTILITIES")
+SET(PROJECT_PRETTY_NAME "Application Framework Host Utilities")
+SET(PROJECT_DESCRIPTION "Host Tools for the Application framework")
+SET(PROJECT_VERSION "4.99-EERC2")
+set(PROJECT_URL "https://gerrit.automotivelinux.org/gerrit/gitweb?p=src/app-framework-host-utilities.git;a=summary")
+
+INCLUDE(FindPkgConfig)
+INCLUDE(CheckIncludeFiles)
+INCLUDE(CheckLibraryExists)
+INCLUDE(GNUInstallDirs)
+INCLUDE(CTest)
+
+###########################################################################
+
+link_libraries(-Wl,--as-needed -Wl,--gc-sections -Wl,--no-undefined)
+
+add_compile_options(-Wall -Wextra -Wconversion)
+add_compile_options(-Wno-unused-parameter) # frankly not using a parameter does it care?
+add_compile_options(-Wno-sign-compare -Wno-sign-conversion)
+add_compile_options(-Werror=maybe-uninitialized)
+add_compile_options(-Werror=implicit-function-declaration)
+add_compile_options(-ffunction-sections -fdata-sections)
+add_compile_options(-fPIC)
+add_compile_options(-g)
+
+set(CMAKE_C_FLAGS_PROFILING "-g -O2 -pg -Wp,-U_FORTIFY_SOURCE")
+set(CMAKE_C_FLAGS_DEBUG "-g -ggdb -Wp,-U_FORTIFY_SOURCE")
+set(CMAKE_C_FLAGS_RELEASE "-g -O2")
+set(CMAKE_C_FLAGS_CCOV "-g -O2 --coverage")
+
+###########################################################################
+
+INCLUDE(FindThreads)
+FIND_PACKAGE(Threads)
+
+PKG_CHECK_MODULES(json-c REQUIRED json-c)
+
+INCLUDE_DIRECTORIES(
+${INCLUDE_DIRS}
+${json-c_INCLUDE_DIRS}
+)
+
+SET(link_libraries
+${json-c_LDFLAGS}
+)
+
+ADD_SUBDIRECTORY(genskel)
diff --git a/LICENSE-2.0.txt b/LICENSE-2.0.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE-2.0.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/genskel/CMakeLists.txt b/genskel/CMakeLists.txt
new file mode 100644
index 0000000..6263c85
--- /dev/null
+++ b/genskel/CMakeLists.txt
@@ -0,0 +1,31 @@
+###########################################################################
+# Copyright 2015, 2016, 2017 IoT.bzh
+#
+# author: José Bollo <jose.bollo@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.
+###########################################################################
+cmake_minimum_required(VERSION 3.5)
+
+ADD_EXECUTABLE(afb-genskel genskel.c)
+ADD_EXECUTABLE(afb-exprefs exprefs.c)
+ADD_EXECUTABLE(afb-json2c json2c.c)
+
+TARGET_LINK_LIBRARIES(afb-genskel ${link_libraries})
+TARGET_LINK_LIBRARIES(afb-exprefs ${link_libraries})
+TARGET_LINK_LIBRARIES(afb-json2c ${link_libraries})
+
+INSTALL(TARGETS afb-genskel RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+INSTALL(TARGETS afb-exprefs RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+INSTALL(TARGETS afb-json2c RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
diff --git a/genskel/exprefs.c b/genskel/exprefs.c
new file mode 100644
index 0000000..4ea44b4
--- /dev/null
+++ b/genskel/exprefs.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2016, 2017 "IoT.bzh"
+ * Author José Bollo <jose.bollo@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.
+ */
+/*
+ * This simple program expands the object { "$ref": "#/path/to/a/target" }
+ *
+ * For example:
+ *
+ * {
+ * "type":{
+ * "a": "int",
+ * "b": { "$ref": "#/type/a" }
+ * }
+ * }
+ *
+ * will be exapanded to
+ *
+ * {
+ * "type":{
+ * "a": "int",
+ * "b": "int"
+ * }
+ * }
+ *
+ * Invocation: program [file|-]...
+ *
+ * without arguments, it reads the input.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <json-c/json.h>
+
+/**
+ * records path to the expanded node
+ */
+struct path
+{
+ struct json_object *object; /**< node being expanded */
+ struct path *upper; /**< link to upper expanded nodes */
+};
+
+/**
+ * root of the JSON being parsed
+ */
+struct json_object *root;
+
+/**
+ * Search for a reference of type "#/a/b/c" int the
+ * parsed JSON object
+ */
+struct json_object *search(const char *path)
+{
+ char *d;
+ struct json_object *i;
+
+ /* does it match #/ at the beginning? */
+ if (path[0] != '#' || (path[0] && path[1] != '/'))
+ return NULL;
+
+ /* search from root to target */
+ i = root;
+ d = strdupa(path+2);
+ d = strtok(d, "/");
+ while(i && d) {
+ if (!json_object_object_get_ex(i, d, &i))
+ return NULL;
+ d = strtok(NULL, "/");
+ }
+ return i;
+}
+
+/**
+ * Expands the node designated by path and returns its expanded form
+ */
+struct json_object *expand(struct path path)
+{
+ struct path *p;
+ struct json_object *o, *x;
+ int n, i;
+ struct json_object_iterator ji, jn;
+
+ /* expansion depends of the type of the node */
+ switch (json_object_get_type(path.object)) {
+ case json_type_object:
+ /* for object, look if it contains a property "$ref" */
+ if (json_object_object_get_ex(path.object, "$ref", &o)) {
+ /* yes, reference, try to substitute its target */
+ if (!json_object_is_type(o, json_type_string)) {
+ fprintf(stderr, "found a $ref not being string. Is: %s\n", json_object_get_string(o));
+ exit(1);
+ }
+ x = search(json_object_get_string(o));
+ if (!x) {
+ fprintf(stderr, "$ref not found. Was: %s\n", json_object_get_string(o));
+ exit(1);
+ }
+ p = &path;
+ while(p) {
+ if (x == p->object) {
+ fprintf(stderr, "$ref recursive. Was: %s\n", json_object_get_string(o));
+ exit(1);
+ }
+ p = p->upper;
+ }
+ /* cool found, return a new instance of the target */
+ return json_object_get(x);
+ }
+ /* no, expand the values */
+ ji = json_object_iter_begin(path.object);
+ jn = json_object_iter_end(path.object);
+ while (!json_object_iter_equal(&ji, &jn)) {
+ o = json_object_iter_peek_value(&ji);
+ x = expand((struct path){ .object = o, .upper = &path });
+ if (x != o)
+ json_object_object_add(path.object, json_object_iter_peek_name(&ji), x);
+ json_object_iter_next(&ji);
+ }
+ break;
+ case json_type_array:
+ /* expand the values of arrays */
+ i = 0;
+ n = json_object_array_length(path.object);
+ while (i != n) {
+ o = json_object_array_get_idx(path.object, i);
+ x = expand((struct path){ .object = o, .upper = &path });
+ if (x != o)
+ json_object_array_put_idx(path.object, i, x);
+ i++;
+ }
+ break;
+ default:
+ /* otherwise no expansion */
+ break;
+ }
+ /* return the given node */
+ return path.object;
+}
+
+/**
+ * process a file and prints its expansion on stdout
+ */
+void process(char *filename)
+{
+ /* translate - */
+ if (!strcmp(filename, "-"))
+ filename = "/dev/stdin";
+
+ /* check access */
+ if (access(filename, R_OK)) {
+ fprintf(stderr, "can't access file %s\n", filename);
+ exit(1);
+ }
+
+ /* read the file */
+ root = json_object_from_file(filename);
+ if (!root) {
+ fprintf(stderr, "reading file %s produced null\n", filename);
+ exit(1);
+ }
+
+ /* expand */
+ root = expand((struct path){ .object = root, .upper = NULL });
+
+ /* print the result */
+ json_object_to_file_ext ("/dev/stdout", root, JSON_C_TO_STRING_PRETTY);
+
+ /* clean up */
+ json_object_put(root);
+}
+
+/** process the list of files or stdin if none */
+int main(int ac, char **av)
+{
+ if (!*++av)
+ process("-");
+ else {
+ do { process(*av); } while(*++av);
+ }
+ return 0;
+}
+
diff --git a/genskel/genskel.c b/genskel/genskel.c
new file mode 100644
index 0000000..62dfe3f
--- /dev/null
+++ b/genskel/genskel.c
@@ -0,0 +1,708 @@
+/*
+ * Copyright (C) 2016, 2017 "IoT.bzh"
+ * Author José Bollo <jose.bollo@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.
+ */
+/*
+ * This simple program expands the object { "$ref": "#/path/to/a/target" }
+ *
+ * For example:
+ *
+ * {
+ * "type":{
+ * "a": "int",
+ * "b": { "$ref": "#/type/a" }
+ * }
+ * }
+ *
+ * will be exapanded to
+ *
+ * {
+ * "type":{
+ * "a": "int",
+ * "b": "int"
+ * }
+ * }
+ *
+ * Invocation: program [file|-]...
+ *
+ * without arguments, it reads the input.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <json-c/json.h>
+
+#define oom(x) do{if(!(x)){fprintf(stderr,"out of memory\n");exit(1);}}while(0)
+
+/**
+ * records path to the expanded node
+ */
+struct path
+{
+ struct json_object *object; /**< node being expanded */
+ struct path *upper; /**< link to upper expanded nodes */
+};
+
+/**
+ * root of the JSON being parsed
+ */
+struct json_object *root = NULL;
+struct json_object *d_perms = NULL;
+struct json_object *a_perms = NULL;
+const char *preinit = NULL;
+const char *init = NULL;
+const char *onevent = NULL;
+const char *api = NULL;
+const char *scope = NULL;
+const char *prefix = NULL;
+const char *postfix = NULL;
+char *capi = NULL;
+int priv = -1;
+int noconc = -1;
+
+/**
+ * Search for a reference of type "#/a/b/c" int the
+ * parsed JSON object
+ */
+struct json_object *search(const char *path)
+{
+ char *d;
+ struct json_object *i;
+
+ /* does it match #/ at the beginning? */
+ if (path[0] != '#' || (path[0] && path[1] != '/'))
+ return NULL;
+
+ /* search from root to target */
+ i = root;
+ d = strdupa(path+2);
+ d = strtok(d, "/");
+ while(i && d) {
+ if (!json_object_object_get_ex(i, d, &i))
+ return NULL;
+ d = strtok(NULL, "/");
+ }
+ return i;
+}
+
+/**
+ * Expands the node designated by path and returns its expanded form
+ */
+struct json_object *expand_$ref(struct path path)
+{
+ struct path *p;
+ struct json_object *o, *x;
+ int n, i;
+ struct json_object_iterator ji, jn;
+
+ /* expansion depends of the type of the node */
+ switch (json_object_get_type(path.object)) {
+ case json_type_object:
+ /* for object, look if it contains a property "$ref" */
+ if (json_object_object_get_ex(path.object, "$ref", &o)) {
+ /* yes, reference, try to substitute its target */
+ if (!json_object_is_type(o, json_type_string)) {
+ fprintf(stderr, "found a $ref not being string. Is: %s\n", json_object_get_string(o));
+ exit(1);
+ }
+ x = search(json_object_get_string(o));
+ if (!x) {
+ fprintf(stderr, "$ref not found. Was: %s\n", json_object_get_string(o));
+ exit(1);
+ }
+ p = &path;
+ while(p) {
+ if (x == p->object) {
+ fprintf(stderr, "$ref recursive. Was: %s\n", json_object_get_string(o));
+ exit(1);
+ }
+ p = p->upper;
+ }
+ /* cool found, return a new instance of the target */
+ return json_object_get(x);
+ }
+ /* no, expand the values */
+ ji = json_object_iter_begin(path.object);
+ jn = json_object_iter_end(path.object);
+ while (!json_object_iter_equal(&ji, &jn)) {
+ o = json_object_iter_peek_value(&ji);
+ x = expand_$ref((struct path){ .object = o, .upper = &path });
+ if (x != o)
+ json_object_object_add(path.object, json_object_iter_peek_name(&ji), x);
+ json_object_iter_next(&ji);
+ }
+ break;
+ case json_type_array:
+ /* expand the values of arrays */
+ i = 0;
+ n = json_object_array_length(path.object);
+ while (i != n) {
+ o = json_object_array_get_idx(path.object, i);
+ x = expand_$ref((struct path){ .object = o, .upper = &path });
+ if (x != o)
+ json_object_array_put_idx(path.object, i, x);
+ i++;
+ }
+ break;
+ default:
+ /* otherwise no expansion */
+ break;
+ }
+
+ /* return the given node */
+ return path.object;
+}
+
+char *cify(const char *str)
+{
+ char *r = strdup(str);
+ int i = 0;
+ while (r && r[i]) {
+ if (!isalnum(r[i]))
+ r[i] = '_';
+ i++;
+ }
+ return r;
+}
+
+char *make_info(const char *text, int split)
+{
+ const char *a, *b;
+ char *desc, c, buf[3];
+ size_t len;
+ int i, pos, e;
+
+ /* estimated length */
+ a = b = text;
+ len = 1;
+ while((c = *b++)) {
+ len += 1 + ('"' == c);
+ }
+
+ len += 7 * (1 + len / 72);
+ desc = malloc(len);
+ oom(desc);
+
+ len = pos = 0;
+ if (!split)
+ desc[len++] = '"';
+ b = a;
+ while((c = *b++)) {
+ if (c == '"') {
+ buf[0] = '\\';
+ buf[1] = '"';
+ buf[2] = 0;
+ }
+ else if (c == '\\') {
+ switch ((c = *b++)) {
+ case 0:
+ b--;
+ break;
+ case '/':
+ buf[0] = '/';
+ buf[1] = 0;
+ break;
+ default:
+ buf[0] = '\\';
+ buf[1] = c;
+ buf[2] = 0;
+ break;
+ }
+ }
+ else {
+ buf[0] = c;
+ buf[1] = 0;
+ }
+ i = e = 0;
+ while (buf[i]) {
+ if (split) {
+ if (pos >= 77 && !e) {
+ desc[len++] = '"';
+ desc[len++] = '\n';
+ pos = 0;
+ }
+ if (pos == 0) {
+ desc[len++] = ' ';
+ desc[len++] = ' ';
+ desc[len++] = ' ';
+ desc[len++] = ' ';
+ desc[len++] = '"';
+ pos = 5;
+ }
+ }
+ c = buf[i++];
+ desc[len++] = c;
+ e = !e && c == '\\';
+ pos++;
+ }
+ }
+ desc[len++] = '"';
+ if (split)
+ desc[len++] = '\n';
+ desc[len] = 0;
+ return desc;
+}
+
+char *make_desc(struct json_object *o)
+{
+ return make_info(json_object_to_json_string_ext(root, 0), 1);
+}
+
+struct json_object *permissions_of_verb(struct json_object *obj)
+{
+ struct json_object *x, *y;
+
+ if (json_object_object_get_ex(obj, "x-permissions", &x))
+ return x;
+
+ if (json_object_object_get_ex(obj, "get", &x))
+ if (json_object_object_get_ex(x, "x-permissions", &y))
+ return y;
+
+ return NULL;
+}
+
+void print_perms()
+{
+ int i, n;
+
+ n = a_perms ? json_object_array_length(a_perms) : 0;
+ if (n) {
+ printf("static const struct afb_auth _afb_auths_v2_%s[] = {\n" , capi);
+ i = 0;
+ while (i < n) {
+ printf("\t{ %s }", json_object_get_string(json_object_array_get_idx(a_perms, i)));
+ printf(",\n"+(++i == n));
+ }
+ printf("};\n\n");
+ }
+}
+
+struct json_object *new_perm(struct json_object *obj, const char *desc)
+{
+ const char *tag;
+ char *b;
+ struct json_object *x, *y;
+
+ tag = obj ? json_object_to_json_string_ext(obj, 0) : desc;
+ if (!json_object_object_get_ex(d_perms, tag, &y)) {
+ if (!d_perms) {
+ d_perms = json_object_new_object();
+ a_perms = json_object_new_array();
+ }
+
+ asprintf(&b, "&_afb_auths_v2_%s[%d]", capi, json_object_array_length(a_perms));
+ x = json_object_new_string(desc);
+ y = json_object_new_string(b);
+ json_object_array_add(a_perms, x);
+ json_object_object_add(d_perms, tag, y);
+ free(b);
+ }
+ return y;
+}
+
+struct json_object *decl_perm(struct json_object *obj);
+
+struct json_object *decl_perm_a(const char *op, struct json_object *obj)
+{
+ int i, n;
+ char *a;
+ struct json_object *x, *y;
+
+ x = NULL;
+ i = n = obj ? json_object_array_length(obj) : 0;
+ while (i) {
+ y = decl_perm(json_object_array_get_idx(obj, --i));
+ if (!y)
+ ;
+ else if (!x)
+ x = y;
+ else if (x != y) {
+ asprintf(&a, ".type = afb_auth_%s, .first = %s, .next = %s",
+ op, json_object_get_string(y), json_object_get_string(x));
+ x = new_perm(NULL, a);
+ free(a);
+ }
+ }
+ return x;
+}
+
+struct json_object *decl_perm(struct json_object *obj)
+{
+ char *a;
+ struct json_object *x, *y;
+
+ if (json_object_object_get_ex(d_perms, json_object_to_json_string_ext(obj, 0), &x))
+ return x;
+
+ if (json_object_object_get_ex(obj, "permission", &x)) {
+ asprintf(&a, ".type = afb_auth_Permission, .text = \"%s\"", json_object_get_string(x));
+ y = new_perm(obj, a);
+ free(a);
+ }
+ else if (json_object_object_get_ex(obj, "anyOf", &x)) {
+ y = decl_perm_a("Or", x);
+ }
+ else if (json_object_object_get_ex(obj, "allOf", &x)) {
+ y = decl_perm_a("And", x);
+ }
+ else if (json_object_object_get_ex(obj, "not", &x)) {
+ x = decl_perm(x);
+ asprintf(&a, ".type = afb_auth_Not, .first = %s", json_object_get_string(x));
+ y = new_perm(obj, a);
+ free(a);
+ }
+ else if (json_object_object_get_ex(obj, "LOA", &x))
+ y = NULL;
+ else if (json_object_object_get_ex(obj, "session", &x))
+ y = NULL;
+ else
+ y = NULL;
+
+ return y;
+}
+
+void declare_permissions(const char *name, struct json_object *obj)
+{
+ struct json_object *p;
+
+ p = permissions_of_verb(obj);
+ if (p)
+ decl_perm(p);
+}
+
+
+#define SESSION_CLOSE 0x000001
+#define SESSION_RENEW 0x000010
+#define SESSION_CHECK 0x000100
+#define SESSION_LOA_1 0x001000
+#define SESSION_LOA_2 0x011000
+#define SESSION_LOA_3 0x111000
+#define SESSION_MASK 0x111111
+
+
+int get_session(struct json_object *obj);
+
+int get_session_a(int and, struct json_object *obj)
+{
+ int i, n, x, y;
+
+ n = obj ? json_object_array_length(obj) : 0;
+ if (n == 0)
+ return 0;
+
+ i = n;
+ x = get_session(json_object_array_get_idx(obj, --i));
+ while (i) {
+ y = get_session(json_object_array_get_idx(obj, --i));
+ if (and)
+ x &= y;
+ else
+ x |= y;
+ }
+ return x;
+}
+
+int get_session(struct json_object *obj)
+{
+ int y;
+ const char *a;
+ struct json_object *x;
+
+ y = 0;
+ if (json_object_object_get_ex(obj, "anyOf", &x)) {
+ y = get_session_a(1, x);
+ }
+ else if (json_object_object_get_ex(obj, "allOf", &x)) {
+ y = get_session_a(0, x);
+ }
+ else if (json_object_object_get_ex(obj, "not", &x)) {
+ y = ~get_session(x) & SESSION_MASK;
+ }
+ else if (json_object_object_get_ex(obj, "LOA", &x)) {
+ switch (json_object_get_int(x)) {
+ case 3: y = SESSION_LOA_3; break;
+ case 2: y = SESSION_LOA_2; break;
+ case 1: y = SESSION_LOA_1; break;
+ default: break;
+ }
+ }
+ else if (json_object_object_get_ex(obj, "session", &x)) {
+ a = json_object_get_string(x);
+ if (!strcmp(a, "check"))
+ y = SESSION_CHECK;
+ else if (!strcmp(a, "close"))
+ y = SESSION_CLOSE;
+ }
+ else if (json_object_object_get_ex(obj, "token", &x)) {
+ a = json_object_get_string(x);
+ if (!strcmp(a, "refresh"))
+ y = SESSION_RENEW;
+ }
+
+ return y;
+}
+
+void print_session(struct json_object *p)
+{
+ int s, c, l;
+
+ s = p ? get_session(p) : 0;
+ c = 1;
+ if (s & SESSION_CHECK) {
+ printf("%s", "|AFB_SESSION_CHECK_V2" + c);
+ c = 0;
+ }
+ if (s & SESSION_LOA_3 & ~SESSION_LOA_2)
+ l = 3;
+ else if (s & SESSION_LOA_2 & ~SESSION_LOA_1)
+ l = 2;
+ else if (s & SESSION_LOA_1)
+ l = 1;
+ else
+ l = 0;
+ if (l) {
+ printf("%s%d_V2", "|AFB_SESSION_LOA_" + c, l);
+ c = 0;
+ }
+ if (s & SESSION_CLOSE) {
+ printf("%s", "|AFB_SESSION_CLOSE_V2" + c);
+ c = 0;
+ }
+ if (s & SESSION_RENEW) {
+ printf("%s", "|AFB_SESSION_REFRESH_V2" + c);
+ c = 0;
+ }
+ if (c)
+ printf("AFB_SESSION_NONE_V2");
+}
+
+void print_verb(const char *name)
+{
+ printf("%s%s%s" , prefix, name, postfix);
+}
+
+void print_declare_verb(const char *name, struct json_object *obj)
+{
+ printf("%s void ", scope);
+ print_verb(name);
+ printf("(struct afb_req req);\n");
+}
+
+void print_struct_verb(const char *name, struct json_object *obj)
+{
+ struct json_object *p, *i;
+ const char *info;
+
+ info = NULL;
+ if (json_object_object_get_ex(obj, "description", &i))
+ info = json_object_get_string(i);
+
+ p = permissions_of_verb(obj);
+ printf(
+ " {\n"
+ " .verb = \"%s\",\n"
+ " .callback = "
+ , name
+ );
+ print_verb(name);
+ printf(
+ ",\n"
+ " .auth = %s,\n"
+ " .info = %s,\n"
+ " .session = "
+ , p && decl_perm(p) ? json_object_get_string(decl_perm(p)) : "NULL"
+ , info ? make_info(info, 0) : "NULL"
+ );
+ print_session(p);
+ printf(
+ "\n"
+ " },\n"
+ );
+}
+
+void enum_verbs(void (*func)(const char *name, struct json_object *obj))
+{
+ struct json_object_iterator ji, jn;
+ struct json_object *paths, *obj;
+ const char *name;
+
+ /* search the verbs */
+ paths = search("#/paths");
+ if (!paths)
+ return;
+
+ /* list the verbs and sort it */
+ ji = json_object_iter_begin(paths);
+ jn = json_object_iter_end(paths);
+ while (!json_object_iter_equal(&ji, &jn)) {
+ name = json_object_iter_peek_name(&ji);
+ obj = json_object_iter_peek_value(&ji);
+ name += (*name == '/');
+ func(name, obj);
+ json_object_iter_next(&ji);
+ }
+}
+
+void getvarbool(int *var, const char *path, int defval)
+{
+ struct json_object *o;
+
+ if (*var != 0 && *var != 1) {
+ o = search(path);
+ if (o && json_object_is_type(o, json_type_boolean))
+ *var = json_object_get_boolean(o);
+ else
+ *var = !!defval;
+ }
+}
+
+void getvar(const char **var, const char *path, const char *defval)
+{
+ struct json_object *o;
+
+ if (!*var) {
+ o = search(path);
+ if (o && json_object_is_type(o, json_type_string))
+ *var = json_object_get_string(o);
+ else
+ *var = defval;
+ }
+}
+
+/**
+ * process a file and prints its expansion on stdout
+ */
+void process(char *filename)
+{
+ char *desc;
+ const char *info;
+
+ /* translate - */
+ if (!strcmp(filename, "-"))
+ filename = "/dev/stdin";
+
+ /* check access */
+ if (access(filename, R_OK)) {
+ fprintf(stderr, "can't access file %s\n", filename);
+ exit(1);
+ }
+
+ /* read the file */
+ root = json_object_from_file(filename);
+ if (!root) {
+ fprintf(stderr, "reading file %s produced null\n", filename);
+ exit(1);
+ }
+
+ /* create the description */
+ desc = make_desc(root);
+
+ /* expand references */
+ root = expand_$ref((struct path){ .object = root, .upper = NULL });
+
+ /* get some names */
+ getvar(&api, "#/info/x-binding-c-generator/api", NULL);
+ getvar(&preinit, "#/info/x-binding-c-generator/preinit", NULL);
+ getvar(&init, "#/info/x-binding-c-generator/init", NULL);
+ getvar(&onevent, "#/info/x-binding-c-generator/onevent", NULL);
+ getvar(&scope, "#/info/x-binding-c-generator/scope", "static");
+ getvar(&prefix, "#/info/x-binding-c-generator/prefix", "afb_verb_");
+ getvar(&postfix, "#/info/x-binding-c-generator/postfix", "_cb");
+ getvarbool(&priv, "#/info/x-binding-c-generator/private", 0);
+ getvarbool(&noconc, "#/info/x-binding-c-generator/noconcurrency", 0);
+ getvar(&api, "#/info/title", "?");
+ info = NULL;
+ getvar(&info, "#/info/description", NULL);
+ capi = cify(api);
+
+ /* get the API name */
+ printf(
+ "\n"
+ "static const char _afb_description_v2_%s[] =\n"
+ "%s"
+ ";\n"
+ "\n"
+ , capi, desc
+ );
+ enum_verbs(declare_permissions);
+ print_perms();
+ enum_verbs(print_declare_verb);
+ printf(
+ "\n"
+ "static const struct afb_verb_v2 _afb_verbs_v2_%s[] = {\n"
+ , capi
+ );
+ enum_verbs(print_struct_verb);
+ printf(
+ " {\n"
+ " .verb = NULL,\n"
+ " .callback = NULL,\n"
+ " .auth = NULL,\n"
+ " .info = NULL,\n"
+ " .session = 0\n"
+ " }\n"
+ "};\n"
+ );
+ printf(
+ "\n"
+ "%sconst struct afb_binding_v2 %s%s = {\n"
+ " .api = \"%s\",\n"
+ " .specification = _afb_description_v2_%s,\n"
+ " .info = %s,\n"
+ " .verbs = _afb_verbs_v2_%s,\n"
+ " .preinit = %s,\n"
+ " .init = %s,\n"
+ " .onevent = %s,\n"
+ " .noconcurrency = %d\n"
+ "};\n"
+ "\n"
+ , priv ? "static " : ""
+ , priv ? "_afb_binding_v2_" : "afbBindingV2"
+ , priv ? capi : ""
+ , api
+ , capi
+ , info ? make_info(info, 0) : "NULL"
+ , capi
+ , preinit ?: "NULL"
+ , init ?: "NULL"
+ , onevent ?: "NULL"
+ , !!noconc
+ );
+
+ /* clean up */
+ json_object_put(root);
+ free(desc);
+}
+
+/** process the list of files or stdin if none */
+int main(int ac, char **av)
+{
+ if (!*++av)
+ process("-");
+ else {
+ do { process(*av); } while(*++av);
+ }
+ return 0;
+}
+
+
+
+
+
diff --git a/genskel/json2c.c b/genskel/json2c.c
new file mode 100644
index 0000000..109b6ee
--- /dev/null
+++ b/genskel/json2c.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2016, 2017 "IoT.bzh"
+ * Author José Bollo <jose.bollo@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.
+ */
+/*
+ * This simple program expands the object { "$ref": "#/path/to/a/target" }
+ *
+ * For example:
+ *
+ * {
+ * "type":{
+ * "a": "int",
+ * "b": { "$ref": "#/type/a" }
+ * }
+ * }
+ *
+ * will be exapanded to
+ *
+ * {
+ * "type":{
+ * "a": "int",
+ * "b": "int"
+ * }
+ * }
+ *
+ * Invocation: program [file|-]...
+ *
+ * without arguments, it reads the input.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <json-c/json.h>
+
+#define oom(x) do{if(!(x)){fprintf(stderr,"out of memory\n");exit(1);}}while(0)
+
+/**
+ * root of the JSON being parsed
+ */
+struct json_object *root = NULL;
+
+char *make_desc(struct json_object *o)
+{
+ const char *a, *b;
+ char *desc, c, buf[3];
+ size_t len;
+ int i, pos, e;
+
+ a = b = json_object_to_json_string_ext(root, 0);
+ len = 1;
+ while((c = *b++)) {
+ len += 1 + ('"' == c);
+ }
+
+ len += 7 * (1 + len / 72);
+ desc = malloc(len);
+ oom(desc);
+
+ len = pos = 0;
+ b = a;
+ while((c = *b++)) {
+ if (c == '"') {
+ buf[0] = '\\';
+ buf[1] = '"';
+ buf[2] = 0;
+ }
+ else if (c == '\\') {
+ switch ((c = *b++)) {
+ case 0:
+ b--;
+ break;
+ case '/':
+ buf[0] = '/';
+ buf[1] = 0;
+ break;
+ default:
+ buf[0] = '\\';
+ buf[1] = c;
+ buf[2] = 0;
+ break;
+ }
+ }
+ else {
+ buf[0] = c;
+ buf[1] = 0;
+ }
+ i = e = 0;
+ while (buf[i]) {
+ if (pos >= 77 && !e) {
+ desc[len++] = '"';
+ desc[len++] = '\n';
+ pos = 0;
+ }
+ if (pos == 0) {
+ desc[len++] = ' ';
+ desc[len++] = ' ';
+ desc[len++] = ' ';
+ desc[len++] = ' ';
+ desc[len++] = '"';
+ pos = 5;
+ }
+ c = buf[i++];
+ desc[len++] = c;
+ e = !e && c == '\\';
+ pos++;
+ }
+ }
+ desc[len++] = '"';
+ desc[len++] = '\n';
+ desc[len] = 0;
+ return desc;
+}
+
+/**
+ * process a file and prints its expansion on stdout
+ */
+void process(char *filename)
+{
+ char *desc;
+
+ /* translate - */
+ if (!strcmp(filename, "-"))
+ filename = "/dev/stdin";
+
+ /* check access */
+ if (access(filename, R_OK)) {
+ fprintf(stderr, "can't access file %s\n", filename);
+ exit(1);
+ }
+
+ /* read the file */
+ root = json_object_from_file(filename);
+ if (!root) {
+ fprintf(stderr, "reading file %s produced null\n", filename);
+ exit(1);
+ }
+
+ /* create the description */
+ desc = make_desc(root);
+
+ printf("%s", desc);
+
+ /* clean up */
+ json_object_put(root);
+ free(desc);
+}
+
+/** process the list of files or stdin if none */
+int main(int ac, char **av)
+{
+ if (!*++av)
+ process("-");
+ else {
+ do { process(*av); } while(*++av);
+ }
+ return 0;
+}
+
+
diff --git a/genskel/monitor-api.json b/genskel/monitor-api.json
new file mode 100644
index 0000000..8361d57
--- /dev/null
+++ b/genskel/monitor-api.json
@@ -0,0 +1,400 @@
+{
+ "openapi": "3.0.0",
+ "info": {
+ "description": "monitoring of bindings and internals",
+ "title": "monitor",
+ "version": "1.0",
+ "x-binding-c-generator": {
+ "api": "monitor",
+ "version": 2,
+ "prefix": "f_",
+ "postfix": "",
+ "preinit": null,
+ "init": null,
+ "onevent": null,
+ "scope": "static",
+ "private": true
+ }
+ },
+ "servers": [
+ {
+ "url": "ws://{host}:{port}/api/monitor",
+ "description": "The API server.",
+ "variables": {
+ "host": {
+ "default": "localhost"
+ },
+ "port": {
+ "default": "1234"
+ }
+ },
+ "x-afb-events": [
+ {
+ "$ref": "#/components/schemas/afb-event"
+ }
+ ]
+ }
+ ],
+ "components": {
+ "schemas": {
+ "afb-reply": {
+ "$ref": "#/components/schemas/afb-reply-v1"
+ },
+ "afb-event": {
+ "$ref": "#/components/schemas/afb-event-v1"
+ },
+ "afb-reply-v1": {
+ "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-v1": {
+ "type": "object",
+ "required": [ "jtype", "event" ],
+ "properties": {
+ "jtype": {
+ "type": "string",
+ "const": "afb-event"
+ },
+ "event": { "type": "string" },
+ "data": { "type": "object" }
+ }
+ },
+ "set-verbosity": {
+ "anyOf": [
+ { "$ref": "#/components/schemas/verbosity-map" },
+ { "$ref": "#/components/schemas/verbosity-level" }
+ ]
+ },
+ "get-request": {
+ "type": "object",
+ "properties": {
+ "verbosity": { "$ref": "#/components/schemas/get-verbosity" },
+ "apis": { "$ref": "#/components/schemas/get-apis" }
+ }
+ },
+ "get-response": {
+ "type": "object",
+ "properties": {
+ "verbosity": { "$ref": "#/components/schemas/verbosity-map" },
+ "apis": { "type": "object" }
+ }
+ },
+ "get-verbosity": {
+ "anyOf": [
+ { "type": "boolean" },
+ { "type": "array", "items": { "type": "string" } },
+ { "type": "object" }
+ ]
+ },
+ "get-apis": {
+ "anyOf": [
+ { "type": "boolean" },
+ { "type": "array", "items": { "type": "string" } },
+ { "type": "object" }
+ ]
+ },
+ "verbosity-map": {
+ "type": "object",
+ "patternProperties": { "^.*$": { "$ref": "#/components/schemas/verbosity-level" } }
+ },
+ "verbosity-level": {
+ "enum": [ "debug", 3, "info", 2, "notice", "warning", 1, "error", 0 ]
+ },
+ "trace-add": {
+ "anyOf": [
+ { "type": "array", "items": { "$ref": "#/components/schemas/trace-add-object" } },
+ { "$ref": "#/components/schemas/trace-add-any" }
+ ]
+ },
+ "trace-add-any": {
+ "anyOf": [
+ { "$ref": "#/components/schemas/trace-add-request" },
+ { "$ref": "#/components/schemas/trace-add-object" }
+ ]
+ },
+ "trace-add-object": {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string", "description": "name of the generated event", "default": "trace" },
+ "tag": { "type": "string", "description": "tag for grouping traces", "default": "trace" },
+ "api": { "type": "string", "description": "api for requests, daemons and services" },
+ "verb": { "type": "string", "description": "verb for requests" },
+ "session": { "type": "string", "description": "session for requests" },
+ "pattern": { "type": "string", "description": "pattern for events" },
+ "request": { "$ref": "#/components/schemas/trace-add-request" },
+ "daemon": { "$ref": "#/components/schemas/trace-add-daemon" },
+ "service": { "$ref": "#/components/schemas/trace-add-service" },
+ "event": { "$ref": "#/components/schemas/trace-add-event" },
+ "for": { "$ref": "#/components/schemas/trace-add" }
+ },
+ "examples": [
+ { "tag": "1", "for": [ "common", { "api": "xxx", "request": "*", "daemon": "*", "service": "*" } ] }
+ ]
+ },
+ "trace-add-request": {
+ "anyOf": [
+ { "type": "array", "items": { "$ref": "#/components/schemas/trace-request-names" } },
+ { "$ref": "#/components/schemas/trace-request-names" }
+ ]
+ },
+ "trace-request-names": {
+ "title": "name of traceable items of requests",
+ "enum": [
+ "*",
+ "addref",
+ "all",
+ "args",
+ "begin",
+ "common",
+ "context",
+ "context_get",
+ "context_set",
+ "end",
+ "event",
+ "extra",
+ "fail",
+ "get",
+ "json",
+ "life",
+ "ref",
+ "result",
+ "session",
+ "session_close",
+ "session_set_LOA",
+ "simple",
+ "store",
+ "stores",
+ "subcall",
+ "subcall_result",
+ "subcalls",
+ "subcallsync",
+ "subcallsync_result",
+ "subscribe",
+ "success",
+ "unref",
+ "unstore",
+ "unsubscribe",
+ "vverbose"
+ ]
+ },
+ "trace-add-daemon": {
+ "anyOf": [
+ { "type": "array", "items": { "$ref": "#/components/schemas/trace-daemon-names" } },
+ { "$ref": "#/components/schemas/trace-daemon-names" }
+ ]
+ },
+ "trace-daemon-names": {
+ "title": "name of traceable items of daemons",
+ "enum": [
+ "*",
+ "all",
+ "common",
+ "event_broadcast_after",
+ "event_broadcast_before",
+ "event_make",
+ "extra",
+ "get_event_loop",
+ "get_system_bus",
+ "get_user_bus",
+ "queue_job",
+ "require_api",
+ "require_api_result",
+ "rootdir_get_fd",
+ "rootdir_open_locale",
+ "unstore_req",
+ "vverbose"
+ ]
+ },
+ "trace-add-service": {
+ "anyOf": [
+ { "type": "array", "items": { "$ref": "#/components/schemas/trace-service-names" } },
+ { "$ref": "#/components/schemas/trace-service-names" }
+ ]
+ },
+ "trace-service-names": {
+ "title": "name of traceable items of services",
+ "enum": [
+ "*",
+ "all",
+ "call",
+ "call_result",
+ "callsync",
+ "callsync_result",
+ "on_event_after",
+ "on_event_before",
+ "start_after",
+ "start_before"
+ ]
+ },
+ "trace-add-event": {
+ "anyOf": [
+ { "type": "array", "items": { "$ref": "#/components/schemas/trace-event-names" } },
+ { "$ref": "#/components/schemas/trace-event-names" }
+ ]
+ },
+ "trace-event-names": {
+ "title": "name of traceable items of events",
+ "enum": [
+ "*",
+ "all",
+ "broadcast_after",
+ "broadcast_before",
+ "common",
+ "create",
+ "drop",
+ "extra",
+ "name",
+ "push_after",
+ "push_before"
+ ]
+ },
+ "trace-drop": {
+ "anyOf": [
+ { "type": "boolean" },
+ {
+ "type": "object",
+ "properties": {
+ "event": { "anyOf": [ { "type": "string" }, { "type": "array", "items": "string" } ] },
+ "tag": { "anyOf": [ { "type": "string" }, { "type": "array", "items": "string" } ] },
+ "session": { "anyOf": [ { "type": "string" }, { "type": "array", "items": "string" } ] }
+ }
+ }
+ ]
+ }
+ },
+ "x-permissions": {
+ "trace": {
+ "permission": "urn:AGL:permission:monitor:public:trace"
+ },
+ "set": {
+ "permission": "urn:AGL:permission:monitor:public:set"
+ },
+ "get": {
+ "permission": "urn:AGL:permission:monitor:public:get"
+ },
+ "get-or-set": {
+ "anyOf": [
+ { "$ref": "#/components/x-permissions/get" },
+ { "$ref": "#/components/x-permissions/set" }
+ ]
+ }
+ }
+ },
+ "paths": {
+ "/get": {
+ "description": "Get monitoring data.",
+ "get": {
+ "x-permissions": {
+ "$ref": "#/components/x-permissions/get-or-set"
+ },
+ "parameters": [
+ {
+ "in": "query",
+ "name": "verbosity",
+ "required": false,
+ "schema": { "$ref": "#/components/schemas/get-verbosity" }
+ },
+ {
+ "in": "query",
+ "name": "apis",
+ "required": false,
+ "schema": { "$ref": "#/components/schemas/get-apis" }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A complex object array response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/afb-reply"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/set": {
+ "description": "Set monitoring actions.",
+ "get": {
+ "x-permissions": {
+ "$ref": "#/components/x-permissions/set"
+ },
+ "parameters": [
+ {
+ "in": "query",
+ "name": "verbosity",
+ "required": false,
+ "schema": { "$ref": "#/components/schemas/set-verbosity" }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A complex object array response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/afb-reply"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/trace": {
+ "description": "Set monitoring actions.",
+ "get": {
+ "x-permissions": {
+ "$ref": "#/components/x-permissions/trace"
+ },
+ "parameters": [
+ {
+ "in": "query",
+ "name": "add",
+ "required": false,
+ "schema": { "$ref": "#/components/schemas/trace-add" }
+ },
+ {
+ "in": "query",
+ "name": "drop",
+ "required": false,
+ "schema": { "$ref": "#/components/schemas/trace-drop" }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A complex object array response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/afb-reply"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}