From: Fulup Ar Foll
Date: Sun, 29 May 2016 21:41:40 +0000 (+0200)
Subject: Merge branch 'master' of https://github.com/iotbzh/afb-daemon
X-Git-Tag: blowfish_2.0.1~62
X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=commitdiff_plain;h=26bca5f8a8c6f9403a84945a5cd914b6da948efd;hp=706bc5c7e0db5f7a782f80ab99fa8fe005289f8d;p=src%2Fapp-framework-binder.git
Merge branch 'master' of https://github.com/iotbzh/afb-daemon
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c5094bb8..7a1a0d01 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,6 +10,9 @@ SET(PROJECT_DESCRIPTION "Secured binder of API for clients of the Application fr
SET(PROJECT_VERSION "0.5")
SET(PROJECT_URL "https://github.com/iotbzh/afb-daemon")
+SET(LIBAFBWSC_VERSION "0.5")
+SET(LIBAFBWSC_SOVERSION "0")
+
INCLUDE(FindPkgConfig)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckLibraryExists)
@@ -69,11 +72,11 @@ ADD_SUBDIRECTORY(plugins)
############################################################
# installs the pkgconfig files
CONFIGURE_FILE(afb-daemon.pc.in afb-daemon.pc @ONLY)
-CONFIGURE_FILE(afb-wsc.pc.in afb-wsc.pc @ONLY)
+CONFIGURE_FILE(libafbwsc.pc.in libafbwsc.pc @ONLY)
INSTALL(FILES
${CMAKE_CURRENT_BINARY_DIR}/afb-daemon.pc
- ${CMAKE_CURRENT_BINARY_DIR}/afb-wsc.pc
+ ${CMAKE_CURRENT_BINARY_DIR}/libafbwsc.pc
DESTINATION
${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
diff --git a/doc/afb-plugin-writing.html b/doc/afb-plugin-writing.html
index 20e25972..b80006f4 100644
--- a/doc/afb-plugin-writing.html
+++ b/doc/afb-plugin-writing.html
@@ -8,7 +8,7 @@
HOWTO WRITE a PLUGIN for AFB-DAEMON
version: 1
-Date: 27 mai 2016
+Date: 29 mai 2016
Author: José Bollo
@@ -18,14 +18,14 @@ Author: José Bollo
Summary
-Before going into details, through a tiny example,
-a short overview plugins basis is needed.
+Before moving further through an example, here after
+a short overview of binder plugins fundamentals.
Nature of a plugin
-A plugin is a separate piece of code made of a shared library.
-The plugin is loaded and activated by afb-daemon when afb-daemon
-starts.
+A plugin is an independent piece of software, self contain and expose as a dynamically loadable library.
+A plugin is loaded by afb-daemon that exposes contained API dynamically at runtime.
-Technically, a plugin is not linked to any library of afb-daemon.
+Technically, a binder plugins does not reference and is not linked with any library from afb-daemon.
-
-Kinds of plugins
+
+Class of plugins
-There is two kinds of plugins: application plugins and service
-plugins.
+Application binder supports two kinds of plugins: application plugins and service
+plugins. Technically both class of plugin are equivalent and coding API is shared. Only sharing mode and security context diverge.
-
-Application plugins
+
+Application-plugins
-Application plugins are intended to be instanciated for each
-application: when an application using that plugin is started,
-its binder starts a new instance of the plugin.
+Application-plugins implements the glue in between application’s UI and services. Every AGL application
+has a corresponding binder that typically activates one or many plugins to interface the application logic with lower platform services.
+When an application is started by AGL application framework, a dedicate binder is started that loads/activates application plugin(s).
+The API expose by application-plugin are executed within corresponding application security context.
-It means that the application plugins mainly have only one
-context to manage for one client.
+Application plugins generally handle a unique context for a unique client. As the application framework start
+a dedicated instance of afb_daemon for each AGL application, if a given plugin is used within multiple application each of those
+application get a new and private instance of this “shared” plugin.
-
-Service plugins
+
+Service-plugins
-Service plugins are intended to be instanciated only one time
-only and connected to many clients.
+Service-plugins enable API activation within corresponding service security context and not within calling application context.
+Service-plugins are intended to run as a unique instance that is shared in between multiple clients.
-So either it does not manage context at all or otherwise,
-if it manages context, it should be able to manage one context
-per client.
+Service-plugins can either be stateless or manage client context. When managing context each client get a private context.
-In details, it may be useful to have service plugins at a user
-level.
+Sharing may either be global to the platform (ie: GPS service) or dedicated to a given user (ie: preference management)
-
-Live cycle of a plugin within afb-daemon
+
+Live cycle of plugins within afb-daemon
-The plugins are loaded and activated when afb-daemon starts.
+Application and service plugins are loaded and activated each time a new afb-daemon is started.
-At start, the plugin initialise itself.
-If it fails to initialise then afb-daemon stops.
+At launch time, every loaded plugin initialise itself.
+If a single plugin initialisation fail corresponding instance of afb-daemon self aborts.
-Conversely, if it success to initialize, it must declare
-a name, that must be unique, and a list of API’s verbs.
+Conversely, when plugin initialisation succeeds, it should register
+its unique name and the list of API verbs it exposes.
-When initialized, the functions implementing the API’s verbs
-of the plugin are activated on call.
+When initialised, on request from clients plugin’s function corresponding to expose API verbs
+are activated by the afb-daemon instance attached to the application or service.
-At the end, nothing special is done by afb-daemon.
-Consequently, developpers of plugins should use ‘atexit’
-or ‘on_exit’ during initialisation if they need to
-perform specific actions when stopping.
+At exit time, no special action is enforced by afb-daemon. When a specific actions is required at afb-daemon stop,
+developers should use ‘atexit/on_exit’ during plugin initialisation sequence to register a custom exit function.
-
-Content of a plugin
+
+Plugin Contend
-For afb-daemon, a plugin contains 2 different
-things: names and functions.
+Afb-daemon’s plugin register two classes of objects: names and functions.
-There is two kind of names:
- - the name of the plugin,
- - the names of the verbs.
+Plugins declare categories of names:
+ - A unique plugin name,
+ - Multiple API verb’s names.
-There is two kind of functions:
- - the initialisation function
- - functions implementing verbs
+Plugins declare two categories of functions:
+ - initialisation function
+ - API functions implementing verbs
-Afb-daemon translates the name of the method that is
-invoked to a pair of API and verb names. For example,
-the method named foo/bar translated to the API
-name foo and the verb name bar.
-To serve it, afb-daemon search the plugin that record
-the name foo and if it also recorded the verb bar,
-it calls the implementation function declared for this verb.
+Afb-daemon parses URI requests to extract plugin name and API verb.
+As an example, URI foo/bar translates to API verb named bar within plugin named foo.
+To serve such a request, afb-daemon looks for an active plugin named foo and then within this plugin for an API verb named bar.
+When find afb-daemon calls corresponding function with attached parameter if any.
-Afb-daemon make no distinction between lower case
-and upper case when searching for a method.
-Thus, The names TicTacToe/Board and tictactoe/borad
-are equals.
+Afb-daemon ignores letter case when parsing URI. Thus TicTacToe/Board and tictactoe/board are equivalent.
The name of the plugin
@@ -370,7 +359,7 @@ and upper case when searching for an API by its name.
The names of the verbs are not checked.
However, the validity rules for verb’s names are the
-same as for API’s names except that the dot (.) character
+same as for API names except that the dot (.) character
is forbidden.
Afb-daemon make no distinction between lower case
diff --git a/doc/afb-plugin-writing.md b/doc/afb-plugin-writing.md
index 3783abcf..54f153c5 100644
--- a/doc/afb-plugin-writing.md
+++ b/doc/afb-plugin-writing.md
@@ -1,7 +1,7 @@
HOWTO WRITE a PLUGIN for AFB-DAEMON
===================================
version: 1
- Date: 27 mai 2016
+ Date: 29 mai 2016
Author: José Bollo
TABLE-OF-CONTENT-HERE
@@ -86,7 +86,7 @@ As an example, URI **foo/bar** translates to plugin named **foo** and method nam
To serve such a request, afb-daemon looks for an active plugin named **foo** and then within this plugin for a method named **bar**.
When find afb-daemon calls corresponding method with attached parameter if any.
-Afb-daemon ignores letter case when parsing URI. Thus **TicTacToe/Board** and **tictactoe/borad** are equivalent.
+Afb-daemon ignores letter case when parsing URI. Thus **TicTacToe/Board** and **tictactoe/board** are equivalent.
#### The name of the plugin
diff --git a/doc/updt.sh b/doc/updt.sh
index af64e31e..1c9d023e 100755
--- a/doc/updt.sh
+++ b/doc/updt.sh
@@ -29,7 +29,7 @@ updadate() {
mkhtml() {
local x=$1
local h=${x%%.md}.html
- expand -i $x | sed 's: : :' > $h.pre
+ expand -i $x | sed 's:^ : :' > $h.pre
markdown -f toc,autolink $h.pre > $h.toc.no
markdown -Tf toc,autolink $h.pre > $h.toc.yes
head --bytes=-$(stat -c %s $h.toc.no) $h.toc.yes > $h.toc
diff --git a/include/afb/afb-event-sender-itf.h b/include/afb/afb-event-sender-itf.h
deleted file mode 100644
index ad354319..00000000
--- a/include/afb/afb-event-sender-itf.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author: José Bollo
- *
- * 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
-
-struct json_object;
-
-struct afb_event_sender_itf {
- void (*push)(void *event_sender, const char *name, struct json_object *object);
-};
-
-struct afb_event_sender {
- const struct afb_event_sender_itf *itf;
- void *closure;
-};
-
-static inline void afb_event_sender_push(struct afb_event_sender mgr, const char *name, struct json_object *object)
-{
- return mgr.itf->push(mgr.closure, name, object);
-}
-
diff --git a/include/afb/afb-plugin.h b/include/afb/afb-plugin.h
index 2b065b08..1eb3475b 100644
--- a/include/afb/afb-plugin.h
+++ b/include/afb/afb-plugin.h
@@ -39,7 +39,6 @@
*/
#include
-#include
/*
* Definition of the versions of the plugin.
@@ -141,10 +140,10 @@ struct sd_bus;
* Definition of the facilities provided by the daemon.
*/
struct afb_daemon_itf {
- struct afb_event_sender (*get_event_sender)(void *closure); /* get the event manager */
- struct sd_event *(*get_event_loop)(void *closure); /* get the common systemd's event loop */
- struct sd_bus *(*get_user_bus)(void *closure); /* get the common systemd's user d-bus */
- struct sd_bus *(*get_system_bus)(void *closure); /* get the common systemd's system d-bus */
+ void (*event_broadcast)(void *closure, const char *name, struct json_object *object); /* broadcasts evant 'name' with 'object' */
+ struct sd_event *(*get_event_loop)(void *closure); /* gets the common systemd's event loop */
+ struct sd_bus *(*get_user_bus)(void *closure); /* gets the common systemd's user d-bus */
+ struct sd_bus *(*get_system_bus)(void *closure); /* gets the common systemd's system d-bus */
void (*vverbose)(void*closure, int level, const char *file, int line, const char *fmt, va_list args);
};
@@ -172,15 +171,6 @@ struct AFB_interface
*/
extern const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *interface);
-/*
- * Retrieves the event sender of AFB
- * 'daemon' MUST be the daemon given in interface when activating the plugin.
- */
-static inline struct afb_event_sender afb_daemon_get_event_sender(struct afb_daemon daemon)
-{
- return daemon.itf->get_event_sender(daemon.closure);
-}
-
/*
* Retrieves the common systemd's event loop of AFB
* 'daemon' MUST be the daemon given in interface when activating the plugin.
@@ -219,7 +209,7 @@ static inline struct sd_bus *afb_daemon_get_system_bus(struct afb_daemon daemon)
*/
static inline void afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object)
{
- return afb_event_sender_push(afb_daemon_get_event_sender(daemon), name, object);
+ return daemon.itf->event_broadcast(daemon.closure, name, object);
}
/*
@@ -237,6 +227,9 @@ static inline void afb_daemon_verbose(struct afb_daemon daemon, int level, const
va_end(args);
}
+/*
+ * Macros for logging messages
+ */
#if !defined(NO_PLUGIN_VERBOSE_MACRO)
# if !defined(NO_PLUGIN_FILE_LINE_INDICATION)
# define ERROR(itf,...) do{if(itf->verbosity>=0)afb_daemon_verbose(itf->daemon,3,__FILE__,__LINE__,__VA_ARGS__);}while(0)
diff --git a/afb-wsc.pc.in b/libafbwsc.pc.in
similarity index 100%
rename from afb-wsc.pc.in
rename to libafbwsc.pc.in
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f41a3a88..ca20665b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -73,6 +73,9 @@ INSTALL(TARGETS afb-daemon
# build and install libafbwsc
###########################################
ADD_LIBRARY(afbwsc SHARED afb-ws.c afb-ws-client.c afb-wsj1.c websock.c afb-common.c)
+SET_TARGET_PROPERTIES(afbwsc PROPERTIES
+ VERSION ${LIBAFBWSC_VERSION}
+ SOVERSION ${LIBAFBWSC_SOVERSION})
TARGET_LINK_LIBRARIES(afbwsc
${libsystemd_LIBRARIES}
-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export-afbwsc.map
diff --git a/src/afb-api-dbus.c b/src/afb-api-dbus.c
index f4fd0eba..c0bc57a8 100644
--- a/src/afb-api-dbus.c
+++ b/src/afb-api-dbus.c
@@ -423,7 +423,7 @@ static void dbus_req_reply(struct dbus_req *dreq, uint8_t type, const char *firs
static void dbus_req_success(struct dbus_req *dreq, struct json_object *obj, const char *info)
{
- dbus_req_reply(dreq, RETOK, json_object_to_json_string(obj), info);
+ dbus_req_reply(dreq, RETOK, json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN), info);
}
static void dbus_req_fail(struct dbus_req *dreq, const char *status, const char *info)
@@ -516,7 +516,7 @@ static void afb_api_dbus_server_send_event(struct api_dbus *api, const char *eve
int rc;
rc = sd_bus_emit_signal(api->sdbus, api->path, api->name,
- "event", "ss", event, json_object_to_json_string(object));
+ "event", "ss", event, json_object_to_json_string_ext(object, JSON_C_TO_STRING_PLAIN));
if (rc < 0)
ERROR("error while emiting event %s", event);
json_object_put(object);
diff --git a/src/afb-api-so.c b/src/afb-api-so.c
index abe100b0..9756b0e0 100644
--- a/src/afb-api-so.c
+++ b/src/afb-api-so.c
@@ -30,7 +30,6 @@
#include
#include
-#include
#include "session.h"
#include "afb-common.h"
@@ -54,7 +53,7 @@ static int api_timeout = 15;
static const char plugin_register_function_v1[] = "pluginAfbV1Register";
-static void afb_api_so_event_sender_push(struct api_so_desc *desc, const char *name, struct json_object *object)
+static int afb_api_so_event_broadcast(struct api_so_desc *desc, const char *name, struct json_object *object)
{
size_t length;
char *event;
@@ -65,16 +64,7 @@ static void afb_api_so_event_sender_push(struct api_so_desc *desc, const char *n
memcpy(event, desc->plugin->v1.prefix, desc->apilength);
event[desc->apilength] = '/';
memcpy(event + desc->apilength + 1, name, length + 1);
- ctxClientEventSend(NULL, event, object);
-}
-
-static const struct afb_event_sender_itf event_sender_itf = {
- .push = (void*)afb_api_so_event_sender_push
-};
-
-static struct afb_event_sender afb_api_so_get_event_sender(struct api_so_desc *desc)
-{
- return (struct afb_event_sender){ .itf = &event_sender_itf, .closure = desc };
+ return ctxClientEventSend(NULL, event, object);
}
static void afb_api_so_vverbose(struct api_so_desc *desc, int level, const char *file, int line, const char *fmt, va_list args)
@@ -90,7 +80,7 @@ static void afb_api_so_vverbose(struct api_so_desc *desc, int level, const char
}
static const struct afb_daemon_itf daemon_itf = {
- .get_event_sender = (void*)afb_api_so_get_event_sender,
+ .event_broadcast = (void*)afb_api_so_event_broadcast,
.get_event_loop = (void*)afb_common_get_event_loop,
.get_user_bus = (void*)afb_common_get_user_bus,
.get_system_bus = (void*)afb_common_get_system_bus,
diff --git a/src/afb-context.c b/src/afb-context.c
index 0492ecbf..ba093c37 100644
--- a/src/afb-context.c
+++ b/src/afb-context.c
@@ -58,7 +58,7 @@ int afb_context_connect(struct afb_context *context, const char *uuid, const cha
init_context(context, session, token);
if (created) {
context->created = 1;
- context->refreshing = 1;
+ /* context->refreshing = 1; */
}
return 0;
}
diff --git a/src/afb-hreq.c b/src/afb-hreq.c
index 4239670d..ab174e2f 100644
--- a/src/afb-hreq.c
+++ b/src/afb-hreq.c
@@ -677,7 +677,7 @@ static void req_send(struct afb_hreq *hreq, const char *buffer, size_t size)
static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t max)
{
- ssize_t len = stpncpy(buf, json_object_to_json_string(obj)+pos, max) - buf;
+ ssize_t len = stpncpy(buf, json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN)+pos, max) - buf;
return len ? : (ssize_t)MHD_CONTENT_READER_END_OF_STREAM;
}
@@ -698,7 +698,7 @@ static void req_reply(struct afb_hreq *hreq, unsigned retcode, const char *statu
if (reqid != NULL && json_object_object_get_ex(reply, "request", &request))
json_object_object_add (request, short_key_for_reqid, json_object_new_string(reqid));
- response = MHD_create_response_from_callback((uint64_t)strlen(json_object_to_json_string(reply)), SIZE_RESPONSE_BUFFER, (void*)send_json_cb, reply, (void*)json_object_put);
+ response = MHD_create_response_from_callback((uint64_t)strlen(json_object_to_json_string_ext(reply, JSON_C_TO_STRING_PLAIN)), SIZE_RESPONSE_BUFFER, (void*)send_json_cb, reply, (void*)json_object_put);
afb_hreq_reply(hreq, retcode, response, NULL);
}
diff --git a/src/afb-ws-client.h b/src/afb-ws-client.h
index 125bd6f3..f2aee7d0 100644
--- a/src/afb-ws-client.h
+++ b/src/afb-ws-client.h
@@ -20,4 +20,10 @@
struct afb_wsj1;
struct afb_wsj1_itf;
+/*
+ * Makes the WebSocket handshake at the 'uri' and if successful
+ * instanciate a wsj1 websocket for this connection using 'itf' and 'closure'.
+ * (see afb_wsj1_create).
+ * Returns NULL in case of failure with errno set appriately.
+ */
extern struct afb_wsj1 *afb_ws_client_connect_wsj1(const char *uri, struct afb_wsj1_itf *itf, void *closure);
diff --git a/src/afb-ws-json1.c b/src/afb-ws-json1.c
index 9e20e7d9..88f9b358 100644
--- a/src/afb-ws-json1.c
+++ b/src/afb-ws-json1.c
@@ -416,7 +416,7 @@ static void aws_emit(struct afb_ws_json1 *aws, int code, const char *id, size_t
json_object_array_add(msg, json_object_new_string(token));
/* emits the reply */
- txt = json_object_to_json_string(msg);
+ txt = json_object_to_json_string_ext(msg, JSON_C_TO_STRING_PLAIN);
afb_ws_text(aws->ws, txt, strlen(txt));
json_object_put(msg);
}
diff --git a/src/afb-wsj1.c b/src/afb-wsj1.c
index df4a2344..7f030a0c 100644
--- a/src/afb-wsj1.c
+++ b/src/afb-wsj1.c
@@ -427,18 +427,18 @@ struct afb_wsj1 *afb_wsj1_msg_wsj1(struct afb_wsj1_msg *msg)
static int wsj1_send_isot(struct afb_wsj1 *wsj1, int i1, const char *s1, const char *o1, const char *t1)
{
char code[2] = { (char)('0' + i1), 0 };
- return afb_ws_texts(wsj1->ws, "[", code, ",\"", s1, "\",", o1, t1 != NULL ? ",\"" : "]", t1, "\"]", NULL);
+ return afb_ws_texts(wsj1->ws, "[", code, ",\"", s1, "\",", o1 == NULL ? "null" : o1, t1 != NULL ? ",\"" : "]", t1, "\"]", NULL);
}
static int wsj1_send_issot(struct afb_wsj1 *wsj1, int i1, const char *s1, const char *s2, const char *o1, const char *t1)
{
char code[2] = { (char)('0' + i1), 0 };
- return afb_ws_texts(wsj1->ws, "[", code, ",\"", s1, "\",\"", s2, "\",", o1, t1 != NULL ? ",\"" : "]", t1, "\"]", NULL);
+ return afb_ws_texts(wsj1->ws, "[", code, ",\"", s1, "\",\"", s2, "\",", o1 == NULL ? "null" : o1, t1 != NULL ? ",\"" : "]", t1, "\"]", NULL);
}
int afb_wsj1_send_event_j(struct afb_wsj1 *wsj1, const char *event, struct json_object *object)
{
- return afb_wsj1_send_event_s(wsj1, event, json_object_to_json_string(object));
+ return afb_wsj1_send_event_s(wsj1, event, json_object_to_json_string_ext(object, JSON_C_TO_STRING_PLAIN));
}
int afb_wsj1_send_event_s(struct afb_wsj1 *wsj1, const char *event, const char *object)
@@ -448,7 +448,7 @@ int afb_wsj1_send_event_s(struct afb_wsj1 *wsj1, const char *event, const char *
int afb_wsj1_call_j(struct afb_wsj1 *wsj1, const char *api, const char *verb, struct json_object *object, void (*on_reply)(void *closure, struct afb_wsj1_msg *msg), void *closure)
{
- return afb_wsj1_call_s(wsj1, api, verb, json_object_to_json_string(object), on_reply, closure);
+ return afb_wsj1_call_s(wsj1, api, verb, json_object_to_json_string_ext(object, JSON_C_TO_STRING_PLAIN), on_reply, closure);
}
int afb_wsj1_call_s(struct afb_wsj1 *wsj1, const char *api, const char *verb, const char *object, void (*on_reply)(void *closure, struct afb_wsj1_msg *msg), void *closure)
@@ -480,7 +480,7 @@ int afb_wsj1_call_s(struct afb_wsj1 *wsj1, const char *api, const char *verb, co
int afb_wsj1_reply_ok_j(struct afb_wsj1_msg *msg, struct json_object *object, const char *token)
{
- return afb_wsj1_reply_ok_s(msg, json_object_to_json_string(object), token);
+ return afb_wsj1_reply_ok_s(msg, json_object_to_json_string_ext(object, JSON_C_TO_STRING_PLAIN), token);
}
int afb_wsj1_reply_ok_s(struct afb_wsj1_msg *msg, const char *object, const char *token)
@@ -490,7 +490,7 @@ int afb_wsj1_reply_ok_s(struct afb_wsj1_msg *msg, const char *object, const char
int afb_wsj1_reply_error_j(struct afb_wsj1_msg *msg, struct json_object *object, const char *token)
{
- return afb_wsj1_reply_error_s(msg, json_object_to_json_string(object), token);
+ return afb_wsj1_reply_error_s(msg, json_object_to_json_string_ext(object, JSON_C_TO_STRING_PLAIN), token);
}
int afb_wsj1_reply_error_s(struct afb_wsj1_msg *msg, const char *object, const char *token)
diff --git a/src/afb-wsj1.h b/src/afb-wsj1.h
index 08bf67f7..44aa5656 100644
--- a/src/afb-wsj1.h
+++ b/src/afb-wsj1.h
@@ -22,44 +22,189 @@ struct afb_wsj1_msg;
struct json_object;
+/*
+ * Interface for callback functions.
+ * The received closure is the closure passed when creating the afb_wsj1
+ * socket using afb_wsj1_create.
+ */
struct afb_wsj1_itf {
+ /*
+ * This function is called on hangup.
+ * Receives the 'closure' and the handle 'wsj1'
+ */
void (*on_hangup)(void *closure, struct afb_wsj1 *wsj1);
+
+ /*
+ * This function is called on incoming call.
+ * Receives the 'closure'
+ */
void (*on_call)(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg);
+
+ /*
+ * This function is called on incoming event
+ */
void (*on_event)(void *closure, const char *event, struct afb_wsj1_msg *msg);
};
+/*
+ * Creates the afb_wsj1 socket connected to the file descriptor 'fd'
+ * and having the callback interface defined by 'itf' for the 'closure'.
+ * Returns the created wsj1 websocket or NULL in case of error.
+ */
extern struct afb_wsj1 *afb_wsj1_create(int fd, struct afb_wsj1_itf *itf, void *closure);
+/*
+ * Increases by one the count of reference to 'wsj1'
+ */
extern void afb_wsj1_addref(struct afb_wsj1 *wsj1);
+
+/*
+ * Decreases by one the count of reference to 'wsj1'
+ * and if it falls to zero releases the used resources
+ * and free the memory
+ */
extern void afb_wsj1_unref(struct afb_wsj1 *wsj1);
+/*
+ * Sends on 'wsj1' the event of name 'event' with the
+ * data 'object'. If not NULL, 'object' should be a valid
+ * JSON string.
+ * Return 0 in case of success. Otherwise, returns -1 and set errno.
+ */
extern int afb_wsj1_send_event_s(struct afb_wsj1 *wsj1, const char *event, const char *object);
+
+/*
+ * Sends on 'wsj1' the event of name 'event' with the
+ * data 'object'. 'object' can be NULL.
+ * Return 0 in case of success. Otherwise, returns -1 and set errno.
+ */
extern int afb_wsj1_send_event_j(struct afb_wsj1 *wsj1, const char *event, struct json_object *object);
+/*
+ * Sends on 'wsj1' a call to the method of 'api'/'verb' with arguments
+ * given by 'object'. If not NULL, 'object' should be a valid JSON string.
+ * On receiving the reply, the function 'on_reply' is called with 'closure'
+ * as its first argument and the message of the reply.
+ * Return 0 in case of success. Otherwise, returns -1 and set errno.
+ */
extern int afb_wsj1_call_s(struct afb_wsj1 *wsj1, const char *api, const char *verb, const char *object, void (*on_reply)(void *closure, struct afb_wsj1_msg *msg), void *closure);
+
+/*
+ * Sends on 'wsj1' a call to the method of 'api'/'verb' with arguments
+ * given by 'object'. 'object' can be NULL.
+ * On receiving the reply, the function 'on_reply' is called with 'closure'
+ * as its first argument and the message of the reply.
+ * Return 0 in case of success. Otherwise, returns -1 and set errno.
+ */
extern int afb_wsj1_call_j(struct afb_wsj1 *wsj1, const char *api, const char *verb, struct json_object *object, void (*on_reply)(void *closure, struct afb_wsj1_msg *msg), void *closure);
+/*
+ * Sends for message 'msg' the OK reply with the 'object' and, if not NULL, the token.
+ * If not NULL, 'object' should be a valid JSON string.
+ * Return 0 in case of success. Otherwise, returns -1 and set errno.
+ */
extern int afb_wsj1_reply_ok_s(struct afb_wsj1_msg *msg, const char *object, const char *token);
+
+/*
+ * Sends for message 'msg' the OK reply with the 'object' and, if not NULL, the token.
+ * 'object' can be NULL.
+ * Return 0 in case of success. Otherwise, returns -1 and set errno.
+ */
extern int afb_wsj1_reply_ok_j(struct afb_wsj1_msg *msg, struct json_object *object, const char *token);
+/*
+ * Sends for message 'msg' the ERROR reply with the 'object' and, if not NULL, the token.
+ * If not NULL, 'object' should be a valid JSON string.
+ * Return 0 in case of success. Otherwise, returns -1 and set errno.
+ */
extern int afb_wsj1_reply_error_s(struct afb_wsj1_msg *msg, const char *object, const char *token);
+
+/*
+ * Sends for message 'msg' the ERROR reply with the 'object' and, if not NULL, the token.
+ * 'object' can be NULL.
+ * Return 0 in case of success. Otherwise, returns -1 and set errno.
+ */
extern int afb_wsj1_reply_error_j(struct afb_wsj1_msg *msg, struct json_object *object, const char *token);
+/*
+ * Increases by one the count of reference to 'msg'.
+ * Should be called if callbacks stores the message.
+ */
extern void afb_wsj1_msg_addref(struct afb_wsj1_msg *msg);
+
+/*
+ * Decreases by one the count of reference to 'msg'.
+ * and if it falls to zero releases the used resources
+ * and free the memory.
+ * Should be called if 'afb_wsj1_msg_addref' was called.
+ */
extern void afb_wsj1_msg_unref(struct afb_wsj1_msg *msg);
+/*
+ * Returns 1 if 'msg' is for a CALL
+ * Otherwise returns 0.
+ */
extern int afb_wsj1_msg_is_call(struct afb_wsj1_msg *msg);
+
+/*
+ * Returns 1 if 'msg' is for a REPLY of any kind
+ * Otherwise returns 0.
+ */
extern int afb_wsj1_msg_is_reply(struct afb_wsj1_msg *msg);
+
+/*
+ * Returns 1 if 'msg' is for a REPLY OK
+ * Otherwise returns 0.
+ */
extern int afb_wsj1_msg_is_reply_ok(struct afb_wsj1_msg *msg);
+
+/*
+ * Returns 1 if 'msg' is for a REPLY ERROR
+ * Otherwise returns 0.
+ */
extern int afb_wsj1_msg_is_reply_error(struct afb_wsj1_msg *msg);
+
+/*
+ * Returns 1 if 'msg' is for an EVENT
+ * Otherwise returns 0.
+ */
extern int afb_wsj1_msg_is_event(struct afb_wsj1_msg *msg);
+/*
+ * Returns the api of the call for 'msg'
+ * Returns NULL if 'msg' is not for a CALL
+ */
extern const char *afb_wsj1_msg_api(struct afb_wsj1_msg *msg);
+
+/*
+ * Returns the verb call for 'msg'
+ * Returns NULL if 'msg' is not for a CALL
+ */
extern const char *afb_wsj1_msg_verb(struct afb_wsj1_msg *msg);
+
+/*
+ * Returns the event name for 'msg'
+ * Returns NULL if 'msg' is not for an EVENT
+ */
extern const char *afb_wsj1_msg_event(struct afb_wsj1_msg *msg);
+
+/*
+ * Returns the token sent with 'msg' or NULL when no token was sent.
+ */
extern const char *afb_wsj1_msg_token(struct afb_wsj1_msg *msg);
+
+/*
+ * Returns the wsj1 of 'msg'
+ */
extern struct afb_wsj1 *afb_wsj1_msg_wsj1(struct afb_wsj1_msg *msg);
+/*
+ * Returns the string representation of the object received with 'msg'
+ */
extern const char *afb_wsj1_msg_object_s(struct afb_wsj1_msg *msg);
+
+/*
+ * Returns the object received with 'msg'
+ */
extern struct json_object *afb_wsj1_msg_object_j(struct afb_wsj1_msg *msg);
diff --git a/test/AFB.html b/test/AFB.html
index a1a4bf59..b0832d9a 100644
--- a/test/AFB.html
+++ b/test/AFB.html
@@ -3,7 +3,7 @@
Test of AFB Echo