aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2018-04-09 18:16:07 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2018-06-15 17:57:36 +0200
commit4521c1e7ae5371ab9d639adc617d17fb4e8ded0c (patch)
treea8a1416a2d58c16ab3993c7e4dc405fc71daab6a /src
parent63682b4da9d3e892d1d0a671de860adc43068142 (diff)
api-v3: First draft
This commit introduces the bindings v3 API for bindings. The documentation has still to be improved and will come very soon. Change-Id: I8f9007370e29f671fdfd1da87fff7372a17db7af Signed-off-by: José Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt28
-rw-r--r--src/afb-api-dbus.c129
-rw-r--r--src/afb-api-dbus.h4
-rw-r--r--src/afb-api-dyn.c285
-rw-r--r--src/afb-api-dyn.h63
-rw-r--r--src/afb-api-so-v1.c139
-rw-r--r--src/afb-api-so-v1.h10
-rw-r--r--src/afb-api-so-v2.c125
-rw-r--r--src/afb-api-so-v2.h9
-rw-r--r--src/afb-api-so-v3.c128
-rw-r--r--src/afb-api-so-v3.h23
-rw-r--r--src/afb-api-so-vdyn.c27
-rw-r--r--src/afb-api-so-vdyn.h2
-rw-r--r--src/afb-api-so.c86
-rw-r--r--src/afb-api-so.h12
-rw-r--r--src/afb-api-v3.c358
-rw-r--r--src/afb-api-v3.h81
-rw-r--r--src/afb-api-ws.c23
-rw-r--r--src/afb-api-ws.h8
-rw-r--r--src/afb-api.c4
-rw-r--r--src/afb-api.h13
-rw-r--r--src/afb-apiset.c823
-rw-r--r--src/afb-apiset.h47
-rw-r--r--src/afb-auth.c60
-rw-r--r--src/afb-autoset.c104
-rw-r--r--src/afb-autoset.h23
-rw-r--r--src/afb-calls.c818
-rw-r--r--src/afb-calls.h235
-rw-r--r--src/afb-config.c236
-rw-r--r--src/afb-config.h52
-rw-r--r--src/afb-context.c11
-rw-r--r--src/afb-cred.c110
-rw-r--r--src/afb-cred.h7
-rw-r--r--src/afb-evt.c147
-rw-r--r--src/afb-evt.h30
-rw-r--r--src/afb-export.c1774
-rw-r--r--src/afb-export.h115
-rw-r--r--src/afb-hook.c928
-rw-r--r--src/afb-hook.h375
-rw-r--r--src/afb-hreq.c43
-rw-r--r--src/afb-monitor.c96
-rw-r--r--src/afb-monitor.h4
-rw-r--r--src/afb-msg-json.c21
-rw-r--r--src/afb-msg-json.h4
-rw-r--r--src/afb-proto-ws.c306
-rw-r--r--src/afb-proto-ws.h23
-rw-r--r--src/afb-session.c92
-rw-r--r--src/afb-stub-ws.c138
-rw-r--r--src/afb-stub-ws.h4
-rw-r--r--src/afb-supervision.c39
-rw-r--r--src/afb-trace.c591
-rw-r--r--src/afb-trace.h4
-rw-r--r--src/afb-ws-json1.c16
-rw-r--r--src/afb-xreq.c977
-rw-r--r--src/afb-xreq.h89
-rw-r--r--src/afs-config.c6
-rw-r--r--src/afs-supervision.h2
-rw-r--r--src/afs-supervisor.c133
-rw-r--r--src/afs-supervisor.h5
-rw-r--r--src/devtools/genskel.c108
-rw-r--r--src/devtools/monitor-api.json11
-rw-r--r--src/jobs-fake.c4
-rw-r--r--src/jobs.c2
-rw-r--r--src/main-afb-client-demo.c (renamed from src/afb-client-demo.c)83
-rw-r--r--src/main-afb-daemon.c (renamed from src/main.c)56
-rw-r--r--src/main-afs-supervisor.c (renamed from src/afs-main.c)4
-rw-r--r--src/monitor-api.inc39
-rw-r--r--src/pearson.c39
-rw-r--r--src/pearson.h20
-rw-r--r--src/tests/CMakeLists.txt2
-rw-r--r--src/tests/apiset/CMakeLists.txt23
-rw-r--r--src/tests/apiset/test-apiset.c579
-rw-r--r--src/tests/apiv3/CMakeLists.txt24
-rw-r--r--src/tests/apiv3/test-apiv3.c198
-rw-r--r--src/tests/session/test-session.c2
-rw-r--r--src/verbose.c152
-rw-r--r--src/verbose.h50
-rw-r--r--src/wrap-json.c432
-rw-r--r--src/wrap-json.h19
79 files changed, 7882 insertions, 4010 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c789fca3..ed59ac0c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -24,16 +24,18 @@ ADD_DEFINITIONS(-DBINDING_INSTALL_DIR="${binding_install_dir}")
# Always add INFER_EXTENSION (more details in afb-hreq.c)
ADD_DEFINITIONS(-DINFER_EXTENSION)
-ADD_LIBRARY(afb-lib STATIC
+SET(AFB_LIB_SOURCES
afb-api.c
- afb-api-dyn.c
afb-api-so.c
- afb-api-so-v1.c
afb-api-so-v2.c
+ afb-api-so-v3.c
afb-api-so-vdyn.c
+ afb-api-v3.c
afb-api-ws.c
afb-apiset.c
afb-auth.c
+ afb-autoset.c
+ afb-calls.c
afb-common.c
afb-config.c
afb-context.c
@@ -66,6 +68,7 @@ ADD_LIBRARY(afb-lib STATIC
fdev-systemd.c
jobs.c
locale-root.c
+ pearson.c
process-name.c
sig-monitor.c
subpath.c
@@ -74,15 +77,26 @@ ADD_LIBRARY(afb-lib STATIC
wrap-json.c
)
+IF(INCLUDE_LEGACY_BINDING_V1)
+ ADD_DEFINITIONS(-DWITH_LEGACY_BINDING_V1)
+ SET(AFB_LIB_SOURCES ${AFB_LIB_SOURCES} afb-api-so-v1.c)
+ENDIF(INCLUDE_LEGACY_BINDING_V1)
+IF(INCLUDE_LEGACY_BINDING_VDYN)
+ ADD_DEFINITIONS(-DWITH_LEGACY_BINDING_VDYN)
+ SET(AFB_LIB_SOURCES ${AFB_LIB_SOURCES} afb-api-so-vdyn.c)
+ENDIF(INCLUDE_LEGACY_BINDING_VDYN)
+
IF(INCLUDE_DBUS_TRANSPARENCY)
ADD_DEFINITIONS(-DWITH_DBUS_TRANSPARENCY)
- TARGET_SOURCES(afb-lib PUBLIC afb-api-dbus.c)
+ SET(AFB_LIB_SOURCES ${AFB_LIB_SOURCES} afb-api-dbus.c)
ENDIF()
+ADD_LIBRARY(afb-lib STATIC ${AFB_LIB_SOURCES})
+
###########################################
# build and install afb-daemon
###########################################
-ADD_EXECUTABLE(afb-daemon main.c)
+ADD_EXECUTABLE(afb-daemon main-afb-daemon.c)
TARGET_LINK_LIBRARIES(afb-daemon
afb-lib
${link_libraries}
@@ -94,7 +108,7 @@ INSTALL(TARGETS afb-daemon
# build and install afb-daemon
###########################################
IF(INCLUDE_SUPERVISOR)
- ADD_EXECUTABLE(afs-supervisor afs-main.c afs-supervisor.c afs-discover.c afs-config.c)
+ ADD_EXECUTABLE(afs-supervisor main-afs-supervisor.c afs-supervisor.c afs-discover.c afs-config.c)
TARGET_LINK_LIBRARIES(afs-supervisor
afb-lib
${link_libraries}
@@ -124,7 +138,7 @@ INSTALL(FILES afb-wsj1.h afb-ws-client.h afb-proto-ws.h DESTINATION ${CMAKE_INST
###########################################
# build and install afb-client-demo
###########################################
-ADD_EXECUTABLE(afb-client-demo afb-client-demo.c)
+ADD_EXECUTABLE(afb-client-demo main-afb-client-demo.c)
TARGET_LINK_LIBRARIES(afb-client-demo
afbwsc
${link_libraries}
diff --git a/src/afb-api-dbus.c b/src/afb-api-dbus.c
index 98c26930..a1e15fd3 100644
--- a/src/afb-api-dbus.c
+++ b/src/afb-api-dbus.c
@@ -27,7 +27,7 @@
#include <systemd/sd-bus.h>
#include <json-c/json.h>
-#include <afb/afb-event.h>
+#include <afb/afb-event-x2.h>
#include "afb-systemd.h"
@@ -76,9 +76,6 @@ struct api_dbus
};
};
-#define RETOK 1
-#define RETERR 2
-
/******************* common part **********************************/
/*
@@ -113,7 +110,7 @@ static struct api_dbus *make_api_dbus_3(int system, const char *path, size_t pat
goto error2;
}
api->api++;
- if (!afb_api_is_valid_name(api->api, 1)) {
+ if (!afb_api_is_valid_name(api->api)) {
errno = EINVAL;
goto error2;
}
@@ -226,7 +223,7 @@ struct dbus_memo {
struct dbus_event
{
struct dbus_event *next;
- struct afb_eventid *eventid;
+ struct afb_event_x2 *event;
int id;
int refcount;
};
@@ -283,32 +280,19 @@ static int api_dbus_client_on_reply(sd_bus_message *message, void *userdata, sd_
{
int rc;
struct dbus_memo *memo;
- const char *first, *second;
- uint8_t type;
- uint32_t flags;
+ const char *json, *error, *info;
/* retrieve the recorded data */
memo = userdata;
/* get the answer */
- rc = sd_bus_message_read(message, "yssu", &type, &first, &second, &flags);
+ rc = sd_bus_message_read(message, "sss", &json, &error, &info);
if (rc < 0) {
/* failing to have the answer */
- afb_xreq_fail(memo->xreq, "error", "dbus error");
+ afb_xreq_reply(memo->xreq, NULL, "error", "dbus error");
} else {
/* report the answer */
- memo->xreq->context.flags = (unsigned)flags;
- switch(type) {
- case RETOK:
- afb_xreq_success(memo->xreq, json_tokener_parse(first), *second ? second : NULL);
- break;
- case RETERR:
- afb_xreq_fail(memo->xreq, first, *second ? second : NULL);
- break;
- default:
- afb_xreq_fail(memo->xreq, "error", "dbus link broken");
- break;
- }
+ afb_xreq_reply(memo->xreq, *json ? json_tokener_parse(json) : NULL, *error ? error : NULL, *info ? info : NULL);
}
api_dbus_client_memo_destroy(memo);
return 1;
@@ -322,24 +306,27 @@ static void api_dbus_client_call(void *closure, struct afb_xreq *xreq)
int rc;
struct dbus_memo *memo;
struct sd_bus_message *msg;
+ const char *creds;
/* create the recording data */
memo = api_dbus_client_memo_make(api, xreq);
if (memo == NULL) {
- afb_xreq_fail(xreq, "error", "out of memory");
+ afb_xreq_reply(memo->xreq, NULL, "error", "out of memory");
return;
}
/* creates the message */
msg = NULL;
- rc = sd_bus_message_new_method_call(api->sdbus, &msg, api->name, api->path, api->name, xreq->request.verb);
+ rc = sd_bus_message_new_method_call(api->sdbus, &msg, api->name, api->path, api->name, xreq->request.called_verb);
if (rc < 0)
goto error;
- rc = sd_bus_message_append(msg, "ssu",
+ creds = xreq_on_behalf_cred_export(xreq);
+ rc = sd_bus_message_append(msg, "ssus",
afb_xreq_raw(xreq, &size),
afb_session_uuid(xreq->context.session),
- (uint32_t)xreq->context.flags);
+ (uint32_t)xreq->context.flags,
+ creds ?: "");
if (rc < 0)
goto error;
@@ -355,7 +342,7 @@ static void api_dbus_client_call(void *closure, struct afb_xreq *xreq)
error:
/* if there was an error report it directly */
errno = -rc;
- afb_xreq_fail(xreq, "error", "dbus error");
+ afb_xreq_reply(memo->xreq, NULL, "error", "dbus error");
api_dbus_client_memo_destroy(memo);
end:
sd_bus_message_unref(msg);
@@ -382,7 +369,7 @@ static struct dbus_event *api_dbus_client_event_search(struct api_dbus *api, int
struct dbus_event *ev;
ev = api->client.events;
- while (ev != NULL && (ev->id != id || 0 != strcmp(afb_evt_eventid_fullname(ev->eventid), name)))
+ while (ev != NULL && (ev->id != id || 0 != strcmp(afb_evt_event_x2_fullname(ev->event), name)))
ev = ev->next;
return ev;
@@ -403,8 +390,8 @@ static void api_dbus_client_event_create(struct api_dbus *api, int id, const cha
/* no conflict, try to add it */
ev = malloc(sizeof *ev);
if (ev != NULL) {
- ev->eventid = afb_evt_eventid_create(name);
- if (ev->eventid == NULL)
+ ev->event = afb_evt_event_x2_create(name);
+ if (ev->event == NULL)
free(ev);
else {
ev->refcount = 1;
@@ -440,7 +427,7 @@ static void api_dbus_client_event_drop(struct api_dbus *api, int id, const char
*prv = ev->next;
/* destroys the event */
- afb_evt_eventid_unref(ev->eventid);
+ afb_evt_event_x2_unref(ev->event);
free(ev);
}
@@ -459,7 +446,7 @@ static void api_dbus_client_event_push(struct api_dbus *api, int id, const char
/* destroys the event */
object = json_tokener_parse(data);
- afb_evt_eventid_push(ev->eventid, object);
+ afb_evt_event_x2_push(ev->event, object);
}
/* subscribes an event */
@@ -484,7 +471,7 @@ static void api_dbus_client_event_subscribe(struct api_dbus *api, int id, const
}
/* subscribe the request to the event */
- rc = afb_xreq_subscribe(memo->xreq, ev->eventid);
+ rc = afb_xreq_subscribe(memo->xreq, ev->event);
if (rc < 0)
ERROR("can't subscribe: %m");
}
@@ -511,7 +498,7 @@ static void api_dbus_client_event_unsubscribe(struct api_dbus *api, int id, cons
}
/* unsubscribe the request from the event */
- rc = afb_xreq_unsubscribe(memo->xreq, ev->eventid);
+ rc = afb_xreq_unsubscribe(memo->xreq, ev->event);
if (rc < 0)
ERROR("can't unsubscribe: %m");
}
@@ -572,11 +559,11 @@ static struct afb_api_itf dbus_api_itf = {
};
/* adds a afb-dbus-service client api */
-int afb_api_dbus_add_client(const char *path, struct afb_apiset *apiset)
+int afb_api_dbus_add_client(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set)
{
int rc;
struct api_dbus *api;
- struct afb_api afb_api;
+ struct afb_api_item afb_api;
char *match;
/* create the dbus client api */
@@ -611,7 +598,7 @@ int afb_api_dbus_add_client(const char *path, struct afb_apiset *apiset)
afb_api.closure = api;
afb_api.itf = &dbus_api_itf;
afb_api.group = NULL;
- if (afb_apiset_add(apiset, api->api, afb_api) < 0)
+ if (afb_apiset_add(declare_set, api->api, afb_api) < 0)
goto error2;
return 0;
@@ -816,77 +803,51 @@ static struct json_object *dbus_req_json(struct afb_xreq *xreq)
return dreq->json;
}
-/* get the argument of the request of 'name' */
-static void dbus_req_reply(struct dbus_req *dreq, uint8_t type, const char *first, const char *second)
+void dbus_req_raw_reply(struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info)
{
+ struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq);
int rc;
- rc = sd_bus_reply_method_return(dreq->message,
- "yssu", type, first ? : "", second ? : "", (uint32_t)dreq->xreq.context.flags);
+
+ rc = sd_bus_reply_method_return(dreq->message, "sss",
+ obj ? json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN) : "",
+ error ? : "",
+ info ? : "");
if (rc < 0)
ERROR("sending the reply failed");
}
-static void dbus_req_success(struct afb_xreq *xreq, struct json_object *obj, const char *info)
-{
- struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq);
-
- dbus_req_reply(dreq, RETOK, json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN), info);
-}
-
-static void dbus_req_fail(struct afb_xreq *xreq, const char *status, const char *info)
-{
- struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq);
-
- dbus_req_reply(dreq, RETERR, status, info);
-}
-
static void afb_api_dbus_server_event_send(struct origin *origin, char order, const char *event, int eventid, const char *data, uint64_t msgid);
-static int dbus_req_subscribe(struct afb_xreq *xreq, struct afb_eventid *eventid)
+static int dbus_req_subscribe(struct afb_xreq *xreq, struct afb_event_x2 *event)
{
struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq);
uint64_t msgid;
int rc;
- rc = afb_evt_eventid_add_watch(dreq->listener->listener, eventid);
+ rc = afb_evt_event_x2_add_watch(dreq->listener->listener, event);
sd_bus_message_get_cookie(dreq->message, &msgid);
- afb_api_dbus_server_event_send(dreq->listener->origin, 'S', afb_evt_eventid_fullname(eventid), afb_evt_eventid_id(eventid), "", msgid);
+ afb_api_dbus_server_event_send(dreq->listener->origin, 'S', afb_evt_event_x2_fullname(event), afb_evt_event_x2_id(event), "", msgid);
return rc;
}
-static int dbus_req_unsubscribe(struct afb_xreq *xreq, struct afb_eventid *eventid)
+static int dbus_req_unsubscribe(struct afb_xreq *xreq, struct afb_event_x2 *event)
{
struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq);
uint64_t msgid;
int rc;
sd_bus_message_get_cookie(dreq->message, &msgid);
- afb_api_dbus_server_event_send(dreq->listener->origin, 'U', afb_evt_eventid_fullname(eventid), afb_evt_eventid_id(eventid), "", msgid);
- rc = afb_evt_eventid_remove_watch(dreq->listener->listener, eventid);
+ afb_api_dbus_server_event_send(dreq->listener->origin, 'U', afb_evt_event_x2_fullname(event), afb_evt_event_x2_id(event), "", msgid);
+ rc = afb_evt_event_x2_remove_watch(dreq->listener->listener, event);
return rc;
}
-static void dbus_req_subcall(
- struct afb_xreq *xreq,
- const char *api,
- const char *verb,
- struct json_object *args,
- void (*callback)(void*, int, struct json_object*),
- void *cb_closure)
-{
- ERROR("DBUS API doesn't support subcalls, info: %s/%s(%s)", api, verb, json_object_to_json_string(args));
- callback(cb_closure, 1, afb_msg_json_reply_error("error", "subcall isn't supported", NULL, NULL));
- json_object_put(args);
-}
-
const struct afb_xreq_query_itf afb_api_dbus_xreq_itf = {
.json = dbus_req_json,
- .success = dbus_req_success,
- .fail = dbus_req_fail,
+ .reply = dbus_req_raw_reply,
.unref = dbus_req_destroy,
.subscribe = dbus_req_subscribe,
.unsubscribe = dbus_req_unsubscribe,
- .subcall = dbus_req_subcall
};
/******************* server part **********************************/
@@ -954,6 +915,7 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd
int rc;
const char *method;
const char *uuid;
+ const char *creds;
struct dbus_req *dreq;
struct api_dbus *api = userdata;
uint32_t flags;
@@ -973,7 +935,7 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd
goto out_of_memory;
/* get the data */
- rc = sd_bus_message_read(message, "ssu", &dreq->request, &uuid, &flags);
+ rc = sd_bus_message_read(message, "ssus", &dreq->request, &uuid, &flags, &creds);
if (rc < 0) {
sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_SIGNATURE, "invalid signature");
goto error;
@@ -992,6 +954,7 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd
/* fulfill the request and emit it */
dreq->xreq.context.flags = flags;
+ dreq->xreq.cred = afb_cred_mixed_on_behalf_import(listener->origin->cred, uuid, creds && creds[0] ? creds : NULL);
dreq->message = sd_bus_message_ref(message);
dreq->json = json_tokener_parse(dreq->request);
if (dreq->json == NULL && strcmp(dreq->request, "null")) {
@@ -999,8 +962,8 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd
dreq->json = json_object_new_string(dreq->request);
}
dreq->listener = listener;
- dreq->xreq.request.api = api->api;
- dreq->xreq.request.verb = method;
+ dreq->xreq.request.called_api = api->api;
+ dreq->xreq.request.called_verb = method;
afb_xreq_process(&dreq->xreq, api->server.apiset);
return 1;
@@ -1012,7 +975,7 @@ error:
}
/* create the service */
-int afb_api_dbus_add_server(const char *path, struct afb_apiset *apiset)
+int afb_api_dbus_add_server(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set)
{
int rc;
struct api_dbus *api;
@@ -1040,7 +1003,7 @@ int afb_api_dbus_add_server(const char *path, struct afb_apiset *apiset)
INFO("afb service over dbus installed, name %s, path %s", api->name, api->path);
api->server.listener = afb_evt_listener_create(&evt_broadcast_itf, api);
- api->server.apiset = afb_apiset_addref(apiset);
+ api->server.apiset = afb_apiset_addref(call_set);
return 0;
error3:
sd_bus_release_name(api->sdbus, api->name);
diff --git a/src/afb-api-dbus.h b/src/afb-api-dbus.h
index 90f20c16..1c47685b 100644
--- a/src/afb-api-dbus.h
+++ b/src/afb-api-dbus.h
@@ -20,8 +20,8 @@
struct afb_req_itf;
-extern int afb_api_dbus_add_client(const char *path, struct afb_apiset *apiset);
+extern int afb_api_dbus_add_client(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set);
-extern int afb_api_dbus_add_server(const char *path, struct afb_apiset *apiset);
+extern int afb_api_dbus_add_server(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set);
diff --git a/src/afb-api-dyn.c b/src/afb-api-dyn.c
deleted file mode 100644
index c2d6cdc4..00000000
--- a/src/afb-api-dyn.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2016, 2017, 2018 "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.
- */
-
-#define _GNU_SOURCE
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <json-c/json.h>
-
-#define AFB_BINDING_VERSION 0
-#include <afb/afb-binding.h>
-
-#include "afb-api.h"
-#include "afb-api-dyn.h"
-#include "afb-apiset.h"
-#include "afb-auth.h"
-#include "afb-export.h"
-#include "afb-xreq.h"
-#include "verbose.h"
-
-/*
- * Description of a binding
- */
-struct afb_api_dyn {
- int count;
- struct afb_api_dyn_verb **verbs;
- const struct afb_verb_v2 *verbsv2;
- struct afb_export *export;
- char info[1];
-};
-
-void afb_api_dyn_set_verbs_v2(
- struct afb_api_dyn *dynapi,
- const struct afb_verb_v2 *verbs)
-{
- dynapi->verbsv2 = verbs;
-}
-
-int afb_api_dyn_add_verb(
- struct afb_api_dyn *dynapi,
- const char *verb,
- const char *info,
- void (*callback)(struct afb_request *request),
- void *vcbdata,
- const struct afb_auth *auth,
- uint32_t session)
-{
- struct afb_api_dyn_verb *v, **vv;
-
- afb_api_dyn_sub_verb(dynapi, verb);
-
- vv = realloc(dynapi->verbs, (1 + dynapi->count) * sizeof *vv);
- if (!vv)
- goto oom;
- dynapi->verbs = vv;
-
- v = malloc(sizeof *v + strlen(verb) + (info ? 1 + strlen(info) : 0));
- if (!v)
- goto oom;
-
- v->callback = callback;
- v->vcbdata = vcbdata;
- v->auth = auth;
- v->session = session;
-
- v->info = 1 + stpcpy(v->verb, verb);
- if (info)
- strcpy((char*)v->info, info);
- else
- v->info = NULL;
-
- dynapi->verbs[dynapi->count++] = v;
- return 0;
-oom:
- errno = ENOMEM;
- return -1;
-}
-
-int afb_api_dyn_sub_verb(
- struct afb_api_dyn *dynapi,
- const char *verb)
-{
- struct afb_api_dyn_verb *v;
- int i;
-
- /* look first in dyna mic verbs */
- for (i = 0 ; i < dynapi->count ; i++) {
- v = dynapi->verbs[i];
- if (!strcasecmp(v->verb, verb)) {
- if (i != --dynapi->count)
- dynapi->verbs[i] = dynapi->verbs[dynapi->count];
- free(v);
- return 0;
- }
- }
-
- errno = ENOENT;
- return -1;
-}
-
-static void call_cb(void *closure, struct afb_xreq *xreq)
-{
- struct afb_api_dyn *dynapi = closure;
- struct afb_api_dyn_verb **verbs, *v;
- const struct afb_verb_v2 *verbsv2;
- int i;
- const char *name;
-
- name = xreq->request.verb;
- xreq->request.dynapi = (void*)dynapi->export; /* hack: this avoids to export afb_export structure */
-
- /* look first in dyna mic verbs */
- verbs = dynapi->verbs;
- i = dynapi->count;
- while (i) {
- v = verbs[--i];
- if (!strcasecmp(v->verb, name)) {
- xreq->request.vcbdata = v->vcbdata;
- afb_xreq_call_verb_vdyn(xreq, verbs[i]);
- return;
- }
- }
-
- verbsv2 = dynapi->verbsv2;
- if (verbsv2) {
- while (verbsv2->verb) {
- if (strcasecmp(verbsv2->verb, name))
- verbsv2++;
- else {
- afb_xreq_call_verb_v2(xreq, verbsv2);
- return;
- }
- }
- }
-
- afb_xreq_fail_unknown_verb(xreq);
-}
-
-static int service_start_cb(void *closure, int share_session, int onneed, struct afb_apiset *apiset)
-{
- struct afb_api_dyn *dynapi = closure;
- return afb_export_start(dynapi->export, share_session, onneed, apiset);
-}
-
-static void update_hooks_cb(void *closure)
-{
- struct afb_api_dyn *dynapi = closure;
- afb_export_update_hook(dynapi->export);
-}
-
-static int get_verbosity_cb(void *closure)
-{
- struct afb_api_dyn *dynapi = closure;
- return afb_export_verbosity_get(dynapi->export);
-}
-
-static void set_verbosity_cb(void *closure, int level)
-{
- struct afb_api_dyn *dynapi = closure;
- afb_export_verbosity_set(dynapi->export, level);
-}
-
-static struct json_object *make_description_openAPIv3(struct afb_api_dyn *dynapi)
-{
- char buffer[256];
- struct afb_api_dyn_verb **iter, **end, *verb;
- struct json_object *r, *f, *a, *i, *p, *g;
-
- r = json_object_new_object();
- json_object_object_add(r, "openapi", json_object_new_string("3.0.0"));
-
- i = json_object_new_object();
- json_object_object_add(r, "info", i);
- json_object_object_add(i, "title", json_object_new_string(afb_export_apiname(dynapi->export)));
- json_object_object_add(i, "version", json_object_new_string("0.0.0"));
- json_object_object_add(i, "description", json_object_new_string(dynapi->info));
-
- p = json_object_new_object();
- json_object_object_add(r, "paths", p);
- iter = dynapi->verbs;
- end = iter + dynapi->count;
- while (iter != end) {
- verb = *iter++;
- buffer[0] = '/';
- strncpy(buffer + 1, verb->verb, sizeof buffer - 1);
- buffer[sizeof buffer - 1] = 0;
- f = json_object_new_object();
- json_object_object_add(p, buffer, f);
- g = json_object_new_object();
- json_object_object_add(f, "get", g);
-
- a = afb_auth_json_v2(verb->auth, verb->session);
- if (a)
- json_object_object_add(g, "x-permissions", a);
-
- a = json_object_new_object();
- json_object_object_add(g, "responses", a);
- f = json_object_new_object();
- json_object_object_add(a, "200", f);
- json_object_object_add(f, "description", json_object_new_string(verb->info?:verb->verb));
- }
- return r;
-}
-
-static struct json_object *describe_cb(void *closure)
-{
- struct afb_api_dyn *dynapi = closure;
- struct json_object *r = make_description_openAPIv3(dynapi);
- return r;
-}
-
-static struct afb_api_itf dyn_api_itf = {
- .call = call_cb,
- .service_start = service_start_cb,
- .update_hooks = update_hooks_cb,
- .get_verbosity = get_verbosity_cb,
- .set_verbosity = set_verbosity_cb,
- .describe = describe_cb
-};
-
-int afb_api_dyn_add(struct afb_apiset *apiset, const char *name, const char *info, int noconcurrency, int (*preinit)(void*, struct afb_dynapi*), void *closure)
-{
- int rc;
- struct afb_api_dyn *dynapi;
- struct afb_api afb_api;
- struct afb_export *export;
-
- INFO("Starting creation of dynamic API %s", name);
-
- /* allocates the description */
- info = info ?: "";
- dynapi = calloc(1, sizeof *dynapi + strlen(info));
- export = afb_export_create_vdyn(apiset, name, dynapi);
- if (!dynapi || !export) {
- ERROR("out of memory");
- goto error;
- }
- strcpy(dynapi->info, info);
- dynapi->export = export;
-
- /* preinit the api */
- rc = afb_export_preinit_vdyn(export, preinit, closure);
- if (rc < 0) {
- ERROR("dynamic api %s preinit function failed, ABORTING it!",
- afb_export_apiname(dynapi->export));
- goto error;
- }
-
- /* records the binding */
- afb_api.closure = dynapi;
- afb_api.itf = &dyn_api_itf;
- afb_api.group = noconcurrency ? dynapi : NULL;
- if (afb_apiset_add(apiset, afb_export_apiname(dynapi->export), afb_api) < 0) {
- ERROR("dynamic api %s can't be registered to set %s, ABORTING it!",
- afb_export_apiname(dynapi->export),
- afb_apiset_name(apiset));
- goto error;
- }
- INFO("binding %s added to set %s", afb_export_apiname(dynapi->export), afb_apiset_name(apiset));
- return 0;
-
-error:
- afb_export_destroy(export);
- free(dynapi);
-
- return -1;
-}
-
diff --git a/src/afb-api-dyn.h b/src/afb-api-dyn.h
deleted file mode 100644
index 107d944e..00000000
--- a/src/afb-api-dyn.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016, 2017, 2018 "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.
- */
-
-
-#pragma once
-
-struct afb_apiset;
-struct afb_dynapi;
-struct afb_auth;
-struct afb_request;
-struct afb_verb_v2;
-
-struct afb_api_dyn_verb
-{
- void (*callback)(struct afb_request *request);
- void *vcbdata;
- const struct afb_auth *auth;
- const char *info;
- int session;
- char verb[1];
-};
-
-struct afb_api_dyn;
-
-extern int afb_api_dyn_add(
- struct afb_apiset *apiset,
- const char *name,
- const char *info,
- int noconcurrency,
- int (*preinit)(void*, struct afb_dynapi*),
- void *closure);
-
-extern void afb_api_dyn_set_verbs_v2(
- struct afb_api_dyn *dynapi,
- const struct afb_verb_v2 *verbs);
-
-extern int afb_api_dyn_add_verb(
- struct afb_api_dyn *dynapi,
- const char *verb,
- const char *info,
- void (*callback)(struct afb_request *request),
- void *vcbdata,
- const struct afb_auth *auth,
- uint32_t session);
-
-extern int afb_api_dyn_sub_verb(
- struct afb_api_dyn *dynapi,
- const char *verb);
-
diff --git a/src/afb-api-so-v1.c b/src/afb-api-so-v1.c
index 985a113d..7db686d8 100644
--- a/src/afb-api-so-v1.c
+++ b/src/afb-api-so-v1.c
@@ -21,9 +21,9 @@
#include <string.h>
#include <dlfcn.h>
#include <assert.h>
+#include <stdarg.h>
#include <json-c/json.h>
-
#include <afb/afb-binding-v1.h>
#include "afb-api.h"
@@ -43,59 +43,24 @@ static const char afb_api_so_v1_register[] = "afbBindingV1Register";
static const char afb_api_so_v1_service_init[] = "afbBindingV1ServiceInit";
static const char afb_api_so_v1_service_event[] = "afbBindingV1ServiceEvent";
-/*
- * Description of a binding
- */
-struct api_so_v1 {
- struct afb_binding_v1 *binding; /* descriptor */
- void *handle; /* context of dlopen */
- struct afb_export *export; /* export */
-};
-
-static const struct afb_verb_desc_v1 *search(struct api_so_v1 *desc, const char *name)
+static const struct afb_verb_desc_v1 *search(struct afb_binding_v1 *binding, const char *name)
{
const struct afb_verb_desc_v1 *verb;
- verb = desc->binding->v1.verbs;
+ verb = binding->v1.verbs;
while (verb->name && strcasecmp(verb->name, name))
verb++;
return verb->name ? verb : NULL;
}
-static void call_cb(void *closure, struct afb_xreq *xreq)
+void afb_api_so_v1_process_call(struct afb_binding_v1 *binding, struct afb_xreq *xreq)
{
const struct afb_verb_desc_v1 *verb;
- struct api_so_v1 *desc = closure;
- xreq->request.dynapi = (void*)desc->export; /* hack: this avoids to export afb_export structure */
- verb = search(desc, xreq->request.verb);
+ verb = search(binding, xreq->request.called_verb);
afb_xreq_call_verb_v1(xreq, verb);
}
-static int service_start_cb(void *closure, int share_session, int onneed, struct afb_apiset *apiset)
-{
- struct api_so_v1 *desc = closure;
- return afb_export_start(desc->export, share_session, onneed, apiset);
-}
-
-static void update_hooks_cb(void *closure)
-{
- struct api_so_v1 *desc = closure;
- afb_export_update_hook(desc->export);
-}
-
-static int get_verbosity_cb(void *closure)
-{
- struct api_so_v1 *desc = closure;
- return afb_export_verbosity_get(desc->export);
-}
-
-static void set_verbosity_cb(void *closure, int level)
-{
- struct api_so_v1 *desc = closure;
- afb_export_verbosity_set(desc->export, level);
-}
-
static struct json_object *addperm(struct json_object *o, struct json_object *x)
{
struct json_object *a;
@@ -130,7 +95,7 @@ static struct json_object *addperm_key_valint(struct json_object *o, const char
return addperm_key_val(o, key, json_object_new_int(val));
}
-static struct json_object *make_description_openAPIv3(struct api_so_v1 *desc)
+struct json_object *afb_api_so_v1_make_description_openAPIv3(struct afb_binding_v1 *binding, const char *apiname)
{
char buffer[256];
const struct afb_verb_desc_v1 *verb;
@@ -141,13 +106,13 @@ static struct json_object *make_description_openAPIv3(struct api_so_v1 *desc)
i = json_object_new_object();
json_object_object_add(r, "info", i);
- json_object_object_add(i, "title", json_object_new_string(afb_export_apiname(desc->export)));
+ json_object_object_add(i, "title", json_object_new_string(apiname));
json_object_object_add(i, "version", json_object_new_string("0.0.0"));
- json_object_object_add(i, "description", json_object_new_string(desc->binding->v1.info ?: afb_export_apiname(desc->export)));
+ json_object_object_add(i, "description", json_object_new_string(binding->v1.info ?: apiname));
p = json_object_new_object();
json_object_object_add(r, "paths", p);
- verb = desc->binding->v1.verbs;
+ verb = binding->v1.verbs;
while (verb->name) {
buffer[0] = '/';
strncpy(buffer + 1, verb->name, sizeof buffer - 1);
@@ -158,14 +123,14 @@ static struct json_object *make_description_openAPIv3(struct api_so_v1 *desc)
json_object_object_add(f, "get", g);
a = NULL;
- if (verb->session & AFB_SESSION_CLOSE_V1)
+ if (verb->session & AFB_SESSION_CLOSE_X1)
a = addperm_key_valstr(a, "session", "close");
- if (verb->session & AFB_SESSION_CHECK_V1)
+ if (verb->session & AFB_SESSION_CHECK_X1)
a = addperm_key_valstr(a, "session", "check");
- if (verb->session & AFB_SESSION_RENEW_V1)
+ if (verb->session & AFB_SESSION_RENEW_X1)
a = addperm_key_valstr(a, "token", "refresh");
- if (verb->session & AFB_SESSION_LOA_MASK_V1)
- a = addperm_key_valint(a, "LOA", (verb->session >> AFB_SESSION_LOA_SHIFT_V1) & AFB_SESSION_LOA_MASK_V1);
+ if (verb->session & AFB_SESSION_LOA_MASK_X1)
+ a = addperm_key_valint(a, "LOA", (verb->session >> AFB_SESSION_LOA_SHIFT_X1) & AFB_SESSION_LOA_MASK_X1);
if (a)
json_object_object_add(g, "x-permissions", a);
@@ -179,95 +144,75 @@ static struct json_object *make_description_openAPIv3(struct api_so_v1 *desc)
return r;
}
-static struct json_object *describe_cb(void *closure)
+int afb_api_so_v1_add(const char *path, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set)
{
- struct api_so_v1 *desc = closure;
-
- return make_description_openAPIv3(desc);
-}
-
-static struct afb_api_itf so_v1_api_itf = {
- .call = call_cb,
- .service_start = service_start_cb,
- .update_hooks = update_hooks_cb,
- .get_verbosity = get_verbosity_cb,
- .set_verbosity = set_verbosity_cb,
- .describe = describe_cb
-};
-
-int afb_api_so_v1_add(const char *path, void *handle, struct afb_apiset *apiset)
-{
- struct api_so_v1 *desc;
+ struct afb_binding_v1 *binding; /* descriptor */
struct afb_binding_v1 *(*register_function) (const struct afb_binding_interface_v1 *interface);
- int (*init)(struct afb_service service);
+ int (*init)(struct afb_service_x1 service);
void (*onevent)(const char *event, struct json_object *object);
- struct afb_api afb_api;
struct afb_export *export;
/* retrieves the register function */
register_function = dlsym(handle, afb_api_so_v1_register);
if (!register_function)
return 0;
+
INFO("binding [%s] is a valid AFB binding V1", path);
/* allocates the description */
init = dlsym(handle, afb_api_so_v1_service_init);
onevent = dlsym(handle, afb_api_so_v1_service_event);
- export = afb_export_create_v1(apiset, path, init, onevent);
- desc = calloc(1, sizeof *desc);
- if (desc == NULL || export == NULL) {
- ERROR("out of memory");
+ export = afb_export_create_v1(declare_set, call_set, path, init, onevent);
+ if (export == NULL) {
+ ERROR("binding [%s] creation failure...", path);
goto error;
}
- desc->export = export;
- desc->handle = handle;
-
- /* init the binding */
- INFO("binding [%s] calling registering function %s", path, afb_api_so_v1_register);
- desc->binding = afb_export_register_v1(desc->export, register_function);
- if (desc->binding == NULL) {
- ERROR("binding [%s] register function failed. continuing...", path);
+ binding = afb_export_register_v1(export, register_function);
+ if (binding == NULL) {
+ ERROR("binding [%s] register failure...", path);
goto error;
}
/* check the returned structure */
- if (desc->binding->type != AFB_BINDING_VERSION_1) {
- ERROR("binding [%s] invalid type %d...", path, desc->binding->type);
+ if (binding->type != AFB_BINDING_VERSION_1) {
+ ERROR("binding [%s] invalid type %d...", path, binding->type);
goto error;
}
- if (desc->binding->v1.prefix == NULL || *desc->binding->v1.prefix == 0) {
+ if (binding->v1.prefix == NULL || *binding->v1.prefix == 0) {
ERROR("binding [%s] bad prefix...", path);
goto error;
}
- if (!afb_api_is_valid_name(desc->binding->v1.prefix, 1)) {
+ if (!afb_api_is_valid_name(binding->v1.prefix)) {
ERROR("binding [%s] invalid prefix...", path);
goto error;
}
- if (desc->binding->v1.info == NULL || *desc->binding->v1.info == 0) {
+ if (binding->v1.info == NULL || *binding->v1.info == 0) {
ERROR("binding [%s] bad description...", path);
goto error;
}
- if (desc->binding->v1.verbs == NULL) {
- ERROR("binding [%s] no APIs...", path);
+ if (binding->v1.verbs == NULL) {
+ ERROR("binding [%s] no verbs...", path);
goto error;
}
/* records the binding */
- if (!strcmp(path, afb_export_apiname(desc->export)))
- afb_export_rename(desc->export, desc->binding->v1.prefix);
- afb_api.closure = desc;
- afb_api.itf = &so_v1_api_itf;
- afb_api.group = NULL;
- if (afb_apiset_add(apiset, afb_export_apiname(desc->export), afb_api) < 0) {
+ if (!strcmp(path, afb_export_apiname(export))) {
+ if (afb_export_rename(export, binding->v1.prefix) < 0) {
+ ERROR("binding [%s] can't be renamed to %s", path, binding->v1.prefix);
+ goto error;
+ }
+ }
+
+ if (afb_export_declare(export, 0) < 0) {
ERROR("binding [%s] can't be registered...", path);
goto error;
}
- INFO("binding %s loaded with API prefix %s", path, afb_export_apiname(desc->export));
+ INFO("binding %s loaded with API prefix %s", path, afb_export_apiname(export));
+ afb_export_unref(export);
return 1;
error:
- afb_export_destroy(export);
- free(desc);
+ afb_export_unref(export);
return -1;
}
diff --git a/src/afb-api-so-v1.h b/src/afb-api-so-v1.h
index 42f18a19..ebe00950 100644
--- a/src/afb-api-so-v1.h
+++ b/src/afb-api-so-v1.h
@@ -18,4 +18,12 @@
#pragma once
-extern int afb_api_so_v1_add(const char *path, void *handle, struct afb_apiset *apiset);
+struct afb_apiset;
+struct afb_binding_v1;
+struct afb_xreq;
+struct json_object;
+
+extern int afb_api_so_v1_add(const char *path, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set);
+
+extern void afb_api_so_v1_process_call(struct afb_binding_v1 *binding, struct afb_xreq *xreq);
+extern struct json_object *afb_api_so_v1_make_description_openAPIv3(struct afb_binding_v1 *binding, const char *apiname);
diff --git a/src/afb-api-so-v2.c b/src/afb-api-so-v2.c
index fb901f58..a13c00e4 100644
--- a/src/afb-api-so-v2.c
+++ b/src/afb-api-so-v2.c
@@ -21,9 +21,10 @@
#include <string.h>
#include <dlfcn.h>
#include <assert.h>
+#include <stdarg.h>
-#include <afb/afb-binding-v2.h>
#include <json-c/json.h>
+#include <afb/afb-binding-v2.h>
#include "afb-api.h"
#include "afb-api-so-v2.h"
@@ -42,78 +43,50 @@
static const char afb_api_so_v2_descriptor[] = "afbBindingV2";
static const char afb_api_so_v2_data[] = "afbBindingV2data";
-/*
- * Description of a binding
- */
-struct api_so_v2 {
- const struct afb_binding_v2 *binding; /* descriptor */
- void *handle; /* context of dlopen */
- struct afb_export *export; /* exportations */
-};
-
-static const struct afb_verb_v2 *search(struct api_so_v2 *desc, const char *name)
+static const struct afb_verb_v2 *search(const struct afb_binding_v2 *binding, const char *name)
{
const struct afb_verb_v2 *verb;
- verb = desc->binding->verbs;
+ verb = binding->verbs;
while (verb->verb && strcasecmp(verb->verb, name))
verb++;
return verb->verb ? verb : NULL;
return NULL;
}
-static void call_cb(void *closure, struct afb_xreq *xreq)
+void afb_api_so_v2_process_call(const struct afb_binding_v2 *binding, struct afb_xreq *xreq)
{
- struct api_so_v2 *desc = closure;
const struct afb_verb_v2 *verb;
- xreq->request.dynapi = (void*)desc->export; /* hack: this avoids to export afb_export structure */
- verb = search(desc, xreq->request.verb);
+ verb = search(binding, xreq->request.called_verb);
afb_xreq_call_verb_v2(xreq, verb);
}
-static int service_start_cb(void *closure, int share_session, int onneed, struct afb_apiset *apiset)
-{
- struct api_so_v2 *desc = closure;
- return afb_export_start(desc->export, share_session, onneed, apiset);
-}
-
-static void update_hooks_cb(void *closure)
-{
- struct api_so_v2 *desc = closure;
- afb_export_update_hook(desc->export);
-}
-
-static int get_verbosity_cb(void *closure)
-{
- struct api_so_v2 *desc = closure;
- return afb_export_verbosity_get(desc->export);
-}
-
-static void set_verbosity_cb(void *closure, int level)
-{
- struct api_so_v2 *desc = closure;
- afb_export_verbosity_set(desc->export, level);
-}
-
-static struct json_object *make_description_openAPIv3(struct api_so_v2 *desc)
+struct json_object *afb_api_so_v2_make_description_openAPIv3(const struct afb_binding_v2 *binding, const char *apiname)
{
char buffer[256];
const struct afb_verb_v2 *verb;
struct json_object *r, *f, *a, *i, *p, *g;
+
+ if (binding->specification) {
+ r = json_tokener_parse(binding->specification);
+ if (r)
+ return r;
+ }
+
r = json_object_new_object();
json_object_object_add(r, "openapi", json_object_new_string("3.0.0"));
i = json_object_new_object();
json_object_object_add(r, "info", i);
- json_object_object_add(i, "title", json_object_new_string(afb_export_apiname(desc->export)));
+ json_object_object_add(i, "title", json_object_new_string(apiname));
json_object_object_add(i, "version", json_object_new_string("0.0.0"));
- json_object_object_add(i, "description", json_object_new_string(desc->binding->info ?: afb_export_apiname(desc->export)));
+ json_object_object_add(i, "description", json_object_new_string(binding->info ?: apiname));
p = json_object_new_object();
json_object_object_add(r, "paths", p);
- verb = desc->binding->verbs;
+ verb = binding->verbs;
while (verb->verb) {
buffer[0] = '/';
strncpy(buffer + 1, verb->verb, sizeof buffer - 1);
@@ -137,29 +110,9 @@ static struct json_object *make_description_openAPIv3(struct api_so_v2 *desc)
return r;
}
-static struct json_object *describe_cb(void *closure)
-{
- struct api_so_v2 *desc = closure;
- struct json_object *r = desc->binding->specification ? json_tokener_parse(desc->binding->specification) : NULL;
- if (!r)
- r = make_description_openAPIv3(desc);
- return r;
-}
-
-static struct afb_api_itf so_v2_api_itf = {
- .call = call_cb,
- .service_start = service_start_cb,
- .update_hooks = update_hooks_cb,
- .get_verbosity = get_verbosity_cb,
- .set_verbosity = set_verbosity_cb,
- .describe = describe_cb
-};
-
-int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle, struct afb_apiset *apiset, struct afb_binding_data_v2 *data)
+int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set, struct afb_binding_data_v2 *data)
{
int rc;
- struct api_so_v2 *desc;
- struct afb_api afb_api;
struct afb_export *export;
/* basic checks */
@@ -169,45 +122,38 @@ int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle
assert(data);
/* allocates the description */
- export = afb_export_create_v2(apiset, binding->api, data, binding->init, binding->onevent);
- desc = calloc(1, sizeof *desc);
- if (!desc || !export) {
+ export = afb_export_create_v2(declare_set, call_set, binding->api, binding, data, binding->init, binding->onevent);
+ if (!export) {
ERROR("out of memory");
goto error;
}
- desc->binding = binding;
- desc->handle = handle;
- desc->export = export;
+ /* records the binding */
+ if (afb_export_declare(export, binding->noconcurrency) < 0) {
+ ERROR("binding %s can't be registered to set %s...", afb_export_apiname(export), afb_apiset_name(declare_set));
+ goto error;
+ }
/* init the binding */
if (binding->preinit) {
INFO("binding %s calling preinit function", binding->api);
rc = binding->preinit();
if (rc < 0) {
- ERROR("binding %s preinit function failed...", afb_export_apiname(desc->export));
+ ERROR("binding %s preinit function failed...", afb_export_apiname(export));
+ afb_export_undeclare(export);
goto error;
}
}
- /* records the binding */
- afb_api.closure = desc;
- afb_api.itf = &so_v2_api_itf;
- afb_api.group = binding->noconcurrency ? export : NULL;
- if (afb_apiset_add(apiset, afb_export_apiname(desc->export), afb_api) < 0) {
- ERROR("binding %s can't be registered to set %s...", afb_export_apiname(desc->export), afb_apiset_name(apiset));
- goto error;
- }
- INFO("binding %s added to set %s", afb_export_apiname(desc->export), afb_apiset_name(apiset));
+ INFO("binding %s added to set %s", afb_export_apiname(export), afb_apiset_name(declare_set));
return 1;
error:
- afb_export_destroy(export);
- free(desc);
+ afb_export_unref(export);
return -1;
}
-int afb_api_so_v2_add(const char *path, void *handle, struct afb_apiset *apiset)
+int afb_api_so_v2_add(const char *path, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set)
{
const struct afb_binding_v2 *binding;
struct afb_binding_data_v2 *data;
@@ -230,22 +176,17 @@ int afb_api_so_v2_add(const char *path, void *handle, struct afb_apiset *apiset)
ERROR("binding [%s] bad api name...", path);
goto error;
}
- if (!afb_api_is_valid_name(binding->api, 1)) {
+ if (!afb_api_is_valid_name(binding->api)) {
ERROR("binding [%s] invalid api name...", path);
goto error;
}
-#if 0
- if (binding->specification == NULL || *binding->specification == 0) {
- ERROR("binding [%s] bad specification...", path);
- goto error;
- }
-#endif
+
if (binding->verbs == NULL) {
ERROR("binding [%s] no verbs...", path);
goto error;
}
- return afb_api_so_v2_add_binding(binding, handle, apiset, data);
+ return afb_api_so_v2_add_binding(binding, handle, declare_set, call_set, data);
error:
return -1;
diff --git a/src/afb-api-so-v2.h b/src/afb-api-so-v2.h
index 87cd80d5..d53206d3 100644
--- a/src/afb-api-so-v2.h
+++ b/src/afb-api-so-v2.h
@@ -21,6 +21,11 @@
struct afb_apiset;
struct afb_binding_v2;
struct afb_binding_data_v2;
+struct afb_xreq;
+struct json_object;
-extern int afb_api_so_v2_add(const char *path, void *handle, struct afb_apiset *apiset);
-extern int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle, struct afb_apiset *apiset, struct afb_binding_data_v2 *data);
+extern int afb_api_so_v2_add(const char *path, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set);
+extern int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set, struct afb_binding_data_v2 *data);
+
+extern void afb_api_so_v2_process_call(const struct afb_binding_v2 *binding, struct afb_xreq *xreq);
+extern struct json_object *afb_api_so_v2_make_description_openAPIv3(const struct afb_binding_v2 *binding, const char *apiname);
diff --git a/src/afb-api-so-v3.c b/src/afb-api-so-v3.c
new file mode 100644
index 00000000..415c13d9
--- /dev/null
+++ b/src/afb-api-so-v3.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 "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.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include <json-c/json.h>
+#include <afb/afb-binding-v3.h>
+
+#include "afb-api.h"
+#include "afb-api-so-v3.h"
+#include "afb-api-v3.h"
+#include "afb-apiset.h"
+#include "afb-export.h"
+#include "verbose.h"
+
+/*
+ * names of symbols
+ */
+static const char afb_api_so_v3_desc[] = "afbBindingV3";
+static const char afb_api_so_v3_root[] = "afbBindingV3root";
+static const char afb_api_so_v3_entry[] = "afbBindingV3entry";
+
+struct args
+{
+ struct afb_api_x3 **root;
+ const struct afb_binding_v3 *desc;
+ int (*entry)(struct afb_api_x3 *);
+};
+
+static int init(void *closure, struct afb_api_x3 *api)
+{
+ const struct args *a = closure;
+ int rc = 0;
+
+ *a->root = api;
+ if (a->desc) {
+ api->userdata = a->desc->userdata;
+ rc = afb_api_v3_set_binding_fields(a->desc, api);
+ }
+
+ if (rc >= 0 && a->entry)
+ rc = a->entry(api);
+
+ if (rc >= 0)
+ afb_api_x3_seal(api);
+
+ return rc;
+}
+
+int afb_api_so_v3_add(const char *path, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set)
+{
+ struct args a;
+ struct afb_api_v3 *api;
+ struct afb_export *export;
+
+ /* retrieves the register function */
+ a.root = dlsym(handle, afb_api_so_v3_root);
+ a.desc = dlsym(handle, afb_api_so_v3_desc);
+ a.entry = dlsym(handle, afb_api_so_v3_entry);
+ if (!a.root && !a.desc && !a.entry)
+ return 0;
+
+ INFO("binding [%s] looks like an AFB binding V3", path);
+
+ /* basic checks */
+ if (!a.root) {
+ ERROR("binding [%s] incomplete symbol set: %s is missing",
+ path, afb_api_so_v3_root);
+ goto error;
+ }
+ if (a.desc) {
+ if (a.desc->api == NULL || *a.desc->api == 0) {
+ ERROR("binding [%s] bad api name...", path);
+ goto error;
+ }
+ if (!afb_api_is_valid_name(a.desc->api)) {
+ ERROR("binding [%s] invalid api name...", path);
+ goto error;
+ }
+ if (!a.entry)
+ a.entry = a.desc->preinit;
+ else if (a.desc->preinit) {
+ ERROR("binding [%s] clash: you can't define %s and %s.preinit, choose only one",
+ path, afb_api_so_v3_entry, afb_api_so_v3_desc);
+ goto error;
+ }
+
+ api = afb_api_v3_create(declare_set, call_set, a.desc->api, a.desc->info, a.desc->noconcurrency, init, &a, 0);
+ if (api)
+ return 1;
+ } else {
+ if (!a.entry) {
+ ERROR("binding [%s] incomplete symbol set: %s is missing",
+ path, afb_api_so_v3_entry);
+ goto error;
+ }
+
+ export = afb_export_create_none_for_path(declare_set, call_set, path, init, &a);
+ if (export)
+ return 1;
+ }
+
+ ERROR("binding [%s] initialisation failed", path);
+
+error:
+ return -1;
+}
+
diff --git a/src/afb-api-so-v3.h b/src/afb-api-so-v3.h
new file mode 100644
index 00000000..52ec22ac
--- /dev/null
+++ b/src/afb-api-so-v3.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2018 "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.
+ */
+
+
+#pragma once
+
+struct afb_apiset;
+
+extern int afb_api_so_v3_add(const char *path, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set);
diff --git a/src/afb-api-so-vdyn.c b/src/afb-api-so-vdyn.c
index 300aa130..17344945 100644
--- a/src/afb-api-so-vdyn.c
+++ b/src/afb-api-so-vdyn.c
@@ -20,6 +20,10 @@
#include <stdlib.h>
#include <dlfcn.h>
+#define AFB_BINDING_VERSION 0
+#include <afb/afb-binding.h>
+
+#include "afb-api-so-v3.h"
#include "afb-api-so-vdyn.h"
#include "afb-export.h"
#include "verbose.h"
@@ -29,19 +33,15 @@
*/
static const char afb_api_so_vdyn_entry[] = "afbBindingVdyn";
-/*
- * Description of a binding
- */
-static int vdyn_preinit(void *closure, struct afb_dynapi *dynapi)
+static int preinit(void *closure, struct afb_api_x3 *api)
{
- int (*entry)(struct afb_dynapi*) = closure;
- return entry(dynapi);
+ int (*entry)(struct afb_api_x3*) = closure;
+ return entry(api);
}
-int afb_api_so_vdyn_add(const char *path, void *handle, struct afb_apiset *apiset)
+int afb_api_so_vdyn_add(const char *path, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set)
{
- int rc;
- int (*entry)(void*, struct afb_dynapi*);
+ int (*entry)(struct afb_api_x3*);
struct afb_export *export;
entry = dlsym(handle, afb_api_so_vdyn_entry);
@@ -50,15 +50,12 @@ int afb_api_so_vdyn_add(const char *path, void *handle, struct afb_apiset *apise
INFO("binding [%s] looks like an AFB binding Vdyn", path);
- export = afb_export_create_vdyn(apiset, path, NULL);
+ export = afb_export_create_none_for_path(declare_set, call_set, path, preinit, entry);
if (!export) {
- ERROR("can't create export for %s", path);
+ INFO("binding [%s] creation failed", path);
return -1;
}
- INFO("binding [%s] calling dynamic initialisation %s", path, afb_api_so_vdyn_entry);
- rc = afb_export_preinit_vdyn(export, vdyn_preinit, entry);
- afb_export_destroy(export);
- return rc < 0 ? rc : 1;
+ return 1;
}
diff --git a/src/afb-api-so-vdyn.h b/src/afb-api-so-vdyn.h
index 05d96235..d8a43f75 100644
--- a/src/afb-api-so-vdyn.h
+++ b/src/afb-api-so-vdyn.h
@@ -20,4 +20,4 @@
struct afb_apiset;
-extern int afb_api_so_vdyn_add(const char *path, void *handle, struct afb_apiset *apiset);
+extern int afb_api_so_vdyn_add(const char *path, void *handle, struct afb_apiset *declare_set, struct afb_apiset * call_set);
diff --git a/src/afb-api-so.c b/src/afb-api-so.c
index 87916cbb..3167ffad 100644
--- a/src/afb-api-so.c
+++ b/src/afb-api-so.c
@@ -25,12 +25,18 @@
#include <sys/stat.h>
#include "afb-api-so.h"
-#include "afb-api-so-v1.h"
#include "afb-api-so-v2.h"
-#include "afb-api-so-vdyn.h"
+#include "afb-api-so-v3.h"
#include "verbose.h"
#include "sig-monitor.h"
+#if defined(WITH_LEGACY_BINDING_V1)
+# include "afb-api-so-v1.h"
+#endif
+#if defined(WITH_LEGACY_BINDING_VDYN)
+# include "afb-api-so-vdyn.h"
+#endif
+
struct safe_dlopen
{
const char *path;
@@ -59,8 +65,9 @@ static void *safe_dlopen(const char *filename, int flags)
return sd.handle;
}
-static int load_binding(const char *path, int force, struct afb_apiset *apiset)
+static int load_binding(const char *path, int force, struct afb_apiset *declare_set, struct afb_apiset * call_set)
{
+ int obsolete = 0;
int rc;
void *handle;
@@ -76,7 +83,16 @@ static int load_binding(const char *path, int force, struct afb_apiset *apiset)
}
/* try the version 2 */
- rc = afb_api_so_v2_add(path, handle, apiset);
+ rc = afb_api_so_v3_add(path, handle, declare_set, call_set);
+ if (rc < 0) {
+ /* error when loading a valid v3 binding */
+ goto error2;
+ }
+ if (rc)
+ return 0; /* yes version 2 */
+
+ /* try the version 2 */
+ rc = afb_api_so_v2_add(path, handle, declare_set, call_set);
if (rc < 0) {
/* error when loading a valid v2 binding */
goto error2;
@@ -84,29 +100,41 @@ static int load_binding(const char *path, int force, struct afb_apiset *apiset)
if (rc)
return 0; /* yes version 2 */
+#if defined(WITH_LEGACY_BINDING_VDYN)
/* try the version dyn */
- rc = afb_api_so_vdyn_add(path, handle, apiset);
+ rc = afb_api_so_vdyn_add(path, handle, declare_set, call_set);
if (rc < 0) {
/* error when loading a valid dyn binding */
goto error2;
}
if (rc)
return 0; /* yes version dyn */
+#else
+ if (dlsym(handle, "afbBindingVdyn")) {
+ WARNING("binding [%s]: version DYN not supported", path);
+ obsolete = 1;
+ }
+#endif
+#if defined(WITH_LEGACY_BINDING_V1)
/* try the version 1 */
- rc = afb_api_so_v1_add(path, handle, apiset);
+ rc = afb_api_so_v1_add(path, handle, declare_set, call_set);
if (rc < 0) {
/* error when loading a valid v1 binding */
goto error2;
}
if (rc)
return 0; /* yes version 1 */
+#else
+ if (dlsym(handle, "afbBindingV1Register")) {
+ WARNING("binding [%s]: version 1 not supported", path);
+ obsolete = 1;
+ }
+#endif
/* not a valid binding */
- if (force)
- ERROR("binding [%s] is not an AFB binding", path);
- else
- INFO("binding [%s] is not an AFB binding", path);
+ _VERBOSE_(force ? Log_Level_Error : Log_Level_Info, "binding [%s] %s",
+ path, obsolete ? "is obsolete" : "isn't an AFB binding");
error2:
dlclose(handle);
@@ -115,12 +143,12 @@ error:
}
-int afb_api_so_add_binding(const char *path, struct afb_apiset *apiset)
+int afb_api_so_add_binding(const char *path, struct afb_apiset *declare_set, struct afb_apiset * call_set)
{
- return load_binding(path, 1, apiset);
+ return load_binding(path, 1, declare_set, call_set);
}
-static int adddirs(char path[PATH_MAX], size_t end, struct afb_apiset *apiset, int failstops)
+static int adddirs(char path[PATH_MAX], size_t end, struct afb_apiset *declare_set, struct afb_apiset * call_set, int failstops)
{
DIR *dir;
struct dirent *dent;
@@ -159,12 +187,12 @@ static int adddirs(char path[PATH_MAX], size_t end, struct afb_apiset *apiset, i
Exclude from the search of bindings any
directory starting with a dot (.) by default.
-It is possible to reactivate the prvious behaviour
+It is possible to reactivate the prvious behaviour
by defining the following preprocessor variables
- AFB_API_SO_ACCEPT_DOT_PREFIXED_DIRS
- When this variable is defined, the directories
+ When this variable is defined, the directories
starting with a dot are searched except
if their name is "." or ".." or ".debug"
@@ -181,7 +209,7 @@ This change is intended to definitely solve the issue
SPEC-662. Yocto installed the debugging symbols in the
subdirectory .debug. For example the binding.so also
had a .debug/binding.so file attached. Opening that
-debug file made dlopen crashing.
+debug file made dlopen crashing.
See https://sourceware.org/bugzilla/show_bug.cgi?id=22101
*/
#if !defined(AFB_API_SO_ACCEPT_DOT_PREFIXED_DIRS) /* not defined by default */
@@ -203,13 +231,13 @@ See https://sourceware.org/bugzilla/show_bug.cgi?id=22101
#endif
}
memcpy(&path[end], dent->d_name, len+1);
- rc = adddirs(path, end+len, apiset, failstops);
+ rc = adddirs(path, end+len, declare_set, call_set, failstops);
} else if (dent->d_type == DT_REG) {
/* case of files */
if (memcmp(&dent->d_name[len - 3], ".so", 4))
continue;
memcpy(&path[end], dent->d_name, len+1);
- rc = load_binding(path, 0, apiset);
+ rc = load_binding(path, 0, declare_set, call_set);
}
if (rc < 0 && failstops) {
closedir(dir);
@@ -220,7 +248,7 @@ See https://sourceware.org/bugzilla/show_bug.cgi?id=22101
return 0;
}
-int afb_api_so_add_directory(const char *path, struct afb_apiset *apiset, int failstops)
+int afb_api_so_add_directory(const char *path, struct afb_apiset *declare_set, struct afb_apiset * call_set, int failstops)
{
size_t length;
char buffer[PATH_MAX];
@@ -232,10 +260,10 @@ int afb_api_so_add_directory(const char *path, struct afb_apiset *apiset, int fa
}
memcpy(buffer, path, length + 1);
- return adddirs(buffer, length, apiset, failstops);
+ return adddirs(buffer, length, declare_set, call_set, failstops);
}
-int afb_api_so_add_path(const char *path, struct afb_apiset *apiset, int failstops)
+int afb_api_so_add_path(const char *path, struct afb_apiset *declare_set, struct afb_apiset * call_set, int failstops)
{
struct stat st;
int rc;
@@ -244,15 +272,15 @@ int afb_api_so_add_path(const char *path, struct afb_apiset *apiset, int failsto
if (rc < 0)
ERROR("Invalid binding path [%s]: %m", path);
else if (S_ISDIR(st.st_mode))
- rc = afb_api_so_add_directory(path, apiset, failstops);
+ rc = afb_api_so_add_directory(path, declare_set, call_set, failstops);
else if (strstr(path, ".so"))
- rc = load_binding(path, 0, apiset);
+ rc = load_binding(path, 0, declare_set, call_set);
else
INFO("not a binding [%s], skipped", path);
return rc;
}
-int afb_api_so_add_pathset(const char *pathset, struct afb_apiset *apiset, int failstops)
+int afb_api_so_add_pathset(const char *pathset, struct afb_apiset *declare_set, struct afb_apiset * call_set, int failstops)
{
static char sep[] = ":";
char *ps, *p;
@@ -263,19 +291,19 @@ int afb_api_so_add_pathset(const char *pathset, struct afb_apiset *apiset, int f
p = strsep(&ps, sep);
if (!p)
return 0;
- rc = afb_api_so_add_path(p, apiset, failstops);
+ rc = afb_api_so_add_path(p, declare_set, call_set, failstops);
if (rc < 0)
return rc;
}
}
-int afb_api_so_add_pathset_fails(const char *pathset, struct afb_apiset *apiset)
+int afb_api_so_add_pathset_fails(const char *pathset, struct afb_apiset *declare_set, struct afb_apiset * call_set)
{
- return afb_api_so_add_pathset(pathset, apiset, 1);
+ return afb_api_so_add_pathset(pathset, declare_set, call_set, 1);
}
-int afb_api_so_add_pathset_nofails(const char *pathset, struct afb_apiset *apiset)
+int afb_api_so_add_pathset_nofails(const char *pathset, struct afb_apiset *declare_set, struct afb_apiset * call_set)
{
- return afb_api_so_add_pathset(pathset, apiset, 0);
+ return afb_api_so_add_pathset(pathset, declare_set, call_set, 0);
}
diff --git a/src/afb-api-so.h b/src/afb-api-so.h
index d37f77c6..e6527469 100644
--- a/src/afb-api-so.h
+++ b/src/afb-api-so.h
@@ -20,15 +20,15 @@
struct afb_apiset;
-extern int afb_api_so_add_binding(const char *path, struct afb_apiset *apiset);
+extern int afb_api_so_add_binding(const char *path, struct afb_apiset *declare_set, struct afb_apiset * call_set);
-extern int afb_api_so_add_directory(const char *path, struct afb_apiset *apiset, int failstops);
+extern int afb_api_so_add_directory(const char *path, struct afb_apiset *declare_set, struct afb_apiset * call_set, int failstops);
-extern int afb_api_so_add_path(const char *path, struct afb_apiset *apiset, int failstops);
+extern int afb_api_so_add_path(const char *path, struct afb_apiset *declare_set, struct afb_apiset * call_set, int failstops);
-extern int afb_api_so_add_pathset(const char *pathset, struct afb_apiset *apiset, int failstops);
+extern int afb_api_so_add_pathset(const char *pathset, struct afb_apiset *declare_set, struct afb_apiset * call_set, int failstops);
-extern int afb_api_so_add_pathset_fails(const char *pathset, struct afb_apiset *apiset);
-extern int afb_api_so_add_pathset_nofails(const char *pathset, struct afb_apiset *apiset);
+extern int afb_api_so_add_pathset_fails(const char *pathset, struct afb_apiset *declare_set, struct afb_apiset * call_set);
+extern int afb_api_so_add_pathset_nofails(const char *pathset, struct afb_apiset *declare_set, struct afb_apiset * call_set);
diff --git a/src/afb-api-v3.c b/src/afb-api-v3.c
new file mode 100644
index 00000000..8c755f94
--- /dev/null
+++ b/src/afb-api-v3.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2016, 2017, 2018 "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.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <fnmatch.h>
+
+#include <json-c/json.h>
+
+#define AFB_BINDING_VERSION 0
+#include <afb/afb-binding.h>
+
+#include "afb-api.h"
+#include "afb-api-v3.h"
+#include "afb-apiset.h"
+#include "afb-auth.h"
+#include "afb-export.h"
+#include "afb-xreq.h"
+#include "verbose.h"
+
+/*
+ * Description of a binding
+ */
+struct afb_api_v3 {
+ int refcount;
+ int count;
+ struct afb_verb_v3 **verbs;
+ const struct afb_verb_v2 *verbsv2;
+ const struct afb_verb_v3 *verbsv3;
+ struct afb_export *export;
+ const char *info;
+};
+
+static const char nulchar = 0;
+
+static int verb_name_compare(const struct afb_verb_v3 *verb, const char *name)
+{
+ return verb->glob
+ ? fnmatch(verb->verb, name, FNM_NOESCAPE|FNM_PATHNAME|FNM_CASEFOLD|FNM_PERIOD)
+ : strcasecmp(verb->verb, name);
+}
+
+static struct afb_verb_v3 *search_dynamic_verb(struct afb_api_v3 *api, const char *name)
+{
+ struct afb_verb_v3 **v, **e, *i;
+
+ v = api->verbs;
+ e = &v[api->count];
+ while (v != e) {
+ i = *v;
+ if (!verb_name_compare(i, name))
+ return i;
+ v++;
+ }
+ return 0;
+}
+
+void afb_api_v3_process_call(struct afb_api_v3 *api, struct afb_xreq *xreq)
+{
+ const struct afb_verb_v3 *verbsv3;
+ const struct afb_verb_v2 *verbsv2;
+ const char *name;
+
+ name = xreq->request.called_verb;
+
+ /* look first in dynamic set */
+ verbsv3 = search_dynamic_verb(api, name);
+ if (!verbsv3) {
+ /* look then in static set */
+ verbsv3 = api->verbsv3;
+ while (verbsv3) {
+ if (!verbsv3->verb)
+ verbsv3 = 0;
+ else if (!verb_name_compare(verbsv3, name))
+ break;
+ else
+ verbsv3++;
+ }
+ }
+ /* is it a v3 verb ? */
+ if (verbsv3) {
+ /* yes */
+ xreq->request.vcbdata = verbsv3->vcbdata;
+ afb_xreq_call_verb_v3(xreq, verbsv3);
+ return;
+ }
+
+ /* look in legacy set */
+ verbsv2 = api->verbsv2;
+ if (verbsv2) {
+ while (verbsv2->verb) {
+ if (strcasecmp(verbsv2->verb, name))
+ verbsv2++;
+ else {
+ afb_xreq_call_verb_v2(xreq, verbsv2);
+ return;
+ }
+ }
+ }
+
+ afb_xreq_reply_unknown_verb(xreq);
+}
+
+struct json_object *afb_api_v3_make_description_openAPIv3(struct afb_api_v3 *api, const char *apiname)
+{
+ char buffer[256];
+ struct afb_verb_v3 **iter, **end, *verb;
+ struct json_object *r, *f, *a, *i, *p, *g;
+
+ r = json_object_new_object();
+ json_object_object_add(r, "openapi", json_object_new_string("3.0.0"));
+
+ i = json_object_new_object();
+ json_object_object_add(r, "info", i);
+ json_object_object_add(i, "title", json_object_new_string(apiname));
+ json_object_object_add(i, "version", json_object_new_string("0.0.0"));
+ json_object_object_add(i, "description", json_object_new_string(api->info));
+
+ p = json_object_new_object();
+ json_object_object_add(r, "paths", p);
+ iter = api->verbs;
+ end = iter + api->count;
+ while (iter != end) {
+ verb = *iter++;
+ buffer[0] = '/';
+ strncpy(buffer + 1, verb->verb, sizeof buffer - 1);
+ buffer[sizeof buffer - 1] = 0;
+ f = json_object_new_object();
+ json_object_object_add(p, buffer, f);
+ g = json_object_new_object();
+ json_object_object_add(f, "get", g);
+
+ a = afb_auth_json_v2(verb->auth, verb->session);
+ if (a)
+ json_object_object_add(g, "x-permissions", a);
+
+ a = json_object_new_object();
+ json_object_object_add(g, "responses", a);
+ f = json_object_new_object();
+ json_object_object_add(a, "200", f);
+ json_object_object_add(f, "description", json_object_new_string(verb->info?:verb->verb));
+ }
+ return r;
+}
+
+struct afb_api_v3 *afb_api_v3_create(
+ struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *apiname,
+ const char *info,
+ int noconcurrency,
+ int (*preinit)(void*, struct afb_api_x3 *),
+ void *closure,
+ int copy_info
+)
+{
+ struct afb_api_v3 *api;
+
+ /* allocates the description */
+ api = calloc(1, sizeof *api + (copy_info && info ? 1 + strlen(info) : 0));
+ if (!api)
+ goto oom;
+ api->refcount = 1;
+ if (!info)
+ api->info = &nulchar;
+ else if (copy_info)
+ api->info = strcpy((char*)(api + 1), info);
+ else
+ api->info = info;
+
+ api->export = afb_export_create_v3(declare_set, call_set, apiname, api);
+ if (!api->export)
+ goto oom2;
+
+ if (afb_export_declare(api->export, noconcurrency) < 0)
+ goto oom3;
+
+ if (preinit && afb_export_preinit_x3(api->export, preinit, closure) < 0)
+ goto oom4;
+
+ return api;
+
+oom4:
+ afb_export_undeclare(api->export);
+oom3:
+ afb_export_unref(api->export);
+oom2:
+ free(api);
+oom:
+ ERROR("out of memory");
+ return NULL;
+}
+
+struct afb_api_v3 *afb_api_v3_addref(struct afb_api_v3 *api)
+{
+ if (api)
+ __atomic_add_fetch(&api->refcount, 1, __ATOMIC_RELAXED);
+ return api;
+}
+
+void afb_api_v3_unref(struct afb_api_v3 *api)
+{
+ if (api && !__atomic_sub_fetch(&api->refcount, 1, __ATOMIC_RELAXED)) {
+ afb_export_destroy(api->export);
+ free(api);
+ }
+}
+
+struct afb_export *afb_api_v3_export(struct afb_api_v3 *api)
+{
+ return api->export;
+}
+
+void afb_api_v3_set_verbs_v2(
+ struct afb_api_v3 *api,
+ const struct afb_verb_v2 *verbs)
+{
+ api->verbsv2 = verbs;
+}
+
+void afb_api_v3_set_verbs_v3(
+ struct afb_api_v3 *api,
+ const struct afb_verb_v3 *verbs)
+{
+ api->verbsv3 = verbs;
+}
+
+int afb_api_v3_add_verb(
+ struct afb_api_v3 *api,
+ const char *verb,
+ const char *info,
+ void (*callback)(struct afb_req_x2 *req),
+ void *vcbdata,
+ const struct afb_auth *auth,
+ uint16_t session,
+ int glob)
+{
+ struct afb_verb_v3 *v, **vv;
+ char *txt;
+ int i;
+
+ for (i = 0 ; i < api->count ; i++) {
+ v = api->verbs[i];
+ if (glob == v->glob && !strcasecmp(verb, v->verb)) {
+ /* refuse to redefine a dynamic verb */
+ errno = EEXIST;
+ return -1;
+ }
+ }
+
+ vv = realloc(api->verbs, (1 + api->count) * sizeof *vv);
+ if (!vv)
+ goto oom;
+ api->verbs = vv;
+
+ v = malloc(sizeof *v + (1 + strlen(verb)) + (info ? 1 + strlen(info) : 0));
+ if (!v)
+ goto oom;
+
+ v->callback = callback;
+ v->vcbdata = vcbdata;
+ v->auth = auth;
+ v->session = session;
+ v->glob = !!glob;
+
+ txt = (char*)(v + 1);
+ v->verb = txt;
+ txt = stpcpy(txt, verb);
+ if (!info)
+ v->info = NULL;
+ else {
+ v->info = ++txt;
+ strcpy(txt, info);
+ }
+
+ api->verbs[api->count++] = v;
+ return 0;
+oom:
+ errno = ENOMEM;
+ return -1;
+}
+
+int afb_api_v3_del_verb(
+ struct afb_api_v3 *api,
+ const char *verb,
+ void **vcbdata)
+{
+ struct afb_verb_v3 **v, **e, *i;
+
+ v = api->verbs;
+ e = &v[api->count];
+ while (v != e) {
+ i = *v++;
+ if (!strcasecmp(i->verb, verb)) {
+ api->count--;
+ if (vcbdata)
+ *vcbdata = i->vcbdata;
+ if (v != e)
+ *--v = *--e;
+ free(i);
+ return 0;
+ }
+ }
+
+ errno = ENOENT;
+ return -1;
+}
+
+int afb_api_v3_set_binding_fields(const struct afb_binding_v3 *desc, struct afb_api_x3 *api)
+{
+ int rc = 0;
+ if (desc->verbs)
+ rc = afb_api_x3_set_verbs_v3(api, desc->verbs);
+ if (!rc && desc->onevent)
+ rc = afb_api_x3_on_event(api, desc->onevent);
+ if (!rc && desc->init)
+ rc = afb_api_x3_on_init(api, desc->init);
+ if (!rc && desc->provide_class)
+ rc = afb_api_x3_provide_class(api, desc->provide_class);
+ if (!rc && desc->require_class)
+ rc = afb_api_x3_require_class(api, desc->require_class);
+ if (!rc && desc->require_api)
+ rc = afb_api_x3_require_api(api, desc->require_api, 1);
+ return rc;
+}
+
+static int init_binding(void *closure, struct afb_api_x3 *api)
+{
+ const struct afb_binding_v3 *desc = closure;
+ int rc = afb_api_v3_set_binding_fields(desc, api);
+ if (!rc && desc->preinit)
+ rc = desc->preinit(api);
+ return rc;
+}
+
+struct afb_api_v3 *afb_api_v3_from_binding(const struct afb_binding_v3 *desc, struct afb_apiset *declare_set, struct afb_apiset * call_set)
+{
+ return afb_api_v3_create(declare_set, call_set, desc->api, desc->info, desc->noconcurrency, init_binding, (void*)desc, 0);
+}
+
diff --git a/src/afb-api-v3.h b/src/afb-api-v3.h
new file mode 100644
index 00000000..33649f35
--- /dev/null
+++ b/src/afb-api-v3.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016, 2017, 2018 "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.
+ */
+
+
+#pragma once
+
+struct afb_apiset;
+struct afb_api_v3;
+struct afb_api_x3;
+struct afb_auth;
+struct afb_req_x2;
+struct afb_verb_v2;
+struct afb_verb_v3;
+struct afb_binding_v3;
+struct afb_xreq;
+struct json_object;
+struct afb_export;
+
+extern struct afb_api_v3 *afb_api_v3_create(
+ struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *apiname,
+ const char *info,
+ int noconcurrency,
+ int (*preinit)(void*, struct afb_api_x3 *),
+ void *closure,
+ int copy_info
+);
+
+extern struct afb_api_v3 *afb_api_v3_from_binding(
+ const struct afb_binding_v3 *desc,
+ struct afb_apiset *declare_set,
+ struct afb_apiset * call_set);
+
+extern int afb_api_v3_set_binding_fields(const struct afb_binding_v3 *desc, struct afb_api_x3 *api);
+
+extern struct afb_api_v3 *afb_api_v3_addref(struct afb_api_v3 *api);
+extern void afb_api_v3_unref(struct afb_api_v3 *api);
+
+extern struct afb_export *afb_api_v3_export(struct afb_api_v3 *api);
+
+extern void afb_api_v3_set_verbs_v2(
+ struct afb_api_v3 *api,
+ const struct afb_verb_v2 *verbs);
+
+extern void afb_api_v3_set_verbs_v3(
+ struct afb_api_v3 *api,
+ const struct afb_verb_v3 *verbs);
+
+extern int afb_api_v3_add_verb(
+ struct afb_api_v3 *api,
+ const char *verb,
+ const char *info,
+ void (*callback)(struct afb_req_x2 *req),
+ void *vcbdata,
+ const struct afb_auth *auth,
+ uint16_t session,
+ int glob);
+
+extern int afb_api_v3_del_verb(
+ struct afb_api_v3 *api,
+ const char *verb,
+ void **vcbdata);
+
+extern void afb_api_v3_process_call(struct afb_api_v3 *api, struct afb_xreq *xreq);
+extern struct json_object *afb_api_v3_make_description_openAPIv3(struct afb_api_v3 *api, const char *apiname);
+
diff --git a/src/afb-api-ws.c b/src/afb-api-ws.c
index 190c2fd8..c1ccd329 100644
--- a/src/afb-api-ws.c
+++ b/src/afb-api-ws.c
@@ -34,6 +34,7 @@
#include "afb-systemd.h"
#include "afb-api.h"
#include "afb-apiset.h"
+#include "afb-api-ws.h"
#include "afb-stub-ws.h"
#include "verbose.h"
#include "fdev.h"
@@ -72,7 +73,7 @@ static struct api_ws *api_ws_make(const char *path)
while (length && path[length - 1] != '/' && path[length - 1] != ':')
length = length - 1;
api->api = &api->path[length];
- if (api->api == NULL || !afb_api_is_valid_name(api->api, 1)) {
+ if (api->api == NULL || !afb_api_is_valid_name(api->api)) {
errno = EINVAL;
goto error2;
}
@@ -219,7 +220,7 @@ static struct fdev *api_ws_socket_fdev(const char *path, int server)
/**********************************************************************************/
-int afb_api_ws_add_client(const char *path, struct afb_apiset *apiset, int strong)
+int afb_api_ws_add_client(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set, int strong)
{
struct api_ws *apiws;
struct afb_stub_ws *stubws;
@@ -234,12 +235,12 @@ int afb_api_ws_add_client(const char *path, struct afb_apiset *apiset, int stron
if (!apiws->fdev)
goto error2;
- stubws = afb_stub_ws_create_client(apiws->fdev, apiws->api, apiset);
+ stubws = afb_stub_ws_create_client(apiws->fdev, apiws->api, call_set);
if (!stubws) {
ERROR("can't setup client ws service to %s", apiws->path);
goto error3;
}
- if (afb_stub_ws_client_add(stubws, apiset) < 0) {
+ if (afb_stub_ws_client_add(stubws, declare_set) < 0) {
ERROR("can't add the client to the apiset for service %s", apiws->path);
goto error3;
}
@@ -253,14 +254,14 @@ error:
return -!!strong;
}
-int afb_api_ws_add_client_strong(const char *path, struct afb_apiset *apiset)
+int afb_api_ws_add_client_strong(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set)
{
- return afb_api_ws_add_client(path, apiset, 1);
+ return afb_api_ws_add_client(path, declare_set, call_set, 1);
}
-int afb_api_ws_add_client_weak(const char *path, struct afb_apiset *apiset)
+int afb_api_ws_add_client_weak(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set)
{
- return afb_api_ws_add_client(path, apiset, 0);
+ return afb_api_ws_add_client(path, declare_set, call_set, 0);
}
static int api_ws_server_accept_client(struct api_ws *apiws, struct fdev *fdev)
@@ -329,7 +330,7 @@ static int api_ws_server_connect(struct api_ws *apiws)
}
/* create the service */
-int afb_api_ws_add_server(const char *path, struct afb_apiset *apiset)
+int afb_api_ws_add_server(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set)
{
int rc;
struct api_ws *apiws;
@@ -340,7 +341,7 @@ int afb_api_ws_add_server(const char *path, struct afb_apiset *apiset)
goto error;
/* check api name */
- if (!afb_apiset_lookup(apiset, apiws->api, 1)) {
+ if (!afb_apiset_lookup(call_set, apiws->api, 1)) {
ERROR("Can't provide ws-server for %s: API %s doesn't exist", path, apiws->api);
goto error2;
}
@@ -350,7 +351,7 @@ int afb_api_ws_add_server(const char *path, struct afb_apiset *apiset)
if (rc < 0)
goto error2;
- apiws->apiset = afb_apiset_addref(apiset);
+ apiws->apiset = afb_apiset_addref(call_set);
return 0;
error2:
diff --git a/src/afb-api-ws.h b/src/afb-api-ws.h
index 123efb73..812cff59 100644
--- a/src/afb-api-ws.h
+++ b/src/afb-api-ws.h
@@ -20,10 +20,10 @@
struct afb_apiset;
-extern int afb_api_ws_add_client(const char *path, struct afb_apiset *apiset, int strong);
-extern int afb_api_ws_add_client_strong(const char *path, struct afb_apiset *apiset);
-extern int afb_api_ws_add_client_weak(const char *path, struct afb_apiset *apiset);
+extern int afb_api_ws_add_client(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set, int strong);
+extern int afb_api_ws_add_client_strong(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set);
+extern int afb_api_ws_add_client_weak(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set);
-extern int afb_api_ws_add_server(const char *path, struct afb_apiset *apiset);
+extern int afb_api_ws_add_server(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set);
diff --git a/src/afb-api.c b/src/afb-api.c
index 54ee5945..de603d3e 100644
--- a/src/afb-api.c
+++ b/src/afb-api.c
@@ -29,7 +29,7 @@
* Checks wether 'name' is a valid API name.
* @return 1 if valid, 0 otherwise
*/
-int afb_api_is_valid_name(const char *name, int hookable)
+int afb_api_is_valid_name(const char *name)
{
unsigned char c;
@@ -60,6 +60,6 @@ int afb_api_is_valid_name(const char *name, int hookable)
}
c = (unsigned char)*++name;
} while(c != 0);
- return !hookable || afb_api_is_hookable(name);
+ return 1;
}
diff --git a/src/afb-api.h b/src/afb-api.h
index 3f2e7f15..d03aaca5 100644
--- a/src/afb-api.h
+++ b/src/afb-api.h
@@ -24,24 +24,21 @@ struct json_object;
struct afb_api_itf
{
void (*call)(void *closure, struct afb_xreq *xreq);
- int (*service_start)(void *closure, int share_session, int onneed, struct afb_apiset *apiset);
+ int (*service_start)(void *closure, int share_session, int onneed);
void (*update_hooks)(void *closure);
- int (*get_verbosity)(void *closure);
- void (*set_verbosity)(void *closure, int level);
+ int (*get_logmask)(void *closure);
+ void (*set_logmask)(void *closure, int level);
struct json_object *(*describe)(void *closure);
void (*unref)(void *closure);
};
-struct afb_api
+struct afb_api_item
{
void *closure;
struct afb_api_itf *itf;
const void *group;
};
-extern int afb_api_is_valid_name(const char *name, int hookable);
+extern int afb_api_is_valid_name(const char *name);
-#define AFB_API_UNHOOKABLE_PREFIX_CHAR '$'
-#define AFB_API_UNHOOKABLE_PREFIX_STRING "$"
-#define afb_api_is_hookable(api) ((api)[0] != AFB_API_UNHOOKABLE_PREFIX_CHAR)
diff --git a/src/afb-apiset.c b/src/afb-apiset.c
index 8d76bbfe..af5a8652 100644
--- a/src/afb-apiset.c
+++ b/src/afb-apiset.c
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2016, 2017, 2018 "IoT.bzh"
- * Author "Fulup Ar Foll"
* Author José Bollo <jose.bollo@iot.bzh>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -32,14 +31,68 @@
#define INCR 8 /* CAUTION: must be a power of 2 */
+struct afb_apiset;
+struct api_desc;
+struct api_class;
+struct api_alias;
+struct api_depend;
+
+/**
+ * array of items
+ */
+struct api_array {
+ int count; /* count of items */
+ union {
+ void **anys;
+ struct api_desc **apis;
+ struct api_class **classes;
+ struct api_alias **aliases;
+ struct api_depend **depends;
+ };
+};
+
/**
* Internal description of an api
*/
struct api_desc
{
- int status;
- const char *name; /**< name of the api */
- struct afb_api api; /**< handler of the api */
+ struct api_desc *next;
+ const char *name; /**< name of the api */
+ int status; /**< initialisation status */
+ struct afb_api_item api; /**< handler of the api */
+ struct {
+ struct api_array classes;
+ struct api_array apis;
+ } require;
+};
+
+/**
+ * internal description of aliases
+ */
+struct api_alias
+{
+ struct api_alias *next;
+ struct api_desc *api;
+ char name[1];
+};
+
+/**
+ *
+ */
+struct api_class
+{
+ struct api_class *next;
+ struct api_array providers;
+ char name[1];
+};
+
+/**
+ *
+ */
+struct api_depend
+{
+ struct afb_apiset *set;
+ char name[1];
};
/**
@@ -47,15 +100,133 @@ struct api_desc
*/
struct afb_apiset
{
- struct api_desc *apis; /**< description of apis */
+ struct api_array apis; /**< the apis */
+ struct api_alias *aliases; /**< the aliases */
struct afb_apiset *subset; /**< subset if any */
- int count; /**< count of apis in the set */
+ struct {
+ int (*callback)(void*, struct afb_apiset*, const char*); /* not found handler */
+ void *closure;
+ void (*cleanup)(void*);
+ } onlack; /** not found handler */
int timeout; /**< the timeout in second for the apiset */
int refcount; /**< reference count for freeing resources */
char name[1]; /**< name of the apiset */
};
/**
+ * global apis
+ */
+static struct api_desc *all_apis;
+
+/**
+ * global classes
+ */
+static struct api_class *all_classes;
+
+/**
+ * Ensure enough room in 'array' for 'count' items
+ */
+static int api_array_ensure_count(struct api_array *array, int count)
+{
+ int c;
+ void **anys;
+
+ c = (count + INCR - 1) & ~(INCR - 1);
+ anys = realloc(array->anys, c * sizeof *anys);
+ if (!anys) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ array->count = count;
+ array->anys = anys;
+ return 0;
+}
+
+/**
+ * Insert in 'array' the item 'any' at the 'index'
+ */
+static int api_array_insert(struct api_array *array, void *any, int index)
+{
+ int n = array->count;
+
+ if (api_array_ensure_count(array, n + 1) < 0)
+ return -1;
+
+ while (index < n) {
+ array->anys[n] = array->anys[n - 1];
+ n--;
+ }
+
+ array->anys[index] = any;
+ return 0;
+}
+
+/**
+ * Add the item 'any' to the 'array'
+ */
+static int api_array_add(struct api_array *array, void *any)
+{
+ int i, n = array->count;
+
+ for (i = 0 ; i < n ; i++) {
+ if (array->anys[i] == any)
+ return 0;
+ }
+
+ if (api_array_ensure_count(array, n + 1) < 0)
+ return -1;
+
+ array->anys[n] = any;
+ return 0;
+}
+
+/**
+ * Delete the 'api' from the 'array'
+ * Returns 1 if delete or 0 if not found
+ */
+static int api_array_del(struct api_array *array, void *any)
+{
+ int i = array->count;
+ while (i) {
+ if (array->anys[--i] == any) {
+ array->anys[i] = array->anys[--array->count];
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Search the class of 'name' and return it.
+ * In case where the class of 'namle' isn't found, it returns
+ * NULL when 'create' is null or a fresh created instance if 'create' isn't
+ * zero (but NULL on allocation failure).
+ */
+static struct api_class *class_search(const char *name, int create)
+{
+ struct api_class *c;
+
+ for (c= all_classes ; c ; c = c->next) {
+ if (!strcasecmp(name, c->name))
+ return c;
+ }
+
+ if (!create)
+ return NULL;
+
+ c = calloc(1, strlen(name) + sizeof *c);
+ if (!c)
+ errno = ENOMEM;
+ else {
+ strcpy(c->name, name);
+ c->next = all_classes;
+ all_classes = c;
+ }
+ return c;
+}
+
+/**
* Search the api of 'name'.
* @param set the api set
* @param name the api name to search
@@ -65,20 +236,16 @@ static struct api_desc *search(struct afb_apiset *set, const char *name)
{
int i, c, up, lo;
struct api_desc *a;
+ struct api_alias *aliases;
/* dichotomic search of the api */
/* initial slice */
lo = 0;
- up = set->count;
- for (;;) {
- /* check remaining slice */
- if (lo >= up) {
- /* not found */
- return NULL;
- }
+ up = set->apis.count;
+ while (lo < up) {
/* check the mid of the slice */
i = (lo + up) >> 1;
- a = &set->apis[i];
+ a = set->apis.apis[i];
c = strcasecmp(a->name, name);
if (c == 0) {
/* found */
@@ -90,6 +257,37 @@ static struct api_desc *search(struct afb_apiset *set, const char *name)
else
up = i;
}
+
+ /* linear search of aliases */
+ aliases = set->aliases;
+ for(;;) {
+ if (!aliases)
+ break;
+ c = strcasecmp(aliases->name, name);
+ if (!c)
+ return aliases->api;
+ if (c > 0)
+ break;
+ aliases = aliases->next;
+ }
+ return NULL;
+}
+
+/**
+ * Search the api of 'name' in the apiset and in its subsets.
+ * @param set the api set
+ * @param name the api name to search
+ * @return the descriptor if found or NULL otherwise
+ */
+static struct api_desc *searchrec(struct afb_apiset *set, const char *name)
+{
+ struct api_desc *result;
+
+ do {
+ result = search(set, name);
+ } while (result == NULL && (set = set->subset) != NULL);
+
+ return result;
}
/**
@@ -111,9 +309,24 @@ struct afb_apiset *afb_apiset_addref(struct afb_apiset *set)
*/
void afb_apiset_unref(struct afb_apiset *set)
{
+ struct api_alias *a;
+ struct api_desc *d;
+
if (set && !__atomic_sub_fetch(&set->refcount, 1, __ATOMIC_RELAXED)) {
afb_apiset_unref(set->subset);
- free(set->apis);
+ if (set->onlack.cleanup)
+ set->onlack.cleanup(set->onlack.closure);
+ while((a = set->aliases)) {
+ set->aliases = a->next;
+ free(a);
+ }
+ while (set->apis.count) {
+ d = set->apis.apis[--set->apis.count];
+ if (d->api.itf->unref)
+ d->api.itf->unref(d->api.closure);
+ free(d);
+ }
+ free(set->apis.apis);
free(set);
}
}
@@ -128,22 +341,49 @@ struct afb_apiset *afb_apiset_create(const char *name, int timeout)
{
struct afb_apiset *set;
- set = malloc((name ? strlen(name) : 0) + sizeof *set);
+ set = calloc(1, (name ? strlen(name) : 0) + sizeof *set);
if (set) {
- set->apis = malloc(INCR * sizeof *set->apis);
- set->count = 0;
set->timeout = timeout;
set->refcount = 1;
- set->subset = NULL;
if (name)
strcpy(set->name, name);
- else
- set->name[0] = 0;
}
return set;
}
/**
+ * Create an apiset being the last subset of 'set'
+ * @param set the set to extend with the created subset (can be NULL)
+ * @param name the name of the created apiset (can be NULL)
+ * @param timeout the default timeout in seconds for the created apiset
+ * @return the created apiset or NULL in case of error
+ */
+struct afb_apiset *afb_apiset_create_subset_last(struct afb_apiset *set, const char *name, int timeout)
+{
+ if (set)
+ while (set->subset)
+ set = set->subset;
+ return afb_apiset_create_subset_first(set, name, timeout);
+}
+
+/**
+ * Create an apiset being the first subset of 'set'
+ * @param set the set to extend with the created subset (can be NULL)
+ * @param name the name of the created apiset (can be NULL)
+ * @param timeout the default timeout in seconds for the created apiset
+ * @return the created apiset or NULL in case of error
+ */
+struct afb_apiset *afb_apiset_create_subset_first(struct afb_apiset *set, const char *name, int timeout)
+{
+ struct afb_apiset *result = afb_apiset_create(name, timeout);
+ if (result && set) {
+ result->subset = set->subset;
+ set->subset = result;
+ }
+ return result;
+}
+
+/**
* the name of the apiset
* @param set the api set
* @return the name of the set
@@ -200,6 +440,15 @@ void afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset)
afb_apiset_unref(tmp);
}
+void afb_apiset_onlack_set(struct afb_apiset *set, int (*callback)(void*, struct afb_apiset*, const char*), void *closure, void (*cleanup)(void*))
+{
+ if (set->onlack.cleanup)
+ set->onlack.cleanup(set->onlack.closure);
+ set->onlack.callback = callback;
+ set->onlack.closure = closure;
+ set->onlack.cleanup = cleanup;
+}
+
/**
* Adds the api of 'name' described by 'api'.
* @param set the api set
@@ -210,52 +459,117 @@ void afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset)
* - EEXIST if name already registered
* - ENOMEM when out of memory
*/
-int afb_apiset_add(struct afb_apiset *set, const char *name, struct afb_api api)
+int afb_apiset_add(struct afb_apiset *set, const char *name, struct afb_api_item api)
{
- struct api_desc *apis;
+ struct api_desc *desc;
int i, c;
- /* check previously existing plugin */
- for (i = 0 ; i < set->count ; i++) {
- c = strcasecmp(set->apis[i].name, name);
- if (c == 0) {
- ERROR("api of name %s already exists", name);
- errno = EEXIST;
- goto error;
- }
+ /* check whether it exists already */
+ if (search(set, name)) {
+ ERROR("api of name %s already exists", name);
+ errno = EEXIST;
+ goto error;
+ }
+
+ /* search insertion place */
+ for (i = 0 ; i < set->apis.count ; i++) {
+ c = strcasecmp(set->apis.apis[i]->name, name);
if (c > 0)
break;
}
- /* allocates enough memory */
- c = (set->count + INCR) & ~(INCR - 1);
- apis = realloc(set->apis, ((unsigned)c) * sizeof * apis);
- if (apis == NULL) {
- ERROR("out of memory");
- errno = ENOMEM;
+ /* allocates memory */
+ desc = calloc(1, sizeof *desc);
+ if (!desc)
+ goto oom;
+
+ desc->status = -1;
+ desc->api = api;
+ desc->name = name;
+
+ if (api_array_insert(&set->apis, desc, i) < 0) {
+ free(desc);
goto error;
}
- set->apis = apis;
- /* copy higher part of the array */
- apis += i;
- if (i != set->count)
- memmove(apis + 1, apis, ((unsigned)(set->count - i)) * sizeof *apis);
-
- /* record the plugin */
- apis->status = -1;
- apis->api = api;
- apis->name = name;
- set->count++;
+ desc->next = all_apis;
+ all_apis = desc;
INFO("API %s added", name);
return 0;
+oom:
+ ERROR("out of memory");
+ errno = ENOMEM;
+error:
+ return -1;
+}
+
+/**
+ * Adds a the 'alias' name to the api of 'name'.
+ * @params set the api set
+ * @param name the name of the api to alias
+ * @param alias the aliased name to add to the api of name
+ * @returns 0 in case of success or -1 in case
+ * of error with errno set:
+ * - ENOENT if the api doesn't exist
+ * - EEXIST if name (of alias) already registered
+ * - ENOMEM when out of memory
+ */
+int afb_apiset_add_alias(struct afb_apiset *set, const char *name, const char *alias)
+{
+ struct api_desc *api;
+ struct api_alias *ali, **pali;
+
+ /* check alias doesn't already exist */
+ if (search(set, alias)) {
+ ERROR("api of name %s already exists", alias);
+ errno = EEXIST;
+ goto error;
+ }
+
+ /* check aliased api exists */
+ api = search(set, name);
+ if (api == NULL) {
+ ERROR("api of name %s doesn't exists", name);
+ errno = ENOENT;
+ goto error;
+ }
+
+ /* allocates and init the struct */
+ ali = malloc(sizeof *ali + strlen(alias));
+ if (ali == NULL) {
+ ERROR("out of memory");
+ errno = ENOMEM;
+ goto error;
+ }
+ ali->api = api;
+ strcpy(ali->name, alias);
+
+ /* insert the alias in the sorted order */
+ pali = &set->aliases;
+ while(*pali && strcmp((*pali)->name, alias) < 0)
+ pali = &(*pali)->next;
+ ali->next = *pali;
+ *pali = ali;
+ return 0;
error:
return -1;
}
+int afb_apiset_is_alias(struct afb_apiset *set, const char *name)
+{
+ struct api_desc *api = searchrec(set, name);
+ return api && strcasecmp(api->name, name);
+}
+
+const char *afb_apiset_unalias(struct afb_apiset *set, const char *name)
+{
+ struct api_desc *api = searchrec(set, name);
+ return api ? api->name : NULL;
+}
+
/**
* Delete from the 'set' the api of 'name'.
* @param set the set to be changed
@@ -264,28 +578,72 @@ error:
*/
int afb_apiset_del(struct afb_apiset *set, const char *name)
{
- struct api_desc *i, *e;
- int c;
+ struct api_class *cla;
+ struct api_alias *ali, **pali;
+ struct api_desc *desc, **pdesc, *odesc;
+ int i, c;
+
+ /* search the alias */
+ pali = &set->aliases;
+ while ((ali = *pali)) {
+ c = strcasecmp(ali->name, name);
+ if (!c) {
+ *pali = ali->next;
+ free(ali);
+ return 0;
+ }
+ if (c > 0)
+ break;
+ pali = &ali->next;
+ }
/* search the api */
- i = set->apis;
- e = i + set->count;
- while (i != e) {
- c = strcasecmp(i->name, name);
+ for (i = 0 ; i < set->apis.count ; i++) {
+ desc = set->apis.apis[i];
+ c = strcasecmp(desc->name, name);
if (c == 0) {
- if (i->api.itf->unref)
- i->api.itf->unref(i->api.closure);
- set->count--;
- e--;
- while (i != e) {
- i[0] = i[1];
+ /* remove from classes */
+ for (cla = all_classes ; cla ; cla = cla->next)
+ api_array_del(&cla->providers, desc);
+
+ /* unlink from the whole set and their requires */
+ pdesc = &all_apis;
+ while ((odesc = *pdesc) != desc) {
+ pdesc = &odesc->next;
+ }
+ *pdesc = odesc = desc->next;
+ while (odesc) {
+ odesc = odesc->next;
+ }
+
+ /* remove references from classes */
+ free(desc->require.classes.classes);
+
+ /* drop the aliases */
+ pali = &set->aliases;
+ while ((ali = *pali)) {
+ if (ali->api != desc)
+ pali = &ali->next;
+ else {
+ *pali = ali->next;
+ free(ali);
+ }
+ }
+
+ /* unref the api */
+ if (desc->api.itf->unref)
+ desc->api.itf->unref(desc->api.closure);
+
+ set->apis.count--;
+ while(i < set->apis.count) {
+ set->apis.apis[i] = set->apis.apis[i + 1];
i++;
}
+ free(desc);
return 0;
}
if (c > 0)
break;
- i++;
}
errno = ENOENT;
return -1;
@@ -300,8 +658,21 @@ int afb_apiset_del(struct afb_apiset *set, const char *name)
*/
static struct api_desc *lookup(struct afb_apiset *set, const char *name, int rec)
{
- struct api_desc *i = search(set, name);
- return i || !rec || !set->subset ? i : lookup(set->subset, name, rec);
+ struct api_desc *result;
+
+ result = search(set, name);
+ while (!result) {
+ /* lacking the api, try onlack behaviour */
+ if (set->onlack.callback && set->onlack.callback(set->onlack.closure, set, name) > 0) {
+ result = search(set, name);
+ if (result)
+ break;
+ }
+ if (!rec || !(set = set->subset))
+ break;
+ result = search(set, name);
+ }
+ return result;
}
/**
@@ -311,7 +682,7 @@ static struct api_desc *lookup(struct afb_apiset *set, const char *name, int rec
* @param rec if not zero look also recursively in subsets
* @return the api pointer in case of success or NULL in case of error
*/
-const struct afb_api *afb_apiset_lookup(struct afb_apiset *set, const char *name, int rec)
+const struct afb_api_item *afb_apiset_lookup(struct afb_apiset *set, const char *name, int rec)
{
struct api_desc *i;
@@ -322,6 +693,78 @@ const struct afb_api *afb_apiset_lookup(struct afb_apiset *set, const char *name
return NULL;
}
+static int start_api(struct api_desc *api, int share_session, int onneed);
+
+/**
+ * Start the apis of the 'array'
+ * The attribute 'share_session' is sent to the start function.
+ */
+static int start_array_apis(struct api_array *array, int share_session)
+{
+ int i, rc = 0, rc2;
+
+ i = array->count;
+ while (i) {
+ rc2 = start_api(array->apis[--i], share_session, 1);
+ if (rc2 < 0) {
+ rc = rc2;
+ }
+ }
+ return rc;
+}
+
+/**
+ * Start the class 'cla' (start the apis that provide it).
+ * The attribute 'share_session' is sent to the start function.
+ */
+static int start_class(struct api_class *cla, int share_session)
+{
+ return start_array_apis(&cla->providers, share_session);
+}
+
+/**
+ * Start the classes of the 'array'
+ * The attribute 'share_session' is sent to the start function.
+ */
+static int start_array_classes(struct api_array *array, int share_session)
+{
+ int i, rc = 0, rc2;
+
+ i = array->count;
+ while (i) {
+ rc2 = start_class(array->classes[--i], share_session);
+ if (rc2 < 0) {
+ rc = rc2;
+ }
+ }
+ return rc;
+}
+
+/**
+ * Start the depends of the 'array'
+ * The attribute 'share_session' is sent to the start function.
+ */
+static int start_array_depends(struct api_array *array, int share_session)
+{
+ struct api_desc *api;
+ int i, rc = 0, rc2;
+
+ i = array->count;
+ while (i) {
+ i--;
+ api = searchrec(array->depends[i]->set, array->depends[i]->name);
+ if (!api)
+ rc = -1;
+ else {
+ rc2 = start_api(api, share_session, 1);
+ if (rc2 < 0) {
+ rc = rc2;
+ }
+ }
+ }
+ return rc;
+}
+
/**
* Starts the service 'api'.
* @param api the api
@@ -331,7 +774,7 @@ const struct afb_api *afb_apiset_lookup(struct afb_apiset *set, const char *name
* must be a service
* @return a positive number on success
*/
-static int start_api(struct afb_apiset *set, struct api_desc *api, int share_session, int onneed)
+static int start_api(struct api_desc *api, int share_session, int onneed)
{
int rc;
@@ -343,9 +786,11 @@ static int start_api(struct afb_apiset *set, struct api_desc *api, int share_ses
}
INFO("API %s starting...", api->name);
+ rc = start_array_classes(&api->require.classes, share_session);
+ rc = start_array_depends(&api->require.apis, share_session);
if (api->api.itf->service_start) {
api->status = EBUSY;
- rc = api->api.itf->service_start(api->api.closure, share_session, onneed, set);
+ rc = api->api.itf->service_start(api->api.closure, share_session, onneed);
if (rc < 0) {
api->status = errno ?: ECANCELED;
ERROR("The api %s failed to start (%d)", api->name, rc);
@@ -369,13 +814,13 @@ static int start_api(struct afb_apiset *set, struct api_desc *api, int share_ses
* @param rec if not zero look also recursively in subsets
* @return 0 in case of success or -1 in case of error
*/
-const struct afb_api *afb_apiset_lookup_started(struct afb_apiset *set, const char *name, int rec)
+const struct afb_api_item *afb_apiset_lookup_started(struct afb_apiset *set, const char *name, int rec)
{
struct api_desc *i;
i = lookup(set, name, rec);
if (i)
- return i->status && start_api(set, i, 1, 1) ? NULL : &i->api;
+ return i->status && start_api(i, 1, 1) ? NULL : &i->api;
errno = ENOENT;
return NULL;
}
@@ -394,14 +839,14 @@ int afb_apiset_start_service(struct afb_apiset *set, const char *name, int share
{
struct api_desc *a;
- a = search(set, name);
+ a = searchrec(set, name);
if (!a) {
ERROR("can't find service %s", name);
errno = ENOENT;
return -1;
}
- return start_api(set, a, share_session, onneed);
+ return start_api(a, share_session, onneed);
}
/**
@@ -414,18 +859,19 @@ int afb_apiset_start_service(struct afb_apiset *set, const char *name, int share
int afb_apiset_start_all_services(struct afb_apiset *set, int share_session)
{
int rc;
- struct api_desc *i, *e;
+ int i;
- i = set->apis;
- e = &set->apis[set->count];
- while (i != e) {
- rc = start_api(set, i, share_session, 1);
- if (rc < 0)
- return rc;
- i++;
+ while (set) {
+ i = 0;
+ while (i < set->apis.count) {
+ rc = start_api(set->apis.apis[i], share_session, 1);
+ if (rc < 0)
+ return rc;
+ i++;
+ }
+ set = set->subset;
}
-
- return set->subset ? afb_apiset_start_all_services(set->subset, share_session) : 0;
+ return 0;
}
/**
@@ -435,65 +881,66 @@ int afb_apiset_start_all_services(struct afb_apiset *set, int share_session)
*/
void afb_apiset_update_hooks(struct afb_apiset *set, const char *name)
{
- const struct api_desc *i, *e;
+ struct api_desc **i, **e, *d;
if (!name) {
- i = set->apis;
- e = &set->apis[set->count];
+ i = set->apis.apis;
+ e = &set->apis.apis[set->apis.count];
+ while (i != e) {
+ d = *i++;
+ if (d->api.itf->update_hooks)
+ d->api.itf->update_hooks(d->api.closure);
+ }
} else {
- i = search(set, name);
- e = &i[!!i];
- }
- while (i != e) {
- if (i->api.itf->update_hooks)
- i->api.itf->update_hooks(i->api.closure);
- i++;
+ d = searchrec(set, name);
+ if (d && d->api.itf->update_hooks)
+ d->api.itf->update_hooks(d->api.closure);
}
}
/**
- * Set the verbosity level of the 'api'
+ * Set the logmask of the 'api' to 'mask'
* @param set the api set
* @param name the api to set (NULL set all)
*/
-void afb_apiset_set_verbosity(struct afb_apiset *set, const char *name, int level)
+void afb_apiset_set_logmask(struct afb_apiset *set, const char *name, int mask)
{
- const struct api_desc *i, *e;
+ int i;
+ struct api_desc *d;
if (!name) {
- i = set->apis;
- e = &set->apis[set->count];
+ for (i = 0 ; i < set->apis.count ; i++) {
+ d = set->apis.apis[i];;
+ if (d->api.itf->set_logmask)
+ d->api.itf->set_logmask(d->api.closure, mask);
+ }
} else {
- i = search(set, name);
- e = &i[!!i];
- }
- while (i != e) {
- if (i->api.itf->set_verbosity)
- i->api.itf->set_verbosity(i->api.closure, level);
- i++;
+ d = searchrec(set, name);
+ if (d && d->api.itf->set_logmask)
+ d->api.itf->set_logmask(d->api.closure, mask);
}
}
/**
- * Get the verbosity level of the 'api'
+ * Get the logmask level of the 'api'
* @param set the api set
* @param name the api to get
- * @return the verbosity level or -1 in case of error
+ * @return the logmask level or -1 in case of error
*/
-int afb_apiset_get_verbosity(struct afb_apiset *set, const char *name)
+int afb_apiset_get_logmask(struct afb_apiset *set, const char *name)
{
const struct api_desc *i;
- i = name ? search(set, name) : NULL;
+ i = name ? searchrec(set, name) : NULL;
if (!i) {
errno = ENOENT;
return -1;
}
- if (!i->api.itf->get_verbosity)
- return verbosity;
+ if (!i->api.itf->get_logmask)
+ return logmask;
- return i->api.itf->get_verbosity(i->api.closure);
+ return i->api.itf->get_logmask(i->api.closure);
}
/**
@@ -506,36 +953,79 @@ struct json_object *afb_apiset_describe(struct afb_apiset *set, const char *name
{
const struct api_desc *i;
- i = name ? search(set, name) : NULL;
+ i = name ? searchrec(set, name) : NULL;
return i && i->api.itf->describe ? i->api.itf->describe(i->api.closure) : NULL;
}
+struct get_names {
+ union {
+ struct {
+ size_t count;
+ size_t size;
+ };
+ struct {
+ const char **ptr;
+ char *data;
+ };
+ };
+ int type;
+};
+
+static void get_names_count(void *closure, struct afb_apiset *set, const char *name, int isalias)
+{
+ struct get_names *gc = closure;
+ if ((1 + isalias) & gc->type) {
+ gc->size += strlen(name);
+ gc->count++;
+ }
+}
+
+static void get_names_value(void *closure, struct afb_apiset *set, const char *name, int isalias)
+{
+ struct get_names *gc = closure;
+ if ((1 + isalias) & gc->type) {
+ *gc->ptr++ = gc->data;
+ gc->data = stpcpy(gc->data, name) + 1;
+ }
+}
+
+#if !defined(APISET_NO_SORT)
+static int get_names_sortcb(const void *a, const void *b)
+{
+ return strcasecmp(*(const char **)a, *(const char **)b);
+}
+#endif
+
/**
* Get the list of api names
* @param set the api set
+ * @param rec recursive
+ * @param type expected type: 1 names, 3 names+aliases, 2 aliases
* @return a NULL terminated array of api names. Must be freed.
*/
-const char **afb_apiset_get_names(struct afb_apiset *set)
+const char **afb_apiset_get_names(struct afb_apiset *set, int rec, int type)
{
+ struct get_names gc;
size_t size;
- char *dest;
const char **names;
- int i;
- size = set->count * (1 + sizeof(*names)) + sizeof(*names);
- for (i = 0 ; i < set->count ; i++)
- size += strlen(set->apis[i].name);
+ gc.count = gc.size = 0;
+ gc.type = type >= 1 && type <= 3 ? type : 1;
+ afb_apiset_enum(set, rec, get_names_count, &gc);
+ size = gc.size + gc.count * (1 + sizeof *names) + sizeof(*names);
names = malloc(size);
+
if (!names)
errno = ENOMEM;
else {
- dest = (void*)&names[set->count+1];
- for (i = 0 ; i < set->count ; i++) {
- names[i] = dest;
- dest = stpcpy(dest, set->apis[i].name) + 1;
- }
- names[i] = NULL;
+ gc.data = (char*)&names[gc.count + 1];
+ gc.ptr = names;
+ afb_apiset_enum(set, rec, get_names_value, &gc);
+#if !defined(APISET_NO_SORT)
+ qsort(names, gc.ptr - names, sizeof *names, get_names_sortcb);
+#endif
+ *gc.ptr = NULL;
}
return names;
}
@@ -543,24 +1033,97 @@ const char **afb_apiset_get_names(struct afb_apiset *set)
/**
* Enumerate the api names to a callback.
* @param set the api set
+ * @param rec should the enumeration be recursive
* @param callback the function to call for each name
* @param closure the closure for the callback
*/
-void afb_apiset_enum(struct afb_apiset *set, int rec, void (*callback)(struct afb_apiset *set, const char *name, void *closure), void *closure)
+void afb_apiset_enum(
+ struct afb_apiset *set,
+ int rec,
+ void (*callback)(void *closure, struct afb_apiset *set, const char *name, int isalias),
+ void *closure)
{
+ int i;
struct afb_apiset *iset;
- struct api_desc *i, *e;
+ struct api_desc *d;
+ struct api_alias *a;
iset = set;
while (iset) {
- i = iset->apis;
- e = &i[iset->count];
- while (i != e) {
- if (lookup(set, i->name, 1) == i)
- callback(iset, i->name, closure);
- i++;
+ for (i = 0 ; i < set->apis.count ; i++) {
+ d = set->apis.apis[i];;
+ if (searchrec(set, d->name) == d)
+ callback(closure, iset, d->name, 0);
+ }
+ a = iset->aliases;
+ while (a) {
+ if (searchrec(set, a->name) == a->api)
+ callback(closure, iset, a->name, 1);
+ a = a->next;
}
iset = rec ? iset->subset : NULL;
}
}
+/**
+ * Declare that the api of 'name' requires the api of name 'required'.
+ * The api is searched in the apiset 'set' and if 'rec' isn't null also in its subset.
+ * Returns 0 if the declaration successed or -1 in case of failure
+ * (ENOMEM: allocation failure, ENOENT: api name not found)
+ */
+int afb_apiset_require(struct afb_apiset *set, const char *name, const char *required)
+{
+ struct api_desc *a;
+ struct api_depend *d;
+ int rc = -1;
+
+ a = searchrec(set, name);
+ if (!a)
+ errno = ENOENT;
+ else {
+ d = malloc(strlen(required) + sizeof *d);
+ if (!d)
+ errno = ENOMEM;
+ else {
+ d->set = set;
+ strcpy(d->name, required);
+ rc = api_array_add(&a->require.apis, d);
+ }
+ }
+ return rc;
+}
+
+/**
+ * Declare that the api of name 'apiname' requires the class of name 'classname'.
+ * Returns 0 if the declaration successed or -1 in case of failure
+ * (ENOMEM: allocation failure, ENOENT: api name not found)
+ */
+int afb_apiset_require_class(struct afb_apiset *set, const char *apiname, const char *classname)
+{
+ struct api_desc *a = searchrec(set, apiname);
+ struct api_class *c = class_search(classname, 1);
+ return a && c ? api_array_add(&a->require.classes, c) : (errno = ENOENT, -1);
+}
+
+/**
+ * Declare that the api of name 'apiname' provides the class of name 'classname'
+ * Returns 0 if the declaration successed or -1 in case of failure
+ * (ENOMEM: allocation failure, ENOENT: api name not found)
+ */
+int afb_apiset_provide_class(struct afb_apiset *set, const char *apiname, const char *classname)
+{
+ struct api_desc *a = searchrec(set, apiname);
+ struct api_class *c = class_search(classname, 1);
+ return a && c ? api_array_add(&c->providers, a) : (errno = ENOENT, -1);
+}
+
+/**
+ * Start any API that provides the class of name 'classname'
+ * The attribute 'share_session' is sent to the start function.
+ */
+int afb_apiset_class_start(const char *classname, int share_session)
+{
+ struct api_class *cla = class_search(classname, 0);
+ return cla ? start_class(cla, share_session) : (errno = ENOENT, -1);
+}
+
diff --git a/src/afb-apiset.h b/src/afb-apiset.h
index 55068dd3..fc8bc266 100644
--- a/src/afb-apiset.h
+++ b/src/afb-apiset.h
@@ -17,28 +17,57 @@
#pragma once
-struct afb_api;
+struct afb_api_item;
struct afb_apiset;
struct json_object;
+extern struct afb_apiset *afb_apiset_create(const char *name, int timeout);
+extern struct afb_apiset *afb_apiset_create_subset_last(struct afb_apiset *set, const char *name, int timeout);
+extern struct afb_apiset *afb_apiset_create_subset_first(struct afb_apiset *set, const char *name, int timeout);
extern struct afb_apiset *afb_apiset_addref(struct afb_apiset *set);
extern void afb_apiset_unref(struct afb_apiset *set);
-extern struct afb_apiset *afb_apiset_create(const char *name, int timeout);
+
extern const char *afb_apiset_name(struct afb_apiset *set);
+
extern int afb_apiset_timeout_get(struct afb_apiset *set);
extern void afb_apiset_timeout_set(struct afb_apiset *set, int to);
+
+extern void afb_apiset_onlack_set(
+ struct afb_apiset *set,
+ int (*callback)(void *closure, struct afb_apiset *set, const char *name),
+ void *closure,
+ void (*cleanup)(void*closure));
+
extern void afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset);
extern struct afb_apiset *afb_apiset_subset_get(struct afb_apiset *set);
-extern int afb_apiset_add(struct afb_apiset *set, const char *name, struct afb_api api);
+
+extern int afb_apiset_add(struct afb_apiset *set, const char *name, struct afb_api_item api);
extern int afb_apiset_del(struct afb_apiset *set, const char *name);
-extern const struct afb_api *afb_apiset_lookup(struct afb_apiset *set, const char *name, int rec);
-extern const struct afb_api *afb_apiset_lookup_started(struct afb_apiset *set, const char *name, int rec);
+
+extern int afb_apiset_add_alias(struct afb_apiset *set, const char *name, const char *alias);
+extern int afb_apiset_is_alias(struct afb_apiset *set, const char *name);
+extern const char *afb_apiset_unalias(struct afb_apiset *set, const char *name);
+
+extern const struct afb_api_item *afb_apiset_lookup(struct afb_apiset *set, const char *name, int rec);
+extern const struct afb_api_item *afb_apiset_lookup_started(struct afb_apiset *set, const char *name, int rec);
+
extern int afb_apiset_start_service(struct afb_apiset *set, const char *name, int share_session, int onneed);
extern int afb_apiset_start_all_services(struct afb_apiset *set, int share_session);
+
extern void afb_apiset_update_hooks(struct afb_apiset *set, const char *name);
-extern void afb_apiset_set_verbosity(struct afb_apiset *set, const char *name, int level);
-extern int afb_apiset_get_verbosity(struct afb_apiset *set, const char *name);
+extern void afb_apiset_set_logmask(struct afb_apiset *set, const char *name, int mask);
+extern int afb_apiset_get_logmask(struct afb_apiset *set, const char *name);
+
extern struct json_object *afb_apiset_describe(struct afb_apiset *set, const char *name);
-extern const char **afb_apiset_get_names(struct afb_apiset *set);
-extern void afb_apiset_enum(struct afb_apiset *set, int rec, void (*callback)(struct afb_apiset *set, const char *name, void *closure), void *closure);
+extern const char **afb_apiset_get_names(struct afb_apiset *set, int rec, int type);
+extern void afb_apiset_enum(
+ struct afb_apiset *set,
+ int rec,
+ void (*callback)(void *closure, struct afb_apiset *set, const char *name, int isalias),
+ void *closure);
+
+extern int afb_apiset_require(struct afb_apiset *set, const char *name, const char *required);
+extern int afb_apiset_require_class(struct afb_apiset *set, const char *apiname, const char *classname);
+extern int afb_apiset_provide_class(struct afb_apiset *set, const char *apiname, const char *classname);
+extern int afb_apiset_class_start(const char *classname, int share_session);
diff --git a/src/afb-auth.c b/src/afb-auth.c
index 47a98d5a..4a3c445f 100644
--- a/src/afb-auth.c
+++ b/src/afb-auth.c
@@ -22,7 +22,7 @@
#include <json-c/json.h>
#include <afb/afb-auth.h>
-#include <afb/afb-session-v2.h>
+#include <afb/afb-session-x2.h>
#include "afb-auth.h"
#include "afb-context.h"
@@ -60,56 +60,10 @@ int afb_auth_check(struct afb_xreq *xreq, const struct afb_auth *auth)
}
}
-/*********************************************************************************/
-#ifdef BACKEND_PERMISSION_IS_CYNARA
-
-#include <pthread.h>
-#include <cynara-client.h>
-
-static cynara *handle;
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
-int afb_auth_has_permission(struct afb_xreq *xreq, const char *permission)
-{
- int rc;
-
- if (!xreq->cred) {
- /* case of permission for self */
- return 1;
- }
- if (!permission) {
- ERROR("Got a null permission!");
- return 0;
- }
-
- /* cynara isn't reentrant */
- pthread_mutex_lock(&mutex);
-
- /* lazy initialisation */
- if (!handle) {
- rc = cynara_initialize(&handle, NULL);
- if (rc != CYNARA_API_SUCCESS) {
- handle = NULL;
- ERROR("cynara initialisation failed with code %d", rc);
- return 0;
- }
- }
-
- /* query cynara permission */
- rc = cynara_check(handle, xreq->cred->label, afb_context_uuid(&xreq->context), xreq->cred->user, permission);
-
- pthread_mutex_unlock(&mutex);
- return rc == CYNARA_API_ACCESS_ALLOWED;
-}
-
-/*********************************************************************************/
-#else
int afb_auth_has_permission(struct afb_xreq *xreq, const char *permission)
{
- WARNING("Granting permission %s by default of backend", permission ?: "(null)");
- return !!permission;
+ return afb_cred_has_permission(xreq->cred, permission, afb_context_uuid(&xreq->context));
}
-#endif
/*********************************************************************************/
@@ -180,17 +134,17 @@ struct json_object *afb_auth_json_v2(const struct afb_auth *auth, int session)
{
struct json_object *result = NULL;
- if (session & AFB_SESSION_CLOSE_V2)
+ if (session & AFB_SESSION_CLOSE_X2)
result = addperm_key_valstr(result, "session", "close");
- if (session & AFB_SESSION_CHECK_V2)
+ if (session & AFB_SESSION_CHECK_X2)
result = addperm_key_valstr(result, "session", "check");
- if (session & AFB_SESSION_REFRESH_V2)
+ if (session & AFB_SESSION_REFRESH_X2)
result = addperm_key_valstr(result, "token", "refresh");
- if (session & AFB_SESSION_LOA_MASK_V2)
- result = addperm_key_valint(result, "LOA", session & AFB_SESSION_LOA_MASK_V2);
+ if (session & AFB_SESSION_LOA_MASK_X2)
+ result = addperm_key_valint(result, "LOA", session & AFB_SESSION_LOA_MASK_X2);
if (auth)
result = addauth(result, auth);
diff --git a/src/afb-autoset.c b/src/afb-autoset.c
new file mode 100644
index 00000000..102830cb
--- /dev/null
+++ b/src/afb-autoset.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016, 2017, 2018 "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.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "verbose.h"
+#include "afb-api-ws.h"
+#include "afb-api-so.h"
+#include "afb-apiset.h"
+#include "afb-autoset.h"
+
+static void cleanup(void *closure)
+{
+ struct afb_apiset *call_set = closure;
+ afb_apiset_unref(call_set);
+}
+
+static int onlack(void *closure, struct afb_apiset *set, const char *name, int (*create)(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set))
+{
+ struct afb_apiset *call_set = closure;
+ char *path;
+ const char *base;
+ size_t lbase, lname;
+
+ base = afb_apiset_name(set);
+ lbase = strlen(base);
+ lname = strlen(name);
+
+ path = alloca(2 + lbase + lname);
+ memcpy(path, base, lbase);
+ path[lbase] = '/';
+ memcpy(&path[lbase + 1], name, lname + 1);
+
+ return create(path, set, call_set);
+}
+
+static int add(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set, int (*callback)(void *, struct afb_apiset *, const char*))
+{
+ struct afb_apiset *ownset;
+
+ /* create a sub-apiset */
+ ownset = afb_apiset_create_subset_last(declare_set, path, 3600);
+ if (!ownset) {
+ ERROR("Can't create apiset autoset-ws %s", path);
+ return -1;
+ }
+
+ /* set the onlack behaviour on this set */
+ afb_apiset_onlack_set(ownset, callback, afb_apiset_addref(call_set), cleanup);
+ return 0;
+}
+
+static int create_ws(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set)
+{
+ return afb_api_ws_add_client(path, declare_set, call_set, 0) >= 0;
+}
+
+static int onlack_ws(void *closure, struct afb_apiset *set, const char *name)
+{
+ return onlack(closure, set, name, create_ws);
+}
+
+int afb_autoset_add_ws(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set)
+{
+ return add(path, declare_set, call_set, onlack_ws);
+}
+
+static int create_so(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set)
+{
+ return afb_api_so_add_binding(path, declare_set, call_set) >= 0;
+}
+
+static int onlack_so(void *closure, struct afb_apiset *set, const char *name)
+{
+ return onlack(closure, set, name, create_so);
+}
+
+int afb_autoset_add_so(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set)
+{
+ return add(path, declare_set, call_set, onlack_so);
+}
diff --git a/src/afb-autoset.h b/src/afb-autoset.h
new file mode 100644
index 00000000..50fdec1a
--- /dev/null
+++ b/src/afb-autoset.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016, 2017, 2018 "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.
+ */
+
+#pragma once
+
+struct afb_apiset;
+
+extern int afb_autoset_add_ws(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set);
+extern int afb_autoset_add_so(const char *path, struct afb_apiset *declare_set, struct afb_apiset *call_set);
diff --git a/src/afb-calls.c b/src/afb-calls.c
new file mode 100644
index 00000000..73b89bf0
--- /dev/null
+++ b/src/afb-calls.c
@@ -0,0 +1,818 @@
+/*
+ * Copyright (C) 2016, 2017, 2018 "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.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <json-c/json.h>
+
+#define AFB_BINDING_VERSION 0
+#include <afb/afb-binding.h>
+
+#include "afb-calls.h"
+#include "afb-cred.h"
+#include "afb-evt.h"
+#include "afb-export.h"
+#include "afb-hook.h"
+#include "afb-msg-json.h"
+#include "afb-session.h"
+#include "afb-xreq.h"
+
+#include "jobs.h"
+#include "verbose.h"
+
+#define CALLFLAGS (afb_req_x2_subcall_api_session|afb_req_x2_subcall_catch_events)
+#define LEGACY_SUBCALLFLAGS (afb_req_x2_subcall_pass_events|afb_req_x2_subcall_on_behalf)
+
+
+/************************************************************************/
+
+struct modes
+{
+ unsigned hooked: 1;
+ unsigned sync: 1;
+ unsigned legacy: 1;
+};
+
+#define mode_sync ((struct modes){ .hooked=0, .sync=1, .legacy=0 })
+#define mode_async ((struct modes){ .hooked=0, .sync=0, .legacy=0 })
+#define mode_legacy_sync ((struct modes){ .hooked=0, .sync=1, .legacy=1 })
+#define mode_legacy_async ((struct modes){ .hooked=0, .sync=0, .legacy=1 })
+#define mode_hooked_sync ((struct modes){ .hooked=1, .sync=1, .legacy=0 })
+#define mode_hooked_async ((struct modes){ .hooked=1, .sync=0, .legacy=0 })
+#define mode_hooked_legacy_sync ((struct modes){ .hooked=1, .sync=1, .legacy=1 })
+#define mode_hooked_legacy_async ((struct modes){ .hooked=1, .sync=0, .legacy=1 })
+
+union callback {
+ void *any;
+ union {
+ void (*legacy_v1)(void*, int, struct json_object*);
+ void (*legacy_v2)(void*, int, struct json_object*, struct afb_req_x1);
+ void (*legacy_v3)(void*, int, struct json_object*, struct afb_req_x2*);
+ void (*x3)(void*, struct json_object*, const char*, const char *, struct afb_req_x2*);
+ } subcall;
+ union {
+ void (*legacy_v12)(void*, int, struct json_object*);
+ void (*legacy_v3)(void*, int, struct json_object*, struct afb_api_x3*);
+ void (*x3)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*);
+ } call;
+};
+
+struct callreq
+{
+ struct afb_xreq xreq;
+
+ struct afb_export *export;
+
+ struct modes mode;
+
+ int flags;
+
+ union {
+ struct {
+ struct jobloop *jobloop;
+ int returned;
+ int status;
+ struct json_object **object;
+ char **error;
+ char **info;
+ };
+ struct {
+ union callback callback;
+ void *closure;
+ union {
+ void (*final)(void*, struct json_object*, const char*, const char*, union callback, struct afb_export*,struct afb_xreq*);
+ void (*legacy_final)(void*, int, struct json_object*, union callback, struct afb_export*,struct afb_xreq*);
+ };
+ };
+ };
+};
+
+/******************************************************************************/
+
+static int store_reply(
+ struct json_object *iobject, const char *ierror, const char *iinfo,
+ struct json_object **sobject, char **serror, char **sinfo)
+{
+ if (serror) {
+ if (!ierror)
+ *serror = NULL;
+ else if (!(*serror = strdup(ierror))) {
+ ERROR("can't report error %s", ierror);
+ json_object_put(iobject);
+ iobject = NULL;
+ iinfo = NULL;
+ }
+ }
+
+ if (sobject)
+ *sobject = iobject;
+ else
+ json_object_put(iobject);
+
+ if (sinfo) {
+ if (!iinfo)
+ *sinfo = NULL;
+ else if (!(*sinfo = strdup(iinfo)))
+ ERROR("can't report info %s", iinfo);
+ }
+
+ return -!!ierror;
+}
+
+/******************************************************************************/
+
+static void sync_leave(struct callreq *callreq)
+{
+ struct jobloop *jobloop = __atomic_exchange_n(&callreq->jobloop, NULL, __ATOMIC_RELAXED);
+ if (jobloop)
+ jobs_leave(jobloop);
+}
+
+static void sync_enter(int signum, void *closure, struct jobloop *jobloop)
+{
+ struct callreq *callreq = closure;
+ if (!signum) {
+ callreq->jobloop = jobloop;
+ afb_export_process_xreq(callreq->export, &callreq->xreq);
+ } else {
+ afb_xreq_reply(&callreq->xreq, NULL, "internal-error", NULL);
+ }
+}
+
+/******************************************************************************/
+
+static void callreq_destroy_cb(struct afb_xreq *xreq)
+{
+ struct callreq *callreq = CONTAINER_OF_XREQ(struct callreq, xreq);
+
+ afb_context_disconnect(&callreq->xreq.context);
+ json_object_put(callreq->xreq.json);
+ afb_cred_unref(callreq->xreq.cred);
+ free(callreq);
+}
+
+static void callreq_reply_cb(struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info)
+{
+ struct callreq *callreq = CONTAINER_OF_XREQ(struct callreq, xreq);
+
+ /* centralized hooking */
+ if (callreq->mode.hooked) {
+ if (callreq->mode.sync) {
+ if (callreq->xreq.caller)
+ afb_hook_xreq_subcallsync_result(callreq->xreq.caller, -!!error, object, error, info);
+ else
+ afb_hook_api_callsync_result(callreq->export, -!!error, object, error, info);
+ } else {
+ if (callreq->xreq.caller)
+ afb_hook_xreq_subcall_result(callreq->xreq.caller, object, error, info);
+ else
+ afb_hook_api_call_result(callreq->export, object, error, info);
+ }
+ }
+
+ /* true report of the result */
+ if (callreq->mode.sync) {
+ callreq->returned = 1;
+ if (callreq->mode.legacy) {
+ callreq->status = -!!error;
+ if (callreq->object)
+ *callreq->object = afb_msg_json_reply(object, error, info, NULL);
+ else
+ json_object_put(object);
+ } else {
+ callreq->status = store_reply(object, error, info,
+ callreq->object, callreq->error, callreq->info);
+ }
+ sync_leave(callreq);
+ } else {
+ if (callreq->mode.legacy) {
+ object = afb_msg_json_reply(object, error, info, NULL);
+ callreq->legacy_final(callreq->closure, -!!error, object, callreq->callback, callreq->export, callreq->xreq.caller);
+ } else {
+ callreq->final(callreq->closure, object, error, info, callreq->callback, callreq->export, callreq->xreq.caller);
+ }
+ json_object_put(object);
+ }
+}
+
+static int callreq_subscribe_cb(struct afb_xreq *xreq, struct afb_event_x2 *event)
+{
+ int rc = 0, rc2;
+ struct callreq *callreq = CONTAINER_OF_XREQ(struct callreq, xreq);
+
+ if (callreq->flags & afb_req_x2_subcall_pass_events)
+ rc = afb_xreq_subscribe(callreq->xreq.caller, event);
+ if (callreq->flags & afb_req_x2_subcall_catch_events) {
+ rc2 = afb_export_subscribe(callreq->export, event);
+ if (rc2 < 0)
+ rc = rc2;
+ }
+ return rc;
+}
+
+static int callreq_unsubscribe_cb(struct afb_xreq *xreq, struct afb_event_x2 *event)
+{
+ int rc = 0, rc2;
+ struct callreq *callreq = CONTAINER_OF_XREQ(struct callreq, xreq);
+
+ if (callreq->flags & afb_req_x2_subcall_pass_events)
+ rc = afb_xreq_unsubscribe(callreq->xreq.caller, event);
+ if (callreq->flags & afb_req_x2_subcall_catch_events) {
+ rc2 = afb_export_unsubscribe(callreq->export, event);
+ if (rc2 < 0)
+ rc = rc2;
+ }
+ return rc;
+}
+
+/******************************************************************************/
+
+const struct afb_xreq_query_itf afb_calls_xreq_itf = {
+ .unref = callreq_destroy_cb,
+ .reply = callreq_reply_cb,
+ .subscribe = callreq_subscribe_cb,
+ .unsubscribe = callreq_unsubscribe_cb
+};
+
+/******************************************************************************/
+
+static struct callreq *callreq_create(
+ struct afb_export *export,
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ struct modes mode)
+{
+ struct callreq *callreq;
+ size_t lenapi, lenverb;
+ char *api2, *verb2;
+
+ lenapi = 1 + strlen(api);
+ lenverb = 1 + strlen(verb);
+ callreq = malloc(lenapi + lenverb + sizeof *callreq);
+ if (!callreq) {
+ ERROR("out of memory");
+ json_object_put(args);
+ errno = ENOMEM;
+ } else {
+ afb_xreq_init(&callreq->xreq, &afb_calls_xreq_itf);
+ callreq->xreq.context.validated = 1;
+ api2 = (char*)&callreq[1];
+ callreq->xreq.request.called_api = memcpy(api2, api, lenapi);;
+ verb2 = &api2[lenapi];
+ callreq->xreq.request.called_verb = memcpy(verb2, verb, lenverb);
+ callreq->xreq.json = args;
+ callreq->mode = mode;
+ if (caller) {
+ export = afb_export_from_api_x3(caller->request.api);
+ if (flags & afb_req_x2_subcall_on_behalf)
+ callreq->xreq.cred = afb_cred_addref(caller->cred);
+ callreq->xreq.caller = caller;
+ afb_xreq_unhooked_addref(caller);
+ }
+ if (caller && (flags & afb_req_x2_subcall_api_session))
+ afb_context_subinit(&callreq->xreq.context, &caller->context);
+ else
+ afb_export_context_init(export, &callreq->xreq.context);
+ callreq->export = export;
+ callreq->flags = flags;
+ }
+ return callreq;
+}
+
+/******************************************************************************/
+
+static int do_sync(
+ struct afb_export *export,
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ struct json_object **object,
+ char **error,
+ char **info,
+ struct modes mode)
+{
+ struct callreq *callreq;
+ int rc;
+
+ /* allocates the request */
+ callreq = callreq_create(export, caller, api, verb, args, flags, mode);
+ if (!callreq)
+ goto interr;
+
+ /* initializes the request */
+ callreq->jobloop = NULL;
+ callreq->returned = 0;
+ callreq->status = 0;
+ callreq->object = object;
+ callreq->error = error;
+ callreq->info = info;
+
+ afb_xreq_unhooked_addref(&callreq->xreq); /* avoid early callreq destruction */
+
+ rc = jobs_enter(NULL, 0, sync_enter, callreq);
+ if (rc >= 0 && callreq->returned) {
+ rc = callreq->status;
+ afb_xreq_unhooked_unref(&callreq->xreq);
+ return rc;
+ }
+
+ afb_xreq_unhooked_unref(&callreq->xreq);
+interr:
+ return store_reply(NULL, "internal-error", NULL, object, info, error);
+}
+
+/******************************************************************************/
+
+static void do_async(
+ struct afb_export *export,
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void *callback,
+ void *closure,
+ void (*final)(void*, struct json_object*, const char*, const char*, union callback, struct afb_export*,struct afb_xreq*),
+ struct modes mode)
+{
+ struct callreq *callreq;
+
+ callreq = callreq_create(export, caller, api, verb, args, flags, mode);
+
+ if (!callreq)
+ final(closure, NULL, "internal-error", NULL, (union callback){ .any = callback }, export, caller);
+ else {
+ callreq->callback.any = callback;
+ callreq->closure = closure;
+ callreq->final = final;
+
+ afb_export_process_xreq(callreq->export, &callreq->xreq);
+ }
+}
+
+/******************************************************************************/
+
+static void final_call(
+ void *closure,
+ struct json_object *object,
+ const char *error,
+ const char *info,
+ union callback callback,
+ struct afb_export *export,
+ struct afb_xreq *caller)
+{
+ if (callback.call.x3)
+ callback.call.x3(closure, object, error, info, afb_export_to_api_x3(export));
+}
+
+static void final_subcall(
+ void *closure,
+ struct json_object *object,
+ const char *error,
+ const char *info,
+ union callback callback,
+ struct afb_export *export,
+ struct afb_xreq *caller)
+{
+ if (callback.subcall.x3)
+ callback.subcall.x3(closure, object, error, info, xreq_to_req_x2(caller));
+}
+
+/******************************************************************************/
+
+void afb_calls_call(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
+ void *closure)
+{
+ do_async(export, NULL, api, verb, args, CALLFLAGS, callback, closure, final_call, mode_async);
+}
+
+void afb_calls_hooked_call(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
+ void *closure)
+{
+ afb_hook_api_call(export, api, verb, args);
+ do_async(export, NULL, api, verb, args, CALLFLAGS, callback, closure, final_call, mode_hooked_async);
+}
+
+int afb_calls_call_sync(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **object,
+ char **error,
+ char **info)
+{
+ return do_sync(export, NULL, api, verb, args, CALLFLAGS, object, error, info, mode_sync);
+}
+
+int afb_calls_hooked_call_sync(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **object,
+ char **error,
+ char **info)
+{
+ afb_hook_api_callsync(export, api, verb, args);
+ return do_sync(export, NULL, api, verb, args, CALLFLAGS, object, error, info, mode_hooked_sync);
+}
+
+void afb_calls_subcall(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void (*callback)(void *closure, struct json_object *object, const char *error, const char * info, struct afb_req_x2 *req),
+ void *closure)
+{
+ do_async(NULL, xreq, api, verb, args, flags, callback, closure, final_subcall, mode_async);
+}
+
+void afb_calls_hooked_subcall(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void (*callback)(void *closure, struct json_object *object, const char *error, const char * info, struct afb_req_x2 *req),
+ void *closure)
+{
+ afb_hook_xreq_subcall(xreq, api, verb, args, flags);
+ do_async(NULL, xreq, api, verb, args, flags, callback, closure, final_subcall, mode_hooked_async);
+}
+
+int afb_calls_subcall_sync(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ struct json_object **object,
+ char **error,
+ char **info)
+{
+ return do_sync(NULL, xreq, api, verb, args, flags, object, error, info, mode_sync);
+}
+
+int afb_calls_hooked_subcall_sync(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ struct json_object **object,
+ char **error,
+ char **info)
+{
+ afb_hook_xreq_subcallsync(xreq, api, verb, args, flags);
+ return do_sync(NULL, xreq, api, verb, args, flags, object, error, info, mode_hooked_sync);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+static int do_legacy_sync(
+ struct afb_export *export,
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ struct json_object **object,
+ struct modes mode)
+{
+ struct callreq *callreq;
+ int rc;
+
+ /* allocates the request */
+ callreq = callreq_create(export, caller, api, verb, args, flags, mode);
+ if (!callreq)
+ goto interr;
+
+ /* initializes the request */
+ callreq->jobloop = NULL;
+ callreq->returned = 0;
+ callreq->status = 0;
+ callreq->object = object;
+
+ afb_xreq_unhooked_addref(&callreq->xreq); /* avoid early callreq destruction */
+
+ rc = jobs_enter(NULL, 0, sync_enter, callreq);
+ if (rc >= 0 && callreq->returned) {
+ rc = callreq->status;
+ afb_xreq_unhooked_unref(&callreq->xreq);
+ return rc;
+ }
+
+ afb_xreq_unhooked_unref(&callreq->xreq);
+interr:
+ if (object)
+ *object = afb_msg_json_internal_error();
+ return -1;
+}
+
+/******************************************************************************/
+
+static void do_legacy_async(
+ struct afb_export *export,
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void *callback,
+ void *closure,
+ void (*final)(void*, int, struct json_object*, union callback, struct afb_export*,struct afb_xreq*),
+ struct modes mode)
+{
+ struct callreq *callreq;
+ struct json_object *ie;
+
+ callreq = callreq_create(export, caller, api, verb, args, flags, mode);
+
+ if (!callreq) {
+ ie = afb_msg_json_internal_error();
+ final(closure, -1, ie, (union callback){ .any = callback }, export, caller);
+ json_object_put(ie);
+ } else {
+ callreq->callback.any = callback;
+ callreq->closure = closure;
+ callreq->legacy_final = final;
+
+ afb_export_process_xreq(callreq->export, &callreq->xreq);
+ }
+}
+
+/******************************************************************************/
+
+static void final_legacy_call_v12(
+ void *closure,
+ int status,
+ struct json_object *object,
+ union callback callback,
+ struct afb_export *export,
+ struct afb_xreq *caller)
+{
+ if (callback.call.legacy_v12)
+ callback.call.legacy_v12(closure, status, object);
+}
+
+static void final_legacy_call_v3(
+ void *closure,
+ int status,
+ struct json_object *object,
+ union callback callback,
+ struct afb_export *export,
+ struct afb_xreq *caller)
+{
+ if (callback.call.legacy_v3)
+ callback.call.legacy_v3(closure, status, object, afb_export_to_api_x3(export));
+}
+
+/******************************************************************************/
+
+void afb_calls_legacy_call_v12(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*),
+ void *closure)
+{
+ do_legacy_async(export, NULL, api, verb, args, CALLFLAGS, callback, closure, final_legacy_call_v12, mode_legacy_async);
+}
+
+void afb_calls_legacy_hooked_call_v12(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*),
+ void *closure)
+{
+ afb_hook_api_call(export, api, verb, args);
+ do_legacy_async(export, NULL, api, verb, args, CALLFLAGS, callback, closure, final_legacy_call_v12, mode_hooked_legacy_async);
+}
+
+void afb_calls_legacy_call_v3(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_api_x3 *),
+ void *closure)
+{
+ do_legacy_async(export, NULL, api, verb, args, CALLFLAGS, callback, closure, final_legacy_call_v3, mode_legacy_async);
+}
+
+void afb_calls_legacy_hooked_call_v3(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_api_x3 *),
+ void *closure)
+{
+ afb_hook_api_call(export, api, verb, args);
+ do_legacy_async(export, NULL, api, verb, args, CALLFLAGS, callback, closure, final_legacy_call_v3, mode_hooked_legacy_async);
+}
+
+int afb_calls_legacy_call_sync(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **result)
+{
+ return do_legacy_sync(export, NULL, api, verb, args, CALLFLAGS, result, mode_legacy_sync);
+}
+
+int afb_calls_legacy_hooked_call_sync(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **result)
+{
+ int rc;
+ struct json_object *object;
+
+ afb_hook_api_callsync(export, api, verb, args);
+ rc = do_legacy_sync(export, NULL, api, verb, args, CALLFLAGS, &object, mode_hooked_legacy_sync);
+ if (result)
+ *result = object;
+ else
+ json_object_put(object);
+ return rc;
+}
+
+/******************************************************************************/
+
+static void final_legacy_subcall_v1(
+ void *closure,
+ int status,
+ struct json_object *object,
+ union callback callback,
+ struct afb_export *export,
+ struct afb_xreq *caller)
+{
+ if (callback.subcall.legacy_v1)
+ callback.subcall.legacy_v1(closure, status, object);
+}
+
+static void final_legacy_subcall_v2(
+ void *closure,
+ int status,
+ struct json_object *object,
+ union callback callback,
+ struct afb_export *export,
+ struct afb_xreq *caller)
+{
+ if (callback.subcall.legacy_v2)
+ callback.subcall.legacy_v2(closure, status, object, xreq_to_req_x1(caller));
+}
+
+static void final_legacy_subcall_v3(
+ void *closure,
+ int status,
+ struct json_object *object,
+ union callback callback,
+ struct afb_export *export,
+ struct afb_xreq *caller)
+{
+ if (callback.subcall.legacy_v3)
+ callback.subcall.legacy_v3(closure, status, object, xreq_to_req_x2(caller));
+}
+
+/******************************************************************************/
+
+void afb_calls_legacy_subcall_v1(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*),
+ void *closure)
+{
+ do_legacy_async(NULL, caller, api, verb, args, LEGACY_SUBCALLFLAGS, callback, closure, final_legacy_subcall_v1, mode_legacy_async);
+}
+
+void afb_calls_legacy_hooked_subcall_v1(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*),
+ void *closure)
+{
+ afb_hook_xreq_subcall(caller, api, verb, args, LEGACY_SUBCALLFLAGS);
+ do_legacy_async(NULL, caller, api, verb, args, LEGACY_SUBCALLFLAGS, callback, closure, final_legacy_subcall_v1, mode_hooked_legacy_async);
+}
+
+void afb_calls_legacy_subcall_v2(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x1),
+ void *closure)
+{
+ do_legacy_async(NULL, caller, api, verb, args, LEGACY_SUBCALLFLAGS, callback, closure, final_legacy_subcall_v2, mode_legacy_async);
+}
+
+void afb_calls_legacy_hooked_subcall_v2(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x1),
+ void *closure)
+{
+ afb_hook_xreq_subcall(caller, api, verb, args, LEGACY_SUBCALLFLAGS);
+ do_legacy_async(NULL, caller, api, verb, args, LEGACY_SUBCALLFLAGS, callback, closure, final_legacy_subcall_v2, mode_hooked_legacy_async);
+}
+
+void afb_calls_legacy_subcall_v3(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x2 *),
+ void *closure)
+{
+ do_legacy_async(NULL, caller, api, verb, args, LEGACY_SUBCALLFLAGS, callback, closure, final_legacy_subcall_v3, mode_legacy_async);
+}
+
+void afb_calls_legacy_hooked_subcall_v3(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x2 *),
+ void *closure)
+{
+ afb_hook_xreq_subcall(caller, api, verb, args, LEGACY_SUBCALLFLAGS);
+ do_legacy_async(NULL, caller, api, verb, args, LEGACY_SUBCALLFLAGS, callback, closure, final_legacy_subcall_v3, mode_hooked_legacy_async);
+}
+
+int afb_calls_legacy_subcall_sync(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **result)
+{
+ return do_legacy_sync(NULL, caller, api, verb, args, LEGACY_SUBCALLFLAGS, result, mode_legacy_sync);
+}
+
+int afb_calls_legacy_hooked_subcall_sync(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **result)
+{
+ afb_hook_xreq_subcallsync(caller, api, verb, args, LEGACY_SUBCALLFLAGS);
+ return do_legacy_sync(NULL, caller, api, verb, args, LEGACY_SUBCALLFLAGS, result, mode_hooked_legacy_sync);
+}
diff --git a/src/afb-calls.h b/src/afb-calls.h
new file mode 100644
index 00000000..15b71bf2
--- /dev/null
+++ b/src/afb-calls.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2016, 2017, 2018 "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.
+ */
+
+#pragma once
+
+struct json_object;
+
+struct afb_export;
+struct afb_xreq;
+
+struct afb_api_x3;
+struct afb_req_x1;
+struct afb_req_x2;
+
+/******************************************************************************/
+
+extern
+void afb_calls_call(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
+ void *closure);
+
+extern
+void afb_calls_hooked_call(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
+ void *closure);
+
+extern
+int afb_calls_call_sync(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **object,
+ char **error,
+ char **info);
+
+extern
+int afb_calls_hooked_call_sync(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **object,
+ char **error,
+ char **info);
+
+extern
+void afb_calls_subcall(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void (*callback)(void *closure, struct json_object *object, const char *error, const char * info, struct afb_req_x2 *req),
+ void *closure);
+
+extern
+void afb_calls_hooked_subcall(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void (*callback)(void *closure, struct json_object *object, const char *error, const char * info, struct afb_req_x2 *req),
+ void *closure);
+
+extern
+int afb_calls_subcall_sync(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ struct json_object **object,
+ char **error,
+ char **info);
+
+extern
+int afb_calls_hooked_subcall_sync(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ struct json_object **object,
+ char **error,
+ char **info);
+
+/******************************************************************************/
+
+extern
+void afb_calls_legacy_call_v12(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*),
+ void *closure);
+
+extern
+void afb_calls_legacy_hooked_call_v12(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*),
+ void *closure);
+
+extern
+void afb_calls_legacy_call_v3(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_api_x3 *),
+ void *closure);
+
+extern
+void afb_calls_legacy_hooked_call_v3(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_api_x3 *),
+ void *closure);
+
+extern
+int afb_calls_legacy_call_sync(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **result);
+
+extern
+int afb_calls_legacy_hooked_call_sync(
+ struct afb_export *export,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **result);
+
+/******************************************************************************/
+
+extern
+void afb_calls_legacy_subcall_v1(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*),
+ void *closure);
+
+extern
+void afb_calls_legacy_hooked_subcall_v1(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*),
+ void *closure);
+
+extern
+void afb_calls_legacy_subcall_v2(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x1),
+ void *closure);
+
+extern
+void afb_calls_legacy_hooked_subcall_v2(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x1),
+ void *closure);
+
+extern
+void afb_calls_legacy_subcall_v3(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x2 *),
+ void *closure);
+
+extern
+void afb_calls_legacy_hooked_subcall_v3(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x2 *),
+ void *closure);
+
+extern
+int afb_calls_legacy_subcall_sync(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **result);
+
+extern
+int afb_calls_legacy_hooked_subcall_sync(
+ struct afb_xreq *caller,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **result);
diff --git a/src/afb-config.c b/src/afb-config.c
index 2a6f931f..f3f48fd6 100644
--- a/src/afb-config.c
+++ b/src/afb-config.c
@@ -23,6 +23,7 @@
#include <getopt.h>
#include <limits.h>
#include <unistd.h>
+#include <ctype.h>
#include <json-c/json.h>
@@ -30,8 +31,6 @@
#include "afb-config.h"
#include "afb-hook.h"
-#include <afb/afb-binding-v1.h>
-
#if !defined(BINDING_INSTALL_DIR)
#error "you should define BINDING_INSTALL_DIR"
#endif
@@ -51,17 +50,25 @@
# define HAS_DBUS 0
#endif
-// default
-#define DEFLT_CNTX_TIMEOUT 32000000 // default Client Connection
- // Timeout: few more than one year
-#define DEFLT_API_TIMEOUT 20 // default Plugin API Timeout [0=NoLimit
- // for Debug Only]
-#define DEFLT_CACHE_TIMEOUT 100000 // default Static File Chache
- // [Client Side Cache
- // 100000~=1day]
-#define CTX_NBCLIENTS 10 // allow a default of 10 authenticated
- // clients
+/**
+ * The default timeout of sessions in seconds
+ */
+#define DEFAULT_SESSION_TIMEOUT 32000000
+
+/**
+ * The default timeout of api calls in seconds
+ */
+#define DEFAULT_API_TIMEOUT 20
+
+/**
+ * The default timeout of cache in seconds
+ */
+#define DEFAULT_CACHE_TIMEOUT 100000
+/**
+ * The default maximum count of sessions
+ */
+#define DEFAULT_MAX_SESSION_COUNT 200
// Define command line option
#define SET_BACKGROUND 2
@@ -81,14 +88,15 @@
#define SET_WEAK_LDPATH 16
#define NO_LDPATH 17
+#if defined(KEEP_LEGACY_MODE)
#define SET_MODE 18
+#endif
#if HAS_DBUS
# define DBUS_CLIENT 20
# define DBUS_SERVICE 21
#endif
-#define SO_BINDING 22
#define SET_SESSIONMAX 23
@@ -99,11 +107,18 @@
#define SET_NO_HTTPD 28
+#define AUTO_WS 'a'
+#define AUTO_LINK 'A'
+#define SO_BINDING 'b'
#define ADD_CALL 'c'
+#if !defined(REMOVE_LEGACY_TRACE)
#define SET_TRACEDITF 'D'
+#endif
#define SET_TRACEEVT 'E'
#define SET_EXEC 'e'
#define DISPLAY_HELP 'h'
+#define SET_LOG 'l'
+#define SET_TRACEAPI 'I'
#if HAS_MONITORING
# define SET_MONITORING 'M'
#endif
@@ -111,7 +126,9 @@
#define SET_TCP_PORT 'p'
#define SET_QUIET 'q'
#define SET_RNDTOKEN 'r'
+#if !defined(REMOVE_LEGACY_TRACE)
#define SET_TRACESVC 'S'
+#endif
#define SET_TRACESES 's'
#define SET_TRACEREQ 'T'
#define SET_AUTH_TOKEN 't'
@@ -121,7 +138,15 @@
#define SET_WORK_DIR 'w'
const char shortopts[] =
- "c:D:E:ehn:p:qrS:s:T:t:u:Vvw:"
+ "a:A:b:c:"
+#if !defined(REMOVE_LEGACY_TRACE)
+ "D:"
+#endif
+ "E:ehl:n:p:qr"
+#if !defined(REMOVE_LEGACY_TRACE)
+ "S:"
+#endif
+ "s:T:t:u:Vvw:"
#if HAS_MONITORING
"M"
#endif
@@ -140,6 +165,7 @@ static AFB_options cliOptions[] = {
/* *INDENT-OFF* */
{SET_VERBOSE, 0, "verbose", "Verbose Mode, repeat to increase verbosity"},
{SET_QUIET, 0, "quiet", "Quiet Mode, repeat to decrease verbosity"},
+ {SET_LOG, 1, "log", "tune log level"},
{SET_FORGROUND, 0, "foreground", "Get all in foreground mode"},
{SET_BACKGROUND, 0, "daemon", "Get all in background mode"},
@@ -172,7 +198,9 @@ static AFB_options cliOptions[] = {
{DISPLAY_VERSION, 0, "version", "Display version and copyright"},
{DISPLAY_HELP, 0, "help", "Display this help"},
+#if defined(KEEP_LEGACY_MODE)
{SET_MODE, 1, "mode", "Set the mode: either local, remote or global"},
+#endif
#if HAS_DBUS
{DBUS_CLIENT, 1, "dbus-client", "Bind to an afb service through dbus"},
@@ -181,13 +209,19 @@ static AFB_options cliOptions[] = {
{WS_CLIENT, 1, "ws-client", "Bind to an afb service through websocket"},
{WS_SERVICE, 1, "ws-server", "Provides an afb service through websockets"},
+ {AUTO_WS, 1, "auto-ws", "Automatic bind on need to remote service through websocket"},
+ {AUTO_LINK, 1, "auto-link", "Automatic load on need to binding shared objects"},
+
{SET_SESSIONMAX, 1, "session-max", "Max count of session simultaneously [default 10]"},
{SET_TRACEREQ, 1, "tracereq", "Log the requests: no, common, extra, all"},
- {SET_TRACEDITF, 1, "traceditf", "Log the requests: no, common, extra, all"},
- {SET_TRACESVC, 1, "tracesvc", "Log the requests: no, all"},
- {SET_TRACEEVT, 1, "traceevt", "Log the requests: no, common, extra, all"},
+#if !defined(REMOVE_LEGACY_TRACE)
+ {SET_TRACEDITF, 1, "traceditf", "Log the daemons: no, common, all"},
+ {SET_TRACESVC, 1, "tracesvc", "Log the services: no, all"},
+#endif
+ {SET_TRACEEVT, 1, "traceevt", "Log the events: no, common, extra, all"},
{SET_TRACESES, 1, "traceses", "Log the sessions: no, all"},
+ {SET_TRACEAPI, 1, "traceapi", "Log the apis: no, common, api, event, all"},
{ADD_CALL, 1, "call", "call at start format of val: API/VERB:json-args"},
@@ -216,19 +250,20 @@ static struct enumdesc tracereq_desc[] = {
{ NULL, 0 }
};
+#if !defined(REMOVE_LEGACY_TRACE)
static struct enumdesc traceditf_desc[] = {
{ "no", 0 },
- { "common", afb_hook_flags_ditf_common },
- { "extra", afb_hook_flags_ditf_extra },
- { "all", afb_hook_flags_ditf_all },
+ { "common", afb_hook_flags_api_ditf_common },
+ { "all", afb_hook_flags_api_ditf_all },
{ NULL, 0 }
};
static struct enumdesc tracesvc_desc[] = {
{ "no", 0 },
- { "all", afb_hook_flags_svc_all },
+ { "all", afb_hook_flags_api_svc_all },
{ NULL, 0 }
};
+#endif
static struct enumdesc traceevt_desc[] = {
{ "no", 0 },
@@ -245,12 +280,25 @@ static struct enumdesc traceses_desc[] = {
{ NULL, 0 }
};
+static struct enumdesc traceapi_desc[] = {
+ { "no", 0 },
+ { "common", afb_hook_flags_api_common },
+ { "api", afb_hook_flags_api_api|afb_hook_flag_api_start },
+ { "event", afb_hook_flags_api_event|afb_hook_flag_api_start },
+ { "all", afb_hook_flags_api_all },
+ { NULL, 0 }
+};
+
+#if defined(KEEP_LEGACY_MODE)
+#include <afb/afb-binding-v1.h>
+
static struct enumdesc mode_desc[] = {
{ "local", AFB_MODE_LOCAL },
{ "remote", AFB_MODE_REMOTE },
{ "global", AFB_MODE_GLOBAL },
{ NULL, 0 }
};
+#endif
/*----------------------------------------------------------
| printversion
@@ -453,6 +501,53 @@ static char **make_exec(char **argv)
}
/*---------------------------------------------------------
+ | set the log levels
+ +--------------------------------------------------------- */
+
+static void set_log(char *args)
+{
+ char o = 0, s, *p, *i = args;
+ int lvl;
+
+ for(;;) switch (*i) {
+ case 0:
+ return;
+ case '+':
+ case '-':
+ o = *i;
+ /*@fallthrough@*/
+ case ' ':
+ case ',':
+ i++;
+ break;
+ default:
+ p = i;
+ while (isalpha(*p)) p++;
+ s = *p;
+ *p = 0;
+ lvl = verbose_level_of_name(i);
+ if (lvl < 0) {
+ i = strdupa(p);
+ *p = s;
+ ERROR("Bad log name '%s' in %s", i, args);
+ exit(1);
+ }
+ *p = s;
+ i = p;
+ if (o == '-')
+ verbose_sub(lvl);
+ else {
+ if (!o) {
+ verbose_clear();
+ o = '+';
+ }
+ verbose_add(lvl);
+ }
+ break;
+ }
+}
+
+/*---------------------------------------------------------
| Parse option and launch action
+--------------------------------------------------------- */
@@ -479,23 +574,27 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config)
while ((optc = getopt_long(argc, argv, shortopts, gnuOptions, NULL)) != EOF) {
switch (optc) {
case SET_VERBOSE:
- verbosity++;
+ verbose_inc();
break;
case SET_QUIET:
- verbosity--;
+ verbose_dec();
+ break;
+
+ case SET_LOG:
+ set_log(argvalstr(optc));
break;
case SET_TCP_PORT:
- config->httpdPort = argvalintdec(optc, 1024, 32767);
+ config->http_port = argvalintdec(optc, 1024, 32767);
break;
case SET_APITIMEOUT:
- config->apiTimeout = argvalintdec(optc, 0, INT_MAX);
+ config->api_timeout = argvalintdec(optc, 0, INT_MAX);
break;
case SET_CNTXTIMEOUT:
- config->cntxTimeout = argvalintdec(optc, 0, INT_MAX);
+ config->session_timeout = argvalintdec(optc, 0, INT_MAX);
break;
case SET_ROOT_DIR:
@@ -557,11 +656,11 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config)
break;
case SET_CACHE_TIMEOUT:
- config->cacheTimeout = argvalintdec(optc, 0, INT_MAX);
+ config->cache_timeout = argvalintdec(optc, 0, INT_MAX);
break;
case SET_SESSIONMAX:
- config->nbSessionMax = argvalintdec(optc, 1, INT_MAX);
+ config->max_session_count = argvalintdec(optc, 1, INT_MAX);
break;
case SET_FORGROUND:
@@ -578,9 +677,11 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config)
config->name = argvalstr(optc);
break;
+#if defined(KEEP_LEGACY_MODE)
case SET_MODE:
config->mode = argvalenum(optc, mode_desc);
break;
+#endif
#if HAS_DBUS
case DBUS_CLIENT:
@@ -604,10 +705,19 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config)
list_add(&config->so_bindings, argvalstr(optc));
break;
+ case AUTO_WS:
+ list_add(&config->auto_ws, argvalstr(optc));
+ break;
+
+ case AUTO_LINK:
+ list_add(&config->auto_link, argvalstr(optc));
+ break;
+
case SET_TRACEREQ:
config->tracereq = argvalenum(optc, tracereq_desc);
break;
+#if !defined(REMOVE_LEGACY_TRACE)
case SET_TRACEDITF:
config->traceditf = argvalenum(optc, traceditf_desc);
break;
@@ -615,6 +725,7 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config)
case SET_TRACESVC:
config->tracesvc = argvalenum(optc, tracesvc_desc);
break;
+#endif
case SET_TRACEEVT:
config->traceevt = argvalenum(optc, traceevt_desc);
@@ -624,9 +735,13 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config)
config->traceses = argvalenum(optc, traceses_desc);
break;
+ case SET_TRACEAPI:
+ config->traceapi = argvalenum(optc, traceapi_desc);
+ break;
+
case SET_NO_HTTPD:
noarg(optc);
- config->noHttpd = 1;
+ config->no_httpd = 1;
break;
case SET_EXEC:
@@ -663,28 +778,28 @@ static void parse_arguments(int argc, char **argv, struct afb_config *config)
static void fulfill_config(struct afb_config *config)
{
// default HTTP port
- if (config->httpdPort == 0)
- config->httpdPort = 1234;
+ if (config->http_port == 0)
+ config->http_port = 1234;
// default binding API timeout
- if (config->apiTimeout == 0)
- config->apiTimeout = DEFLT_API_TIMEOUT;
+ if (config->api_timeout == 0)
+ config->api_timeout = DEFAULT_API_TIMEOUT;
// default AUTH_TOKEN
if (config->random_token)
config->token = NULL;
// cache timeout default one hour
- if (config->cacheTimeout == 0)
- config->cacheTimeout = DEFLT_CACHE_TIMEOUT;
+ if (config->cache_timeout == 0)
+ config->cache_timeout = DEFAULT_CACHE_TIMEOUT;
// cache timeout default one hour
- if (config->cntxTimeout == 0)
- config->cntxTimeout = DEFLT_CNTX_TIMEOUT;
+ if (config->session_timeout == 0)
+ config->session_timeout = DEFAULT_SESSION_TIMEOUT;
// max count of sessions
- if (config->nbSessionMax == 0)
- config->nbSessionMax = CTX_NBCLIENTS;
+ if (config->max_session_count == 0)
+ config->max_session_count = DEFAULT_MAX_SESSION_COUNT;
/* set directories */
if (config->workdir == NULL)
@@ -717,6 +832,10 @@ static void fulfill_config(struct afb_config *config)
strncpy(config->console, config->uploaddir, 512);
strncat(config->console, "/AFB-console.out", 512);
}
+
+#if !defined(REMOVE_LEGACY_TRACE)
+ config->traceapi |= config->traceditf | config->tracesvc;
+#endif
}
void afb_config_dump(struct afb_config *config)
@@ -761,21 +880,26 @@ void afb_config_dump(struct afb_config *config)
V(exec)
- D(httpdPort)
- D(cacheTimeout)
- D(apiTimeout)
- D(cntxTimeout)
- D(nbSessionMax)
+ D(http_port)
+ D(cache_timeout)
+ D(api_timeout)
+ D(session_timeout)
+ D(max_session_count)
+#if defined(KEEP_LEGACY_MODE)
E(mode,mode_desc)
+#endif
E(tracereq,tracereq_desc)
+#if !defined(REMOVE_LEGACY_TRACE)
E(traceditf,traceditf_desc)
E(tracesvc,tracesvc_desc)
+#endif
E(traceevt,traceevt_desc)
E(traceses,traceses_desc)
+ E(traceapi,traceapi_desc)
B(no_ldpaths)
- B(noHttpd)
+ B(no_httpd)
B(background)
#if HAS_MONITORING
B(monitoring)
@@ -823,10 +947,13 @@ static void on_environment_enum(int *to, const char *name, struct enumdesc *desc
static void parse_environment(struct afb_config *config)
{
on_environment_enum(&config->tracereq, "AFB_TRACEREQ", tracereq_desc);
+#if !defined(REMOVE_LEGACY_TRACE)
on_environment_enum(&config->traceditf, "AFB_TRACEDITF", traceditf_desc);
on_environment_enum(&config->tracesvc, "AFB_TRACESVC", tracesvc_desc);
+#endif
on_environment_enum(&config->traceevt, "AFB_TRACEEVT", traceevt_desc);
on_environment_enum(&config->traceses, "AFB_TRACESES", traceses_desc);
+ on_environment_enum(&config->traceapi, "AFB_TRACEAPI", traceapi_desc);
on_environment_list(&config->ldpaths, "AFB_LDPATHS");
}
@@ -839,7 +966,7 @@ struct afb_config *afb_config_parse_arguments(int argc, char **argv)
parse_environment(result);
parse_arguments(argc, argv, result);
fulfill_config(result);
- if (verbosity >= 3)
+ if (verbose_wants(Log_Level_Info))
afb_config_dump(result);
return result;
}
@@ -895,21 +1022,26 @@ struct json_object *afb_config_json(struct afb_config *config)
V(exec)
- D(httpdPort)
- D(cacheTimeout)
- D(apiTimeout)
- D(cntxTimeout)
- D(nbSessionMax)
+ D(http_port)
+ D(cache_timeout)
+ D(api_timeout)
+ D(session_timeout)
+ D(max_session_count)
+#if defined(KEEP_LEGACY_MODE)
E(mode,mode_desc)
+#endif
E(tracereq,tracereq_desc)
+#if !defined(REMOVE_LEGACY_TRACE)
E(traceditf,traceditf_desc)
E(tracesvc,tracesvc_desc)
+#endif
E(traceevt,traceevt_desc)
E(traceses,traceses_desc)
+ E(traceapi,traceapi_desc)
B(no_ldpaths)
- B(noHttpd)
+ B(no_httpd)
B(background)
#if HAS_MONITORING
B(monitoring)
diff --git a/src/afb-config.h b/src/afb-config.h
index 89b1f78e..30fd398c 100644
--- a/src/afb-config.h
+++ b/src/afb-config.h
@@ -22,22 +22,27 @@ struct json_object;
* other definitions ---------------------------------------------------
*/
+/**
+ * list of configuration values
+ */
struct afb_config_list {
struct afb_config_list *next;
char *value;
};
-// main config structure
+/**
+ * main config structure
+ */
struct afb_config {
- char *console; // console device name (can be a file or a tty)
- char *rootdir; // base dir for files
- char *roothttp; // directory for http files
- char *rootbase; // Angular HTML5 base URL
- char *rootapi; // Base URL for REST APIs
- char *workdir; // where to run the program
- char *uploaddir; // where to store transient files
- char *token; // initial authentication token [default NULL no session]
- char *name; /* name to set to the daemon */
+ char *console; /*< console device name (can be a file or a tty) */
+ char *rootdir; /*< base dir for files */
+ char *roothttp; /*< directory for http files */
+ char *rootbase; /*< Angular HTML5 base URL */
+ char *rootapi; /*< Base URL for REST APIs */
+ char *workdir; /*< where to run the program */
+ char *uploaddir; /*< where to store transient files */
+ char *token; /*< initial authentication token [default NULL no session] */
+ char *name; /*< name to set to the daemon */
struct afb_config_list *aliases;
#if defined(WITH_DBUS_TRANSPARENCY)
@@ -50,32 +55,39 @@ struct afb_config {
struct afb_config_list *ldpaths;
struct afb_config_list *weak_ldpaths;
struct afb_config_list *calls;
+ struct afb_config_list *auto_ws;
+ struct afb_config_list *auto_link;
char **exec;
/* integers */
- int httpdPort;
- int cacheTimeout;
- int apiTimeout;
- int cntxTimeout; // Client Session Context timeout
- int nbSessionMax; // max count of sessions
+ int http_port;
+ int cache_timeout;
+ int api_timeout;
+ int session_timeout; /*< session timeout */
+ int max_session_count; /*< max count of sessions */
/* enums */
+#if defined(KEEP_LEGACY_MODE)
int mode; // mode of listening
+#endif
int tracereq;
+#if !defined(REMOVE_LEGACY_TRACE)
int traceditf;
int tracesvc;
+#endif
int traceevt;
int traceses;
+ int traceapi;
/* booleans */
- unsigned no_ldpaths: 1; /* disable default ldpaths */
- unsigned noHttpd: 1;
- unsigned background: 1; /* run in backround mode */
+ unsigned no_ldpaths: 1; /**< disable default ldpaths */
+ unsigned no_httpd: 1;
+ unsigned background: 1; /**< run in backround mode */
+ unsigned random_token: 1; /**< expects a random token */
#if defined(WITH_MONITORING_OPTION)
- unsigned monitoring: 1; /* activates monitoring */
+ unsigned monitoring: 1; /**< activates monitoring */
#endif
- unsigned random_token: 1; /* expects a random token */
};
extern struct afb_config *afb_config_parse_arguments(int argc, char **argv);
diff --git a/src/afb-context.c b/src/afb-context.c
index 13733ce6..6b3d6e9d 100644
--- a/src/afb-context.c
+++ b/src/afb-context.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
+#include <errno.h>
#include "afb-session.h"
#include "afb-context.h"
@@ -184,10 +185,12 @@ static inline unsigned ptr2loa(void *ptr)
int afb_context_change_loa(struct afb_context *context, unsigned loa)
{
- if (!context->validated || loa > 7)
- return 0;
+ if (!context->validated || loa > 7) {
+ errno = EINVAL;
+ return -1;
+ }
- return 0 <= afb_session_set_cookie(context->session, loa_key(context), loa2ptr(loa), NULL);
+ return afb_session_set_cookie(context->session, loa_key(context), loa2ptr(loa), NULL);
}
unsigned afb_context_get_loa(struct afb_context *context)
@@ -195,5 +198,3 @@ unsigned afb_context_get_loa(struct afb_context *context)
assert(context->session != NULL);
return ptr2loa(afb_session_get_cookie(context->session, loa_key(context)));
}
-
-
diff --git a/src/afb-cred.c b/src/afb-cred.c
index f09d4441..b7b3175e 100644
--- a/src/afb-cred.c
+++ b/src/afb-cred.c
@@ -18,6 +18,7 @@
#define _GNU_SOURCE
#include <stdlib.h>
+#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
@@ -26,6 +27,8 @@
#include <sys/socket.h>
#include "afb-cred.h"
+#include "verbose.h"
+
#define MAX_LABEL_LENGTH 1024
@@ -46,6 +49,10 @@
# define DEFAULT_PEERCRED_PID 0 /* no process */
#endif
+static char on_behalf_credential_permission[] = "urn:AGL:permission:*:partner:on-behalf-credentials";
+static char export_format[] = "%x:%x:%x-%s";
+static char import_format[] = "%x:%x:%x-%n";
+
static struct afb_cred *current;
static struct afb_cred *mkcred(uid_t uid, gid_t gid, pid_t pid, const char *label, size_t size)
@@ -70,6 +77,7 @@ static struct afb_cred *mkcred(uid_t uid, gid_t gid, pid_t pid, const char *labe
cred->uid = uid;
cred->gid = gid;
cred->pid = pid;
+ cred->exported = NULL;
dest = (char*)(&cred[1]);
cred->user = dest;
while(i)
@@ -175,3 +183,105 @@ struct afb_cred *afb_cred_current()
return afb_cred_addref(current);
}
+const char *afb_cred_export(struct afb_cred *cred)
+{
+ int rc;
+
+ if (!cred->exported) {
+ rc = asprintf((char**)&cred->exported,
+ export_format,
+ (int)cred->uid,
+ (int)cred->gid,
+ (int)cred->pid,
+ cred->label);
+ if (rc < 0) {
+ errno = ENOMEM;
+ cred->exported = NULL;
+ }
+ }
+ return cred->exported;
+}
+
+struct afb_cred *afb_cred_import(const char *string)
+{
+ struct afb_cred *cred;
+ int rc, uid, gid, pid, pos;
+
+ rc = sscanf(string, import_format, &uid, &gid, &pid, &pos);
+ if (rc == 3)
+ cred = afb_cred_create((uid_t)uid, (gid_t)gid, (pid_t)pid, &string[pos]);
+ else {
+ errno = EINVAL;
+ cred = NULL;
+ }
+ return cred;
+}
+
+struct afb_cred *afb_cred_mixed_on_behalf_import(struct afb_cred *cred, const char *context, const char *exported)
+
+{
+ struct afb_cred *imported;
+ if (exported) {
+ if (afb_cred_has_permission(cred, on_behalf_credential_permission, context)) {
+ imported = afb_cred_import(exported);
+ if (imported)
+ return imported;
+ ERROR("Can't import on behalf credentials: %m");
+ } else {
+ ERROR("On behalf credentials refused");
+ }
+ }
+ return afb_cred_addref(cred);
+}
+
+/*********************************************************************************/
+#ifdef BACKEND_PERMISSION_IS_CYNARA
+
+#include <pthread.h>
+#include <cynara-client.h>
+
+static cynara *handle;
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int afb_cred_has_permission(struct afb_cred *cred, const char *permission, const char *context)
+{
+ int rc;
+
+ if (!cred) {
+ /* case of permission for self */
+ return 1;
+ }
+ if (!permission) {
+ ERROR("Got a null permission!");
+ return 0;
+ }
+
+ /* cynara isn't reentrant */
+ pthread_mutex_lock(&mutex);
+
+ /* lazy initialisation */
+ if (!handle) {
+ rc = cynara_initialize(&handle, NULL);
+ if (rc != CYNARA_API_SUCCESS) {
+ handle = NULL;
+ ERROR("cynara initialisation failed with code %d", rc);
+ return 0;
+ }
+ }
+
+ /* query cynara permission */
+ rc = cynara_check(handle, cred->label, context ?: "", cred->user, permission);
+
+ pthread_mutex_unlock(&mutex);
+ return rc == CYNARA_API_ACCESS_ALLOWED;
+}
+
+/*********************************************************************************/
+#else
+int afb_cred_has_permission(struct afb_cred *cred, const char *permission, const char *context)
+{
+ WARNING("Granting permission %s by default of backend", permission ?: "(null)");
+ return !!permission;
+}
+#endif
+
diff --git a/src/afb-cred.h b/src/afb-cred.h
index 7ee4723c..614fa4bc 100644
--- a/src/afb-cred.h
+++ b/src/afb-cred.h
@@ -28,6 +28,7 @@ struct afb_cred
const char *user;
const char *label;
const char *id;
+ const char *exported;
};
extern struct afb_cred *afb_cred_current();
@@ -36,4 +37,10 @@ extern struct afb_cred *afb_cred_create_for_socket(int fd);
extern struct afb_cred *afb_cred_addref(struct afb_cred *cred);
extern void afb_cred_unref(struct afb_cred *cred);
+extern int afb_cred_has_permission(struct afb_cred *cred, const char *permission, const char *context);
+
+extern const char *afb_cred_export(struct afb_cred *cred);
+extern struct afb_cred *afb_cred_import(const char *string);
+
+extern struct afb_cred *afb_cred_mixed_on_behalf_import(struct afb_cred *cred, const char *context, const char *exported);
diff --git a/src/afb-evt.c b/src/afb-evt.c
index 6b94ce8c..ed3e4672 100644
--- a/src/afb-evt.c
+++ b/src/afb-evt.c
@@ -24,8 +24,8 @@
#include <pthread.h>
#include <json-c/json.h>
-#include <afb/afb-eventid-itf.h>
-#include <afb/afb-event.h>
+#include <afb/afb-event-x2-itf.h>
+#include <afb/afb-event-x1.h>
#include "afb-evt.h"
#include "afb-hook.h"
@@ -50,8 +50,8 @@ struct afb_evt_listener {
/* head of the list of events listened */
struct afb_evt_watch *watchs;
- /* mutex of the listener */
- pthread_mutex_t mutex;
+ /* rwlock of the listener */
+ pthread_rwlock_t rwlock;
/* count of reference to the listener */
int refcount;
@@ -63,7 +63,7 @@ struct afb_evt_listener {
struct afb_evtid {
/* interface */
- struct afb_eventid eventid;
+ struct afb_event_x2 eventid;
/* next event */
struct afb_evtid *next;
@@ -71,8 +71,8 @@ struct afb_evtid {
/* head of the list of listeners watching the event */
struct afb_evt_watch *watchs;
- /* mutex of the event */
- pthread_mutex_t mutex;
+ /* rwlock of the event */
+ pthread_rwlock_t rwlock;
/* hooking */
int hookflags;
@@ -109,7 +109,7 @@ struct afb_evt_watch {
};
/* the interface for events */
-static struct afb_eventid_itf afb_evt_eventid_itf = {
+static struct afb_event_x2_itf afb_evt_event_x2_itf = {
.broadcast = (void*)afb_evt_evtid_broadcast,
.push = (void*)afb_evt_evtid_push,
.unref = (void*)afb_evt_evtid_unref,
@@ -118,7 +118,7 @@ static struct afb_eventid_itf afb_evt_eventid_itf = {
};
/* the interface for events */
-static struct afb_eventid_itf afb_evt_hooked_eventid_itf = {
+static struct afb_event_x2_itf afb_evt_hooked_eventid_itf = {
.broadcast = (void*)afb_evt_evtid_hooked_broadcast,
.push = (void*)afb_evt_evtid_hooked_push,
.unref = (void*)afb_evt_evtid_hooked_unref,
@@ -127,11 +127,11 @@ static struct afb_eventid_itf afb_evt_hooked_eventid_itf = {
};
/* head of the list of listeners */
-static pthread_mutex_t listeners_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_rwlock_t listeners_rwlock = PTHREAD_RWLOCK_INITIALIZER;
static struct afb_evt_listener *listeners = NULL;
/* handling id of events */
-static pthread_mutex_t events_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_rwlock_t events_rwlock = PTHREAD_RWLOCK_INITIALIZER;
static struct afb_evtid *evtids = NULL;
static int event_id_counter = 0;
static int event_id_wrapped = 0;
@@ -147,7 +147,8 @@ static int broadcast(const char *event, struct json_object *obj, int id)
struct afb_evt_listener *listener;
result = 0;
- pthread_mutex_lock(&listeners_mutex);
+
+ pthread_rwlock_rdlock(&listeners_rwlock);
listener = listeners;
while(listener) {
if (listener->itf->broadcast != NULL) {
@@ -156,7 +157,7 @@ static int broadcast(const char *event, struct json_object *obj, int id)
}
listener = listener->next;
}
- pthread_mutex_unlock(&listeners_mutex);
+ pthread_rwlock_unlock(&listeners_rwlock);
json_object_put(obj);
return result;
}
@@ -228,7 +229,7 @@ int afb_evt_evtid_push(struct afb_evtid *evtid, struct json_object *obj)
struct afb_evt_listener *listener;
result = 0;
- pthread_mutex_lock(&evtid->mutex);
+ pthread_rwlock_rdlock(&evtid->rwlock);
watch = evtid->watchs;
while(watch) {
listener = watch->listener;
@@ -239,7 +240,7 @@ int afb_evt_evtid_push(struct afb_evtid *evtid, struct json_object *obj)
}
watch = watch->next_by_evtid;
}
- pthread_mutex_unlock(&evtid->mutex);
+ pthread_rwlock_unlock(&evtid->rwlock);
json_object_put(obj);
return result;
}
@@ -252,6 +253,7 @@ int afb_evt_evtid_push(struct afb_evtid *evtid, struct json_object *obj)
*/
int afb_evt_evtid_hooked_push(struct afb_evtid *evtid, struct json_object *obj)
{
+
int result;
/* lease the object */
@@ -319,7 +321,7 @@ struct afb_evtid *afb_evt_evtid_create(const char *fullname)
goto error;
/* allocates the id */
- pthread_mutex_lock(&events_mutex);
+ pthread_rwlock_wrlock(&events_rwlock);
do {
if (++event_id_counter < 0) {
event_id_wrapped = 1;
@@ -335,15 +337,16 @@ struct afb_evtid *afb_evt_evtid_create(const char *fullname)
/* initialize the event */
memcpy(evtid->fullname, fullname, len + 1);
evtid->next = evtids;
+ evtid->refcount = 1;
evtid->watchs = NULL;
evtid->id = event_id_counter;
- pthread_mutex_init(&evtid->mutex, NULL);
+ pthread_rwlock_init(&evtid->rwlock, NULL);
evtids = evtid;
evtid->hookflags = afb_hook_flags_evt(evtid->fullname);
- evtid->eventid.itf = evtid->hookflags ? &afb_evt_hooked_eventid_itf : &afb_evt_eventid_itf;
+ evtid->eventid.itf = evtid->hookflags ? &afb_evt_hooked_eventid_itf : &afb_evt_event_x2_itf;
if (evtid->hookflags & afb_hook_flag_evt_create)
afb_hook_evt_create(evtid->fullname, evtid->id);
- pthread_mutex_unlock(&events_mutex);
+ pthread_rwlock_unlock(&events_rwlock);
/* returns the event */
return evtid;
@@ -402,14 +405,14 @@ void afb_evt_evtid_unref(struct afb_evtid *evtid)
if (!__atomic_sub_fetch(&evtid->refcount, 1, __ATOMIC_RELAXED)) {
/* unlinks the event if valid! */
- pthread_mutex_lock(&events_mutex);
+ pthread_rwlock_wrlock(&events_rwlock);
found = 0;
prv = &evtids;
while (*prv && !(found = (*prv == evtid)))
prv = &(*prv)->next;
if (found)
*prv = evtid->next;
- pthread_mutex_unlock(&events_mutex);
+ pthread_rwlock_unlock(&events_rwlock);
/* destroys the event */
if (!found)
@@ -418,15 +421,15 @@ void afb_evt_evtid_unref(struct afb_evtid *evtid)
/* removes all watchers */
while(evtid->watchs != NULL) {
listener = evtid->watchs->listener;
- pthread_mutex_lock(&listener->mutex);
- pthread_mutex_lock(&evtid->mutex);
+ pthread_rwlock_wrlock(&listener->rwlock);
+ pthread_rwlock_wrlock(&evtid->rwlock);
remove_watch(evtid->watchs);
- pthread_mutex_unlock(&evtid->mutex);
- pthread_mutex_unlock(&listener->mutex);
+ pthread_rwlock_unlock(&evtid->rwlock);
+ pthread_rwlock_unlock(&listener->rwlock);
}
/* free */
- pthread_mutex_destroy(&evtid->mutex);
+ pthread_rwlock_destroy(&evtid->rwlock);
free(evtid);
}
}
@@ -489,7 +492,7 @@ struct afb_evt_listener *afb_evt_listener_create(const struct afb_evt_itf *itf,
struct afb_evt_listener *listener;
/* search if an instance already exists */
- pthread_mutex_lock(&listeners_mutex);
+ pthread_rwlock_wrlock(&listeners_rwlock);
listener = listeners;
while (listener != NULL) {
if (listener->itf == itf && listener->closure == closure) {
@@ -507,12 +510,12 @@ struct afb_evt_listener *afb_evt_listener_create(const struct afb_evt_itf *itf,
listener->closure = closure;
listener->watchs = NULL;
listener->refcount = 1;
- pthread_mutex_init(&listener->mutex, NULL);
+ pthread_rwlock_init(&listener->rwlock, NULL);
listener->next = listeners;
listeners = listener;
}
found:
- pthread_mutex_unlock(&listeners_mutex);
+ pthread_rwlock_unlock(&listeners_rwlock);
return listener;
}
@@ -537,25 +540,25 @@ void afb_evt_listener_unref(struct afb_evt_listener *listener)
if (!__atomic_sub_fetch(&listener->refcount, 1, __ATOMIC_RELAXED)) {
/* unlink the listener */
- pthread_mutex_lock(&listeners_mutex);
+ pthread_rwlock_wrlock(&listeners_rwlock);
prv = &listeners;
while (*prv != listener)
prv = &(*prv)->next;
*prv = listener->next;
- pthread_mutex_unlock(&listeners_mutex);
+ pthread_rwlock_unlock(&listeners_rwlock);
/* remove the watchers */
- pthread_mutex_lock(&listener->mutex);
+ pthread_rwlock_wrlock(&listener->rwlock);
while (listener->watchs != NULL) {
evtid = listener->watchs->evtid;
- pthread_mutex_lock(&evtid->mutex);
+ pthread_rwlock_wrlock(&evtid->rwlock);
remove_watch(listener->watchs);
- pthread_mutex_unlock(&evtid->mutex);
+ pthread_rwlock_unlock(&evtid->rwlock);
}
- pthread_mutex_unlock(&listener->mutex);
+ pthread_rwlock_unlock(&listener->rwlock);
/* free the listener */
- pthread_mutex_destroy(&listener->mutex);
+ pthread_rwlock_destroy(&listener->rwlock);
free(listener);
}
}
@@ -575,7 +578,7 @@ int afb_evt_watch_add_evtid(struct afb_evt_listener *listener, struct afb_evtid
}
/* search the existing watch for the listener */
- pthread_mutex_lock(&listener->mutex);
+ pthread_rwlock_wrlock(&listener->rwlock);
watch = listener->watchs;
while(watch != NULL) {
if (watch->evtid == evtid)
@@ -586,7 +589,7 @@ int afb_evt_watch_add_evtid(struct afb_evt_listener *listener, struct afb_evtid
/* not found, allocate a new */
watch = malloc(sizeof *watch);
if (watch == NULL) {
- pthread_mutex_unlock(&listener->mutex);
+ pthread_rwlock_unlock(&listener->rwlock);
errno = ENOMEM;
return -1;
}
@@ -597,16 +600,16 @@ int afb_evt_watch_add_evtid(struct afb_evt_listener *listener, struct afb_evtid
watch->listener = listener;
watch->next_by_listener = listener->watchs;
listener->watchs = watch;
- pthread_mutex_lock(&evtid->mutex);
+ pthread_rwlock_wrlock(&evtid->rwlock);
watch->next_by_evtid = evtid->watchs;
evtid->watchs = watch;
- pthread_mutex_unlock(&evtid->mutex);
+ pthread_rwlock_unlock(&evtid->rwlock);
found:
if (watch->activity == 0 && listener->itf->add != NULL)
listener->itf->add(listener->closure, evtid->fullname, evtid->id);
watch->activity++;
- pthread_mutex_unlock(&listener->mutex);
+ pthread_rwlock_unlock(&listener->rwlock);
return 0;
}
@@ -620,7 +623,7 @@ int afb_evt_watch_sub_evtid(struct afb_evt_listener *listener, struct afb_evtid
struct afb_evt_watch *watch;
/* search the existing watch */
- pthread_mutex_lock(&listener->mutex);
+ pthread_rwlock_wrlock(&listener->rwlock);
watch = listener->watchs;
while(watch != NULL) {
if (watch->evtid == evtid) {
@@ -629,12 +632,12 @@ int afb_evt_watch_sub_evtid(struct afb_evt_listener *listener, struct afb_evtid
if (watch->activity == 0 && listener->itf->remove != NULL)
listener->itf->remove(listener->closure, evtid->fullname, evtid->id);
}
- pthread_mutex_unlock(&listener->mutex);
+ pthread_rwlock_unlock(&listener->rwlock);
return 0;
}
watch = watch->next_by_listener;
}
- pthread_mutex_unlock(&listener->mutex);
+ pthread_rwlock_unlock(&listener->rwlock);
errno = ENOENT;
return -1;
}
@@ -646,20 +649,20 @@ void afb_evt_update_hooks()
{
struct afb_evtid *evtid;
- pthread_mutex_lock(&events_mutex);
+ pthread_rwlock_rdlock(&events_rwlock);
for (evtid = evtids ; evtid ; evtid = evtid->next) {
evtid->hookflags = afb_hook_flags_evt(evtid->fullname);
- evtid->eventid.itf = evtid->hookflags ? &afb_evt_hooked_eventid_itf : &afb_evt_eventid_itf;
+ evtid->eventid.itf = evtid->hookflags ? &afb_evt_hooked_eventid_itf : &afb_evt_event_x2_itf;
}
- pthread_mutex_unlock(&events_mutex);
+ pthread_rwlock_unlock(&events_rwlock);
}
-inline struct afb_evtid *afb_evt_eventid_to_evtid(struct afb_eventid *eventid)
+inline struct afb_evtid *afb_evt_event_x2_to_evtid(struct afb_event_x2 *eventid)
{
return (struct afb_evtid*)eventid;
}
-inline struct afb_eventid *afb_evt_eventid_from_evtid(struct afb_evtid *evtid)
+inline struct afb_event_x2 *afb_evt_event_x2_from_evtid(struct afb_evtid *evtid)
{
return &evtid->eventid;
}
@@ -668,35 +671,35 @@ inline struct afb_eventid *afb_evt_eventid_from_evtid(struct afb_evtid *evtid)
* Creates an event of 'fullname' and returns it.
* Returns an event with closure==NULL in case of error.
*/
-struct afb_eventid *afb_evt_eventid_create(const char *fullname)
+struct afb_event_x2 *afb_evt_event_x2_create(const char *fullname)
{
- return afb_evt_eventid_from_evtid(afb_evt_evtid_create(fullname));
+ return afb_evt_event_x2_from_evtid(afb_evt_evtid_create(fullname));
}
/*
* Creates an event of name 'prefix'/'name' and returns it.
* Returns an event with closure==NULL in case of error.
*/
-struct afb_eventid *afb_evt_eventid_create2(const char *prefix, const char *name)
+struct afb_event_x2 *afb_evt_event_x2_create2(const char *prefix, const char *name)
{
- return afb_evt_eventid_from_evtid(afb_evt_evtid_create2(prefix, name));
+ return afb_evt_event_x2_from_evtid(afb_evt_evtid_create2(prefix, name));
}
/*
* Returns the fullname of the 'eventid'
*/
-const char *afb_evt_eventid_fullname(struct afb_eventid *eventid)
+const char *afb_evt_event_x2_fullname(struct afb_event_x2 *eventid)
{
- struct afb_evtid *evtid = afb_evt_eventid_to_evtid(eventid);
+ struct afb_evtid *evtid = afb_evt_event_x2_to_evtid(eventid);
return evtid ? evtid->fullname : NULL;
}
/*
* Returns the id of the 'eventid'
*/
-int afb_evt_eventid_id(struct afb_eventid *eventid)
+int afb_evt_event_x2_id(struct afb_event_x2 *eventid)
{
- struct afb_evtid *evtid = afb_evt_eventid_to_evtid(eventid);
+ struct afb_evtid *evtid = afb_evt_event_x2_to_evtid(eventid);
return evtid ? evtid->id : 0;
}
@@ -704,9 +707,9 @@ int afb_evt_eventid_id(struct afb_eventid *eventid)
* Makes the 'listener' watching 'eventid'
* Returns 0 in case of success or else -1.
*/
-int afb_evt_eventid_add_watch(struct afb_evt_listener *listener, struct afb_eventid *eventid)
+int afb_evt_event_x2_add_watch(struct afb_evt_listener *listener, struct afb_event_x2 *eventid)
{
- struct afb_evtid *evtid = afb_evt_eventid_to_evtid(eventid);
+ struct afb_evtid *evtid = afb_evt_event_x2_to_evtid(eventid);
/* check parameter */
if (!evtid) {
@@ -722,9 +725,9 @@ int afb_evt_eventid_add_watch(struct afb_evt_listener *listener, struct afb_even
* Avoids the 'listener' to watch 'eventid'
* Returns 0 in case of success or else -1.
*/
-int afb_evt_eventid_remove_watch(struct afb_evt_listener *listener, struct afb_eventid *eventid)
+int afb_evt_event_x2_remove_watch(struct afb_evt_listener *listener, struct afb_event_x2 *eventid)
{
- struct afb_evtid *evtid = afb_evt_eventid_to_evtid(eventid);
+ struct afb_evtid *evtid = afb_evt_event_x2_to_evtid(eventid);
/* check parameter */
if (!evtid) {
@@ -736,41 +739,41 @@ int afb_evt_eventid_remove_watch(struct afb_evt_listener *listener, struct afb_e
return afb_evt_watch_sub_evtid(listener, evtid);
}
-int afb_evt_eventid_push(struct afb_eventid *eventid, struct json_object *object)
+int afb_evt_event_x2_push(struct afb_event_x2 *eventid, struct json_object *object)
{
- struct afb_evtid *evtid = afb_evt_eventid_to_evtid(eventid);
+ struct afb_evtid *evtid = afb_evt_event_x2_to_evtid(eventid);
if (evtid)
return afb_evt_evtid_hooked_push(evtid, object);
json_object_put(object);
return 0;
}
-int afb_evt_eventid_unhooked_push(struct afb_eventid *eventid, struct json_object *object)
+int afb_evt_event_x2_unhooked_push(struct afb_event_x2 *eventid, struct json_object *object)
{
- struct afb_evtid *evtid = afb_evt_eventid_to_evtid(eventid);
+ struct afb_evtid *evtid = afb_evt_event_x2_to_evtid(eventid);
if (evtid)
return afb_evt_evtid_push(evtid, object);
json_object_put(object);
return 0;
}
-struct afb_event afb_evt_event_from_evtid(struct afb_evtid *evtid)
+struct afb_event_x1 afb_evt_event_from_evtid(struct afb_evtid *evtid)
{
return evtid
- ? (struct afb_event){ .itf = &afb_evt_hooked_eventid_itf, .closure = &evtid->eventid }
- : (struct afb_event){ .itf = NULL, .closure = NULL };
+ ? (struct afb_event_x1){ .itf = &afb_evt_hooked_eventid_itf, .closure = &evtid->eventid }
+ : (struct afb_event_x1){ .itf = NULL, .closure = NULL };
}
-void afb_evt_eventid_unref(struct afb_eventid *eventid)
+void afb_evt_event_x2_unref(struct afb_event_x2 *eventid)
{
- struct afb_evtid *evtid = afb_evt_eventid_to_evtid(eventid);
+ struct afb_evtid *evtid = afb_evt_event_x2_to_evtid(eventid);
if (evtid)
afb_evt_evtid_unref(evtid);
}
-struct afb_eventid *afb_evt_eventid_addref(struct afb_eventid *eventid)
+struct afb_event_x2 *afb_evt_event_x2_addref(struct afb_event_x2 *eventid)
{
- struct afb_evtid *evtid = afb_evt_eventid_to_evtid(eventid);
+ struct afb_evtid *evtid = afb_evt_event_x2_to_evtid(eventid);
if (evtid)
afb_evt_evtid_addref(evtid);
return eventid;
diff --git a/src/afb-evt.h b/src/afb-evt.h
index c3999df2..ceb1b1b9 100644
--- a/src/afb-evt.h
+++ b/src/afb-evt.h
@@ -17,8 +17,8 @@
#pragma once
-struct afb_event;
-struct afb_eventid;
+struct afb_event_x1;
+struct afb_event_x2;
struct afb_evtid;
struct afb_session;
struct json_object;
@@ -66,20 +66,20 @@ extern int afb_evt_watch_sub_evtid(struct afb_evt_listener *listener, struct afb
extern void afb_evt_update_hooks();
-extern struct afb_eventid *afb_evt_eventid_create(const char *fullname);
-extern struct afb_eventid *afb_evt_eventid_create2(const char *prefix, const char *name);
-extern const char *afb_evt_eventid_fullname(struct afb_eventid *eventid);
-extern int afb_evt_eventid_id(struct afb_eventid *eventid);
-extern struct afb_eventid *afb_evt_eventid_addref(struct afb_eventid *eventid);
-extern void afb_evt_eventid_unref(struct afb_eventid *eventid);
+extern struct afb_event_x2 *afb_evt_event_x2_create(const char *fullname);
+extern struct afb_event_x2 *afb_evt_event_x2_create2(const char *prefix, const char *name);
+extern const char *afb_evt_event_x2_fullname(struct afb_event_x2 *event);
+extern int afb_evt_event_x2_id(struct afb_event_x2 *eventid);
+extern struct afb_event_x2 *afb_evt_event_x2_addref(struct afb_event_x2 *eventid);
+extern void afb_evt_event_x2_unref(struct afb_event_x2 *eventid);
-extern int afb_evt_eventid_push(struct afb_eventid *eventid, struct json_object *object);
-extern int afb_evt_eventid_unhooked_push(struct afb_eventid *eventid, struct json_object *object);
+extern int afb_evt_event_x2_push(struct afb_event_x2 *eventid, struct json_object *object);
+extern int afb_evt_event_x2_unhooked_push(struct afb_event_x2 *eventid, struct json_object *object);
-extern int afb_evt_eventid_add_watch(struct afb_evt_listener *listener, struct afb_eventid *eventid);
-extern int afb_evt_eventid_remove_watch(struct afb_evt_listener *listener, struct afb_eventid *eventid);
+extern int afb_evt_event_x2_add_watch(struct afb_evt_listener *listener, struct afb_event_x2 *eventid);
+extern int afb_evt_event_x2_remove_watch(struct afb_evt_listener *listener, struct afb_event_x2 *eventid);
-extern struct afb_evtid *afb_evt_eventid_to_evtid(struct afb_eventid *eventid);
-extern struct afb_eventid *afb_evt_eventid_from_evtid(struct afb_evtid *evtid);
-extern struct afb_event afb_evt_event_from_evtid(struct afb_evtid *evtid);
+extern struct afb_evtid *afb_evt_event_x2_to_evtid(struct afb_event_x2 *eventid);
+extern struct afb_event_x2 *afb_evt_event_x2_from_evtid(struct afb_evtid *evtid);
+extern struct afb_event_x1 afb_evt_event_from_evtid(struct afb_evtid *evtid);
diff --git a/src/afb-export.c b/src/afb-export.c
index 12adf08d..fbf77f86 100644
--- a/src/afb-export.c
+++ b/src/afb-export.c
@@ -20,6 +20,8 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <fnmatch.h>
+#include <ctype.h>
#include <json-c/json.h>
@@ -28,7 +30,11 @@
#include "afb-api.h"
#include "afb-apiset.h"
-#include "afb-api-dyn.h"
+#if defined(WITH_LEGACY_BINDING_V1)
+#include "afb-api-so-v1.h"
+#endif
+#include "afb-api-so-v2.h"
+#include "afb-api-v3.h"
#include "afb-common.h"
#include "afb-systemd.h"
#include "afb-cred.h"
@@ -38,20 +44,48 @@
#include "afb-msg-json.h"
#include "afb-session.h"
#include "afb-xreq.h"
+#include "afb-calls.h"
#include "jobs.h"
#include "verbose.h"
/*************************************************************************
- * internal types and structures
+ * internal types
************************************************************************/
+/*
+ * structure for handling events
+ */
+struct event_handler
+{
+ /* link to the next event handler of the list */
+ struct event_handler *next;
+
+ /* function to call on the case of the event */
+ void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
+
+ /* closure for the callback */
+ void *closure;
+
+ /* the handled pattern */
+ char pattern[1];
+};
+
+/*
+ * Actually supported versions
+ */
enum afb_api_version
{
- Api_Version_Dyn = 0,
+ Api_Version_None = 0,
+#if defined(WITH_LEGACY_BINDING_V1)
Api_Version_1 = 1,
+#endif
Api_Version_2 = 2,
+ Api_Version_3 = 3
};
+/*
+ * The states of exported APIs
+ */
enum afb_api_state
{
Api_State_Pre_Init,
@@ -59,13 +93,16 @@ enum afb_api_state
Api_State_Run
};
+/*
+ * structure of the exported API
+ */
struct afb_export
{
/* keep it first */
- struct afb_dynapi dynapi;
+ struct afb_api_x3 api;
- /* name of the api */
- char *apiname;
+ /* reference count */
+ int refcount;
/* version of the api */
unsigned version: 4;
@@ -73,124 +110,157 @@ struct afb_export
/* current state */
unsigned state: 4;
+ /* declared */
+ unsigned declared: 1;
+
+ /* unsealed */
+ unsigned unsealed: 1;
+
/* hooking flags */
int hookditf;
int hooksvc;
- /* dynamic api */
- struct afb_api_dyn *apidyn;
-
/* session for service */
struct afb_session *session;
- /* apiset for service */
- struct afb_apiset *apiset;
+ /* apiset the API is declared in */
+ struct afb_apiset *declare_set;
+
+ /* apiset for calls */
+ struct afb_apiset *call_set;
/* event listener for service or NULL */
struct afb_evt_listener *listener;
+ /* event handler list */
+ struct event_handler *event_handlers;
+
+ /* internal descriptors */
+ union {
+#if defined(WITH_LEGACY_BINDING_V1)
+ struct afb_binding_v1 *v1;
+#endif
+ const struct afb_binding_v2 *v2;
+ struct afb_api_v3 *v3;
+ } desc;
+
/* start function */
union {
- int (*v1)(struct afb_service);
+#if defined(WITH_LEGACY_BINDING_V1)
+ int (*v1)(struct afb_service_x1);
+#endif
int (*v2)();
- int (*vdyn)(struct afb_dynapi *dynapi);
+ int (*v3)(struct afb_api_x3 *api);
} init;
/* event handling */
- union {
- void (*v12)(const char *event, struct json_object *object);
- void (*vdyn)(struct afb_dynapi *dynapi, const char *event, struct json_object *object);
- } on_event;
+ void (*on_any_event_v12)(const char *event, struct json_object *object);
+ void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
/* exported data */
union {
+#if defined(WITH_LEGACY_BINDING_V1)
struct afb_binding_interface_v1 v1;
+#endif
struct afb_binding_data_v2 *v2;
} export;
+
+ /* initial name */
+ char name[1];
};
-/************************************************************************************************************/
+/*****************************************************************************/
+
+static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
+{
+ return (struct afb_api_x3*)export;
+}
-static inline struct afb_dynapi *to_dynapi(struct afb_export *export)
+static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
{
- return (struct afb_dynapi*)export;
+ return (struct afb_export*)api;
}
-static inline struct afb_export *from_dynapi(struct afb_dynapi *dynapi)
+struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
{
- return (struct afb_export*)dynapi;
+ return from_api_x3(api);
}
-/*************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
+struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
+{
+ return to_api_x3(export);
+}
+
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
F R O M D I T F
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************/
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
/**********************************************
* normal flow
**********************************************/
-static void vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
+static void vverbose_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
{
char *p;
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
if (!fmt || vasprintf(&p, fmt, args) < 0)
vverbose(level, file, line, function, fmt, args);
else {
- verbose(level, file, line, function, "[API %s] %s", export->apiname, p);
+ verbose(level, file, line, function, "[API %s] %s", export->api.apiname, p);
free(p);
}
}
-static void old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
+static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
{
vverbose_cb(closure, level, file, line, NULL, fmt, args);
}
-static struct afb_eventid *eventid_make_cb(void *closure, const char *name)
+static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
{
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
/* check daemon state */
if (export->state == Api_State_Pre_Init) {
- ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->apiname, name);
+ ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
errno = EINVAL;
return NULL;
}
/* create the event */
- return afb_evt_eventid_create2(export->apiname, name);
+ return afb_evt_event_x2_create2(export->api.apiname, name);
}
-static struct afb_event event_make_cb(void *closure, const char *name)
+static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
{
- struct afb_eventid *eventid = eventid_make_cb(closure, name);
- return afb_evt_event_from_evtid(afb_evt_eventid_to_evtid(eventid));
+ struct afb_event_x2 *event = event_x2_make_cb(closure, name);
+ return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
}
-static int event_broadcast_cb(void *closure, const char *name, struct json_object *object)
+static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
{
size_t plen, nlen;
char *event;
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
/* check daemon state */
if (export->state == Api_State_Pre_Init) {
- ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit", export->apiname, name, json_object_to_json_string(object));
+ ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit", export->api.apiname, name, json_object_to_json_string(object));
errno = EINVAL;
return 0;
}
/* makes the event name */
- plen = strlen(export->apiname);
+ plen = strlen(export->api.apiname);
nlen = strlen(name);
event = alloca(nlen + plen + 2);
- memcpy(event, export->apiname, plen);
+ memcpy(event, export->api.apiname, plen);
event[plen] = '/';
memcpy(event + plen + 1, name, nlen + 1);
@@ -198,190 +268,218 @@ static int event_broadcast_cb(void *closure, const char *name, struct json_objec
return afb_evt_broadcast(event, object);
}
-static int rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
+static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
{
return afb_common_rootdir_open_locale(filename, flags, locale);
}
-static int queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
+static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
{
return jobs_queue(group, timeout, callback, argument);
}
-static struct afb_req unstore_req_cb(void *closure, struct afb_stored_req *sreq)
+static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
{
return afb_xreq_unstore(sreq);
}
-static int require_api_cb(void *closure, const char *name, int initialized)
-{
- struct afb_export *export = closure;
- if (export->state != Api_State_Init) {
- ERROR("[API %s] Bad call to 'afb_daemon_require(%s, %d)', must be in Init", export->apiname, name, initialized);
- errno = EINVAL;
- return -1;
+static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
+{
+ struct afb_export *export = from_api_x3(closure);
+ int rc, rc2;
+ char *iter, *end, save;
+
+ /* scan the names in a local copy */
+ rc = 0;
+ iter = strdupa(name);
+ for(;;) {
+ /* skip any space */
+ save = *iter;
+ while(isspace(save))
+ save = *++iter;
+ if (!save) /* at end? */
+ return rc;
+
+ /* search for the end */
+ end = iter;
+ while (save && !isspace(save))
+ save = *++end;
+ *end = 0;
+
+ /* check the required api */
+ if (export->state == Api_State_Pre_Init)
+ rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
+ else
+ rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
+ if (rc2 < 0)
+ rc = rc2;
+
+ *end = save;
+ iter = end;
}
- return -!(initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->apiset, name, 1);
}
-static int rename_api_cb(void *closure, const char *name)
+static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
{
- struct afb_export *export = closure;
- if (export->state != Api_State_Pre_Init) {
- ERROR("[API %s] Bad call to 'afb_daemon_rename(%s)', must be in PreInit", export->apiname, name);
- errno = EINVAL;
- return -1;
- }
- if (!afb_api_is_valid_name(name, 1)) {
- ERROR("[API %s] Can't rename to %s: bad API name", export->apiname, name);
+ struct afb_export *export = from_api_x3(closure);
+ if (!afb_api_is_valid_name(aliasname)) {
+ ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
errno = EINVAL;
return -1;
}
- NOTICE("[API %s] renamed to [API %s]", export->apiname, name);
- afb_export_rename(export, name);
+ NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
+ afb_export_add_alias(export, apiname, aliasname);
return 0;
}
-static int api_new_api_cb(
- void *closure,
+static struct afb_api_x3 *api_new_api_cb(
+ struct afb_api_x3 *closure,
const char *api,
const char *info,
int noconcurrency,
- int (*preinit)(void*, struct afb_dynapi *),
+ int (*preinit)(void*, struct afb_api_x3 *),
void *preinit_closure)
{
- struct afb_export *export = closure;
- return afb_api_dyn_add(export->apiset, api, info, noconcurrency, preinit, preinit_closure);
+ struct afb_export *export = from_api_x3(closure);
+ struct afb_api_v3 *apiv3 = afb_api_v3_create(export->declare_set, export->call_set, api, info, noconcurrency, preinit, preinit_closure, 1);
+ return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
}
/**********************************************
* hooked flow
**********************************************/
-static void hooked_vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
+static void hooked_vverbose_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
{
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
va_list ap;
va_copy(ap, args);
vverbose_cb(closure, level, file, line, function, fmt, args);
- afb_hook_ditf_vverbose(export, level, file, line, function, fmt, ap);
+ afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
va_end(ap);
}
-static void hooked_old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
+static void legacy_hooked_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
{
hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
}
-static struct afb_eventid *hooked_eventid_make_cb(void *closure, const char *name)
+static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
{
- struct afb_export *export = closure;
- struct afb_eventid *r = eventid_make_cb(closure, name);
- afb_hook_ditf_event_make(export, name, r);
+ struct afb_export *export = from_api_x3(closure);
+ struct afb_event_x2 *r = event_x2_make_cb(closure, name);
+ afb_hook_api_event_make(export, name, r);
return r;
}
-static struct afb_event hooked_event_make_cb(void *closure, const char *name)
+static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
{
- struct afb_eventid *eventid = hooked_eventid_make_cb(closure, name);
- return (struct afb_event){ .itf = eventid ? eventid->itf : NULL, .closure = eventid };
+ struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
+ struct afb_event_x1 e;
+ e.closure = event;
+ e.itf = event ? event->itf : NULL;
+ return e;
}
-static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object)
+static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
{
int r;
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
json_object_get(object);
- afb_hook_ditf_event_broadcast_before(export, name, json_object_get(object));
+ afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
r = event_broadcast_cb(closure, name, object);
- afb_hook_ditf_event_broadcast_after(export, name, object, r);
+ afb_hook_api_event_broadcast_after(export, name, object, r);
json_object_put(object);
return r;
}
-static struct sd_event *hooked_get_event_loop(void *closure)
+static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
{
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
struct sd_event *r = afb_systemd_get_event_loop();
- return afb_hook_ditf_get_event_loop(export, r);
+ return afb_hook_api_get_event_loop(export, r);
}
-static struct sd_bus *hooked_get_user_bus(void *closure)
+static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
{
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
struct sd_bus *r = afb_systemd_get_user_bus();
- return afb_hook_ditf_get_user_bus(export, r);
+ return afb_hook_api_get_user_bus(export, r);
}
-static struct sd_bus *hooked_get_system_bus(void *closure)
+static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
{
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
struct sd_bus *r = afb_systemd_get_system_bus();
- return afb_hook_ditf_get_system_bus(export, r);
+ return afb_hook_api_get_system_bus(export, r);
}
-static int hooked_rootdir_get_fd(void *closure)
+static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
{
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
int r = afb_common_rootdir_get_fd();
- return afb_hook_ditf_rootdir_get_fd(export, r);
+ return afb_hook_api_rootdir_get_fd(export, r);
}
-static int hooked_rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
+static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
{
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
int r = rootdir_open_locale_cb(closure, filename, flags, locale);
- return afb_hook_ditf_rootdir_open_locale(export, filename, flags, locale, r);
+ return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
}
-static int hooked_queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
+static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
{
- struct afb_export *export = closure;
+ struct afb_export *export = from_api_x3(closure);
int r = queue_job_cb(closure, callback, argument, group, timeout);
- return afb_hook_ditf_queue_job(export, callback, argument, group, timeout, r);
+ return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
}
-static struct afb_req hooked_unstore_req_cb(void *closure, struct afb_stored_req *sreq)
+static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
{
- struct afb_export *export = closure;
- afb_hook_ditf_unstore_req(export, sreq);
- return unstore_req_cb(closure, sreq);
+ struct afb_export *export = from_api_x3(closure);
+ afb_hook_api_legacy_unstore_req(export, sreq);
+ return legacy_unstore_req_cb(closure, sreq);
}
-static int hooked_require_api_cb(void *closure, const char *name, int initialized)
+static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
{
int result;
- struct afb_export *export = closure;
- afb_hook_ditf_require_api(export, name, initialized);
+ struct afb_export *export = from_api_x3(closure);
+ afb_hook_api_require_api(export, name, initialized);
result = require_api_cb(closure, name, initialized);
- return afb_hook_ditf_require_api_result(export, name, initialized, result);
+ return afb_hook_api_require_api_result(export, name, initialized, result);
}
-static int hooked_rename_api_cb(void *closure, const char *name)
+static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
{
- struct afb_export *export = closure;
- const char *oldname = export->apiname;
- int result = rename_api_cb(closure, name);
- return afb_hook_ditf_rename_api(export, oldname, name, result);
+ struct afb_export *export = from_api_x3(closure);
+ int result = add_alias_cb(closure, apiname, aliasname);
+ return afb_hook_api_add_alias(export, apiname, aliasname, result);
}
-static int hooked_api_new_api_cb(
- void *closure,
+static struct afb_api_x3 *hooked_api_new_api_cb(
+ struct afb_api_x3 *closure,
const char *api,
const char *info,
int noconcurrency,
- int (*preinit)(void*, struct afb_dynapi *),
+ int (*preinit)(void*, struct afb_api_x3 *),
void *preinit_closure)
{
- /* TODO */
- return api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
+ struct afb_api_x3 *result;
+ struct afb_export *export = from_api_x3(closure);
+ afb_hook_api_new_api_before(export, api, info, noconcurrency);
+ result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
+ afb_hook_api_new_api_after(export, -!result, api);
+ return result;
}
+
/**********************************************
* vectors
**********************************************/
-static const struct afb_daemon_itf daemon_itf = {
- .vverbose_v1 = old_vverbose_cb,
+static const struct afb_daemon_itf_x1 daemon_itf = {
+ .vverbose_v1 = legacy_vverbose_v1_cb,
.vverbose_v2 = vverbose_cb,
- .event_make = event_make_cb,
+ .event_make = legacy_event_x1_make_cb,
.event_broadcast = event_broadcast_cb,
.get_event_loop = afb_systemd_get_event_loop,
.get_user_bus = afb_systemd_get_user_bus,
@@ -389,16 +487,16 @@ static const struct afb_daemon_itf daemon_itf = {
.rootdir_get_fd = afb_common_rootdir_get_fd,
.rootdir_open_locale = rootdir_open_locale_cb,
.queue_job = queue_job_cb,
- .unstore_req = unstore_req_cb,
+ .unstore_req = legacy_unstore_req_cb,
.require_api = require_api_cb,
- .rename_api = rename_api_cb,
+ .add_alias = add_alias_cb,
.new_api = api_new_api_cb,
};
-static const struct afb_daemon_itf hooked_daemon_itf = {
- .vverbose_v1 = hooked_old_vverbose_cb,
+static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
+ .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
.vverbose_v2 = hooked_vverbose_cb,
- .event_make = hooked_event_make_cb,
+ .event_make = legacy_hooked_event_x1_make_cb,
.event_broadcast = hooked_event_broadcast_cb,
.get_event_loop = hooked_get_event_loop,
.get_user_bus = hooked_get_user_bus,
@@ -406,422 +504,185 @@ static const struct afb_daemon_itf hooked_daemon_itf = {
.rootdir_get_fd = hooked_rootdir_get_fd,
.rootdir_open_locale = hooked_rootdir_open_locale_cb,
.queue_job = hooked_queue_job_cb,
- .unstore_req = hooked_unstore_req_cb,
+ .unstore_req = legacy_hooked_unstore_req_cb,
.require_api = hooked_require_api_cb,
- .rename_api = hooked_rename_api_cb,
+ .add_alias = hooked_add_alias_cb,
.new_api = hooked_api_new_api_cb,
};
-/*************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
F R O M S V C
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************/
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
/* the common session for services sharing their session */
static struct afb_session *common_session;
-/*************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
F R O M S V C
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************/
-
-/*
- * Structure for requests initiated by the service
- */
-struct call_req
-{
- struct afb_xreq xreq;
-
- struct afb_export *export;
-
- /* the args */
- union {
- void (*callback)(void*, int, struct json_object*);
- void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
- };
- void *closure;
-
- /* sync */
- struct jobloop *jobloop;
- struct json_object *result;
- int status;
-};
-
-/*
- * destroys the call_req
- */
-static void callreq_destroy(struct afb_xreq *xreq)
-{
- struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
-
- afb_context_disconnect(&callreq->xreq.context);
- json_object_put(callreq->xreq.json);
- afb_cred_unref(callreq->xreq.cred);
- free(callreq);
-}
-
-static void callreq_reply_async(struct afb_xreq *xreq, int status, json_object *obj)
-{
- struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
- if (callreq->callback)
- callreq->callback(callreq->closure, status, obj);
- json_object_put(obj);
-}
-
-static void callreq_reply_async_dynapi(struct afb_xreq *xreq, int status, json_object *obj)
-{
- struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
- if (callreq->callback_dynapi)
- callreq->callback_dynapi(callreq->closure, status, obj, to_dynapi(callreq->export));
- json_object_put(obj);
-}
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
-static void callreq_sync_leave(struct call_req *callreq)
-{
- struct jobloop *jobloop = callreq->jobloop;
-
- if (jobloop) {
- callreq->jobloop = NULL;
- jobs_leave(jobloop);
- }
-}
-
-static void callreq_reply_sync(struct afb_xreq *xreq, int status, json_object *obj)
-{
- struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
- callreq->status = status;
- callreq->result = obj;
- callreq_sync_leave(callreq);
-}
-
-static void callreq_sync_enter(int signum, void *closure, struct jobloop *jobloop)
+static void call_x3(
+ struct afb_api_x3 *apix3,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
+ void *closure)
{
- struct call_req *callreq = closure;
-
- if (!signum) {
- callreq->jobloop = jobloop;
- afb_xreq_process(&callreq->xreq, callreq->export->apiset);
- } else {
- callreq->result = afb_msg_json_internal_error();
- callreq->status = -1;
- callreq_sync_leave(callreq);
- }
+ struct afb_export *export = from_api_x3(apix3);
+ return afb_calls_call(export, api, verb, args, callback, closure);
}
-/* interface for requests of services */
-const struct afb_xreq_query_itf afb_export_xreq_async_itf = {
- .unref = callreq_destroy,
- .reply = callreq_reply_async
-};
-
-/* interface for requests of services */
-const struct afb_xreq_query_itf afb_export_xreq_async_dynapi_itf = {
- .unref = callreq_destroy,
- .reply = callreq_reply_async_dynapi
-};
-
-/* interface for requests of services */
-const struct afb_xreq_query_itf afb_export_xreq_sync_itf = {
- .unref = callreq_destroy,
- .reply = callreq_reply_sync
-};
-
-/*
- * create an call_req
- */
-static struct call_req *callreq_create(
- struct afb_export *export,
+static int call_sync_x3(
+ struct afb_api_x3 *apix3,
const char *api,
const char *verb,
struct json_object *args,
- const struct afb_xreq_query_itf *itf)
-{
- struct call_req *callreq;
- size_t lenapi, lenverb;
- char *copy;
-
- /* allocates the request */
- lenapi = 1 + strlen(api);
- lenverb = 1 + strlen(verb);
- callreq = malloc(lenapi + lenverb + sizeof *callreq);
- if (callreq != NULL) {
- /* initialises the request */
- afb_xreq_init(&callreq->xreq, itf);
- afb_context_init(&callreq->xreq.context, export->session, NULL);
- callreq->xreq.context.validated = 1;
- copy = (char*)&callreq[1];
- memcpy(copy, api, lenapi);
- callreq->xreq.request.api = copy;
- copy = &copy[lenapi];
- memcpy(copy, verb, lenverb);
- callreq->xreq.request.verb = copy;
- callreq->xreq.listener = export->listener;
- callreq->xreq.json = args;
- callreq->export = export;
- }
- return callreq;
+ struct json_object **object,
+ char **error,
+ char **info)
+{
+ struct afb_export *export = from_api_x3(apix3);
+ return afb_calls_call_sync(export, api, verb, args, object, error, info);
}
-/*
- * Initiates a call for the service
- */
-static void svc_call(
- void *closure,
+static void legacy_call_v12(
+ struct afb_api_x3 *apix3,
const char *api,
const char *verb,
struct json_object *args,
void (*callback)(void*, int, struct json_object*),
- void *cbclosure)
+ void *closure)
{
- struct afb_export *export = closure;
- struct call_req *callreq;
- struct json_object *ierr;
-
- /* allocates the request */
- callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_itf);
- if (callreq == NULL) {
- ERROR("out of memory");
- json_object_put(args);
- ierr = afb_msg_json_internal_error();
- if (callback)
- callback(cbclosure, -1, ierr);
- json_object_put(ierr);
- return;
- }
-
- /* initialises the request */
- callreq->jobloop = NULL;
- callreq->callback = callback;
- callreq->closure = cbclosure;
-
- /* terminates and frees ressources if needed */
- afb_xreq_process(&callreq->xreq, export->apiset);
+ struct afb_export *export = from_api_x3(apix3);
+ afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
}
-static void svc_call_dynapi(
- struct afb_dynapi *dynapi,
+static void legacy_call_x3(
+ struct afb_api_x3 *apix3,
const char *api,
const char *verb,
struct json_object *args,
- void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
- void *cbclosure)
-{
- struct afb_export *export = from_dynapi(dynapi);
- struct call_req *callreq;
- struct json_object *ierr;
-
- /* allocates the request */
- callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_dynapi_itf);
- if (callreq == NULL) {
- ERROR("out of memory");
- json_object_put(args);
- ierr = afb_msg_json_internal_error();
- if (callback)
- callback(cbclosure, -1, ierr, to_dynapi(export));
- json_object_put(ierr);
- return;
- }
-
- /* initialises the request */
- callreq->jobloop = NULL;
- callreq->callback_dynapi = callback;
- callreq->closure = cbclosure;
-
- /* terminates and frees ressources if needed */
- afb_xreq_process(&callreq->xreq, export->apiset);
+ void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
+ void *closure)
+{
+ struct afb_export *export = from_api_x3(apix3);
+ afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
}
-static int svc_call_sync(
- void *closure,
+static int legacy_call_sync(
+ struct afb_api_x3 *apix3,
const char *api,
const char *verb,
struct json_object *args,
struct json_object **result)
{
- struct afb_export *export = closure;
- struct call_req *callreq;
- struct json_object *resu;
- int rc;
-
- /* allocates the request */
- callreq = callreq_create(export, api, verb, args, &afb_export_xreq_sync_itf);
- if (callreq == NULL) {
- ERROR("out of memory");
- errno = ENOMEM;
- json_object_put(args);
- resu = afb_msg_json_internal_error();
- rc = -1;
- } else {
- /* initialises the request */
- callreq->jobloop = NULL;
- callreq->callback = NULL;
- callreq->result = NULL;
- callreq->status = 0;
- afb_xreq_unhooked_addref(&callreq->xreq); /* avoid early callreq destruction */
- rc = jobs_enter(NULL, 0, callreq_sync_enter, callreq);
- if (rc >= 0)
- rc = callreq->status;
- resu = (rc >= 0 || callreq->result) ? callreq->result : afb_msg_json_internal_error();
- afb_xreq_unhooked_unref(&callreq->xreq);
- }
- if (result)
- *result = resu;
- else
- json_object_put(resu);
- return rc;
+ struct afb_export *export = from_api_x3(apix3);
+ return afb_calls_legacy_call_sync(export, api, verb, args, result);
}
-struct hooked_call
-{
- struct afb_export *export;
- union {
- void (*callback)(void*, int, struct json_object*);
- void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
- };
- void *cbclosure;
-};
-
-static void svc_hooked_call_result(void *closure, int status, struct json_object *result)
+static void hooked_call_x3(
+ struct afb_api_x3 *apix3,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
+ void *closure)
{
- struct hooked_call *hc = closure;
- afb_hook_svc_call_result(hc->export, status, result);
- hc->callback(hc->cbclosure, status, result);
- free(hc);
+ struct afb_export *export = from_api_x3(apix3);
+ afb_calls_hooked_call(export, api, verb, args, callback, closure);
}
-static void svc_hooked_call_dynapi_result(void *closure, int status, struct json_object *result, struct afb_dynapi *dynapi)
+static int hooked_call_sync_x3(
+ struct afb_api_x3 *apix3,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ struct json_object **object,
+ char **error,
+ char **info)
{
- struct hooked_call *hc = closure;
- afb_hook_svc_call_result(hc->export, status, result);
- hc->callback_dynapi(hc->cbclosure, status, result, dynapi);
- free(hc);
+ struct afb_export *export = from_api_x3(apix3);
+ return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
}
-static void svc_hooked_call(
- void *closure,
+static void legacy_hooked_call_v12(
+ struct afb_api_x3 *apix3,
const char *api,
const char *verb,
struct json_object *args,
void (*callback)(void*, int, struct json_object*),
- void *cbclosure)
+ void *closure)
{
- struct afb_export *export = closure;
- struct hooked_call *hc;
-
- if (export->hooksvc & afb_hook_flag_svc_call)
- afb_hook_svc_call(export, api, verb, args);
-
- if (export->hooksvc & afb_hook_flag_svc_call_result) {
- hc = malloc(sizeof *hc);
- if (!hc)
- WARNING("allocation failed");
- else {
- hc->export = export;
- hc->callback = callback;
- hc->cbclosure = cbclosure;
- callback = svc_hooked_call_result;
- cbclosure = hc;
- }
- }
- svc_call(closure, api, verb, args, callback, cbclosure);
+ struct afb_export *export = from_api_x3(apix3);
+ afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
}
-static void svc_hooked_call_dynapi(
- struct afb_dynapi *dynapi,
+static void legacy_hooked_call_x3(
+ struct afb_api_x3 *apix3,
const char *api,
const char *verb,
struct json_object *args,
- void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
- void *cbclosure)
+ void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
+ void *closure)
{
- struct afb_export *export = from_dynapi(dynapi);
- struct hooked_call *hc;
-
- if (export->hooksvc & afb_hook_flag_svc_call)
- afb_hook_svc_call(export, api, verb, args);
-
- if (export->hooksvc & afb_hook_flag_svc_call_result) {
- hc = malloc(sizeof *hc);
- if (!hc)
- WARNING("allocation failed");
- else {
- hc->export = export;
- hc->callback_dynapi = callback;
- hc->cbclosure = cbclosure;
- callback = svc_hooked_call_dynapi_result;
- cbclosure = hc;
- }
- }
- svc_call_dynapi(dynapi, api, verb, args, callback, cbclosure);
+ struct afb_export *export = from_api_x3(apix3);
+ afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
}
-static int svc_hooked_call_sync(
- void *closure,
+static int legacy_hooked_call_sync(
+ struct afb_api_x3 *apix3,
const char *api,
const char *verb,
struct json_object *args,
struct json_object **result)
{
- struct afb_export *export = closure;
- struct json_object *resu;
- int rc;
-
- if (export->hooksvc & afb_hook_flag_svc_callsync)
- afb_hook_svc_callsync(export, api, verb, args);
-
- rc = svc_call_sync(closure, api, verb, args, &resu);
-
- if (export->hooksvc & afb_hook_flag_svc_callsync_result)
- afb_hook_svc_callsync_result(export, rc, resu);
-
- if (result)
- *result = resu;
- else
- json_object_put(resu);
-
- return rc;
+ struct afb_export *export = from_api_x3(apix3);
+ return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
}
/* the interface for services */
-static const struct afb_service_itf service_itf = {
- .call = svc_call,
- .call_sync = svc_call_sync
+static const struct afb_service_itf_x1 service_itf = {
+ .call = legacy_call_v12,
+ .call_sync = legacy_call_sync
};
/* the interface for services */
-static const struct afb_service_itf hooked_service_itf = {
- .call = svc_hooked_call,
- .call_sync = svc_hooked_call_sync
+static const struct afb_service_itf_x1 hooked_service_itf = {
+ .call = legacy_hooked_call_v12,
+ .call_sync = legacy_hooked_call_sync
};
-/*************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
F R O M D Y N A P I
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************/
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
static int api_set_verbs_v2_cb(
- struct afb_dynapi *dynapi,
+ struct afb_api_x3 *api,
const struct afb_verb_v2 *verbs)
{
- struct afb_export *export = from_dynapi(dynapi);
+ struct afb_export *export = from_api_x3(api);
- if (export->apidyn) {
- afb_api_dyn_set_verbs_v2(export->apidyn, verbs);
+ if (export->unsealed) {
+ afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
return 0;
}
@@ -829,115 +690,292 @@ static int api_set_verbs_v2_cb(
return -1;
}
+static int api_set_verbs_v3_cb(
+ struct afb_api_x3 *api,
+ const struct afb_verb_v3 *verbs)
+{
+ struct afb_export *export = from_api_x3(api);
+
+ if (!export->unsealed) {
+ errno = EPERM;
+ return -1;
+ }
+
+ afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
+ return 0;
+}
+
static int api_add_verb_cb(
- struct afb_dynapi *dynapi,
+ struct afb_api_x3 *api,
const char *verb,
const char *info,
- void (*callback)(struct afb_request *request),
+ void (*callback)(struct afb_req_x2 *req),
void *vcbdata,
const struct afb_auth *auth,
- uint32_t session)
+ uint32_t session,
+ int glob)
{
- struct afb_export *export = from_dynapi(dynapi);
+ struct afb_export *export = from_api_x3(api);
- if (export->apidyn)
- return afb_api_dyn_add_verb(export->apidyn, verb, info, callback, vcbdata, auth, session);
+ if (!export->unsealed) {
+ errno = EPERM;
+ return -1;
+ }
- errno = EPERM;
- return -1;
+ return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
}
-static int api_sub_verb_cb(
- struct afb_dynapi *dynapi,
- const char *verb)
+static int api_del_verb_cb(
+ struct afb_api_x3 *api,
+ const char *verb,
+ void **vcbdata)
{
- struct afb_export *export = from_dynapi(dynapi);
+ struct afb_export *export = from_api_x3(api);
- if (export->apidyn)
- return afb_api_dyn_sub_verb(export->apidyn, verb);
+ if (!export->unsealed) {
+ errno = EPERM;
+ return -1;
+ }
- errno = EPERM;
- return -1;
+ return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
}
static int api_set_on_event_cb(
- struct afb_dynapi *dynapi,
- void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
+ struct afb_api_x3 *api,
+ void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
{
- struct afb_export *export = from_dynapi(dynapi);
- return afb_export_handle_events_vdyn(export, onevent);
+ struct afb_export *export = from_api_x3(api);
+ return afb_export_handle_events_v3(export, onevent);
}
static int api_set_on_init_cb(
- struct afb_dynapi *dynapi,
- int (*oninit)(struct afb_dynapi *dynapi))
+ struct afb_api_x3 *api,
+ int (*oninit)(struct afb_api_x3 *api))
{
- struct afb_export *export = from_dynapi(dynapi);
+ struct afb_export *export = from_api_x3(api);
- return afb_export_handle_init_vdyn(export, oninit);
+ return afb_export_handle_init_v3(export, oninit);
}
static void api_seal_cb(
- struct afb_dynapi *dynapi)
+ struct afb_api_x3 *api)
+{
+ struct afb_export *export = from_api_x3(api);
+
+ export->unsealed = 0;
+}
+
+static int event_handler_add_cb(
+ struct afb_api_x3 *api,
+ const char *pattern,
+ void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
+ void *closure)
+{
+ struct afb_export *export = from_api_x3(api);
+
+ return afb_export_event_handler_add(export, pattern, callback, closure);
+}
+
+static int event_handler_del_cb(
+ struct afb_api_x3 *api,
+ const char *pattern,
+ void **closure)
+{
+ struct afb_export *export = from_api_x3(api);
+
+ return afb_export_event_handler_del(export, pattern, closure);
+}
+
+static int class_provide_cb(struct afb_api_x3 *api, const char *name)
+{
+ struct afb_export *export = from_api_x3(api);
+
+ int rc = 0, rc2;
+ char *iter, *end, save;
+
+ iter = strdupa(name);
+ for(;;) {
+ /* skip any space */
+ save = *iter;
+ while(isspace(save))
+ save = *++iter;
+ if (!save) /* at end? */
+ return rc;
+
+ /* search for the end */
+ end = iter;
+ while (save && !isspace(save))
+ save = *++end;
+ *end = 0;
+
+ rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
+ if (rc2 < 0)
+ rc = rc2;
+
+ *end = save;
+ iter = end;
+ }
+}
+
+static int class_require_cb(struct afb_api_x3 *api, const char *name)
+{
+ struct afb_export *export = from_api_x3(api);
+
+ int rc = 0, rc2;
+ char *iter, *end, save;
+
+ iter = strdupa(name);
+ for(;;) {
+ /* skip any space */
+ save = *iter;
+ while(isspace(save))
+ save = *++iter;
+ if (!save) /* at end? */
+ return rc;
+
+ /* search for the end */
+ end = iter;
+ while (save && !isspace(save))
+ save = *++end;
+ *end = 0;
+
+ rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
+ if (rc2 < 0)
+ rc = rc2;
+
+ *end = save;
+ iter = end;
+ }
+}
+
+static int delete_api_cb(struct afb_api_x3 *api)
{
- struct afb_export *export = from_dynapi(dynapi);
+ struct afb_export *export = from_api_x3(api);
+
+ if (!export->unsealed) {
+ errno = EPERM;
+ return -1;
+ }
- export->apidyn = NULL;
+ afb_export_undeclare(export);
+ afb_export_unref(export);
+ return 0;
}
static int hooked_api_set_verbs_v2_cb(
- struct afb_dynapi *dynapi,
+ struct afb_api_x3 *api,
const struct afb_verb_v2 *verbs)
{
- /* TODO */
- return api_set_verbs_v2_cb(dynapi, verbs);
+ struct afb_export *export = from_api_x3(api);
+ int result = api_set_verbs_v2_cb(api, verbs);
+ return afb_hook_api_api_set_verbs_v2(export, result, verbs);
+}
+
+static int hooked_api_set_verbs_v3_cb(
+ struct afb_api_x3 *api,
+ const struct afb_verb_v3 *verbs)
+{
+ struct afb_export *export = from_api_x3(api);
+ int result = api_set_verbs_v3_cb(api, verbs);
+ return afb_hook_api_api_set_verbs_v3(export, result, verbs);
}
static int hooked_api_add_verb_cb(
- struct afb_dynapi *dynapi,
+ struct afb_api_x3 *api,
const char *verb,
const char *info,
- void (*callback)(struct afb_request *request),
+ void (*callback)(struct afb_req_x2 *req),
void *vcbdata,
const struct afb_auth *auth,
- uint32_t session)
+ uint32_t session,
+ int glob)
{
- /* TODO */
- return api_add_verb_cb(dynapi, verb, info, callback, vcbdata, auth, session);
+ struct afb_export *export = from_api_x3(api);
+ int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
+ return afb_hook_api_api_add_verb(export, result, verb, info, glob);
}
-static int hooked_api_sub_verb_cb(
- struct afb_dynapi *dynapi,
- const char *verb)
+static int hooked_api_del_verb_cb(
+ struct afb_api_x3 *api,
+ const char *verb,
+ void **vcbdata)
{
- /* TODO */
- return api_sub_verb_cb(dynapi, verb);
+ struct afb_export *export = from_api_x3(api);
+ int result = api_del_verb_cb(api, verb, vcbdata);
+ return afb_hook_api_api_del_verb(export, result, verb);
}
static int hooked_api_set_on_event_cb(
- struct afb_dynapi *dynapi,
- void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
+ struct afb_api_x3 *api,
+ void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
{
- /* TODO */
- return api_set_on_event_cb(dynapi, onevent);
+ struct afb_export *export = from_api_x3(api);
+ int result = api_set_on_event_cb(api, onevent);
+ return afb_hook_api_api_set_on_event(export, result);
}
static int hooked_api_set_on_init_cb(
- struct afb_dynapi *dynapi,
- int (*oninit)(struct afb_dynapi *dynapi))
+ struct afb_api_x3 *api,
+ int (*oninit)(struct afb_api_x3 *api))
{
- /* TODO */
- return api_set_on_init_cb(dynapi, oninit);
+ struct afb_export *export = from_api_x3(api);
+ int result = api_set_on_init_cb(api, oninit);
+ return afb_hook_api_api_set_on_init(export, result);
}
static void hooked_api_seal_cb(
- struct afb_dynapi *dynapi)
+ struct afb_api_x3 *api)
{
- /* TODO */
- api_seal_cb(dynapi);
+ struct afb_export *export = from_api_x3(api);
+ afb_hook_api_api_seal(export);
+ api_seal_cb(api);
}
-static const struct afb_dynapi_itf dynapi_itf = {
+static int hooked_event_handler_add_cb(
+ struct afb_api_x3 *api,
+ const char *pattern,
+ void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
+ void *closure)
+{
+ struct afb_export *export = from_api_x3(api);
+ int result = event_handler_add_cb(api, pattern, callback, closure);
+ return afb_hook_api_event_handler_add(export, result, pattern);
+}
+
+static int hooked_event_handler_del_cb(
+ struct afb_api_x3 *api,
+ const char *pattern,
+ void **closure)
+{
+ struct afb_export *export = from_api_x3(api);
+ int result = event_handler_del_cb(api, pattern, closure);
+ return afb_hook_api_event_handler_del(export, result, pattern);
+}
+
+static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
+{
+ struct afb_export *export = from_api_x3(api);
+ int result = class_provide_cb(api, name);
+ return afb_hook_api_class_provide(export, result, name);
+}
+
+static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
+{
+ struct afb_export *export = from_api_x3(api);
+ int result = class_require_cb(api, name);
+ return afb_hook_api_class_require(export, result, name);
+}
+
+static int hooked_delete_api_cb(struct afb_api_x3 *api)
+{
+ struct afb_export *export = afb_export_addref(from_api_x3(api));
+ int result = delete_api_cb(api);
+ result = afb_hook_api_delete_api(export, result);
+ afb_export_unref(export);
+ return result;
+}
+
+static const struct afb_api_x3_itf api_x3_itf = {
.vverbose = (void*)vverbose_cb,
@@ -949,24 +987,35 @@ static const struct afb_dynapi_itf dynapi_itf = {
.queue_job = queue_job_cb,
.require_api = require_api_cb,
- .rename_api = rename_api_cb,
+ .add_alias = add_alias_cb,
.event_broadcast = event_broadcast_cb,
- .eventid_make = eventid_make_cb,
+ .event_make = event_x2_make_cb,
- .call = svc_call_dynapi,
- .call_sync = svc_call_sync,
+ .legacy_call = legacy_call_x3,
+ .legacy_call_sync = legacy_call_sync,
.api_new_api = api_new_api_cb,
.api_set_verbs_v2 = api_set_verbs_v2_cb,
.api_add_verb = api_add_verb_cb,
- .api_sub_verb = api_sub_verb_cb,
+ .api_del_verb = api_del_verb_cb,
.api_set_on_event = api_set_on_event_cb,
.api_set_on_init = api_set_on_init_cb,
.api_seal = api_seal_cb,
+ .api_set_verbs_v3 = api_set_verbs_v3_cb,
+ .event_handler_add = event_handler_add_cb,
+ .event_handler_del = event_handler_del_cb,
+
+ .call = call_x3,
+ .call_sync = call_sync_x3,
+
+ .class_provide = class_provide_cb,
+ .class_require = class_require_cb,
+
+ .delete_api = delete_api_cb,
};
-static const struct afb_dynapi_itf hooked_dynapi_itf = {
+static const struct afb_api_x3_itf hooked_api_x3_itf = {
.vverbose = hooked_vverbose_cb,
@@ -978,86 +1027,187 @@ static const struct afb_dynapi_itf hooked_dynapi_itf = {
.queue_job = hooked_queue_job_cb,
.require_api = hooked_require_api_cb,
- .rename_api = hooked_rename_api_cb,
+ .add_alias = hooked_add_alias_cb,
.event_broadcast = hooked_event_broadcast_cb,
- .eventid_make = hooked_eventid_make_cb,
+ .event_make = hooked_event_x2_make_cb,
- .call = svc_hooked_call_dynapi,
- .call_sync = svc_hooked_call_sync,
+ .legacy_call = legacy_hooked_call_x3,
+ .legacy_call_sync = legacy_hooked_call_sync,
.api_new_api = hooked_api_new_api_cb,
.api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
.api_add_verb = hooked_api_add_verb_cb,
- .api_sub_verb = hooked_api_sub_verb_cb,
+ .api_del_verb = hooked_api_del_verb_cb,
.api_set_on_event = hooked_api_set_on_event_cb,
.api_set_on_init = hooked_api_set_on_init_cb,
.api_seal = hooked_api_seal_cb,
+ .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
+ .event_handler_add = hooked_event_handler_add_cb,
+ .event_handler_del = hooked_event_handler_del_cb,
+
+ .call = hooked_call_x3,
+ .call_sync = hooked_call_sync_x3,
+
+ .class_provide = hooked_class_provide_cb,
+ .class_require = hooked_class_require_cb,
+
+ .delete_api = hooked_delete_api_cb,
};
-/*************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- F R O M S V C
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************/
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ L I S T E N E R S
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
/*
* Propagates the event to the service
*/
-static void export_on_event_v12(void *closure, const char *event, int eventid, struct json_object *object)
-{
- struct afb_export *export = closure;
+static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
+{
+ struct event_handler *handler;
+ struct afb_export *export = from_api_x3(closure);
+
+ /* hook the event before */
+ if (export->hooksvc & afb_hook_flag_api_on_event)
+ afb_hook_api_on_event_before(export, event, eventid, object);
+
+ /* transmit to specific handlers */
+ /* search the handler */
+ handler = export->event_handlers;
+ while (handler) {
+ if (fnmatch(handler->pattern, event, 0)) {
+ if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
+ handler->callback(handler->closure, event, object, to_api_x3(export));
+ else {
+ afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
+ handler->callback(handler->closure, event, object, to_api_x3(export));
+ afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
+ }
+ }
+ handler = handler->next;
+ }
+
+ /* transmit to default handler */
+ if (export->on_any_event_v3)
+ export->on_any_event_v3(to_api_x3(export), event, object);
+ else if (export->on_any_event_v12)
+ export->on_any_event_v12(event, object);
- if (export->hooksvc & afb_hook_flag_svc_on_event_before)
- afb_hook_svc_on_event_before(export, event, eventid, object);
- export->on_event.v12(event, object);
- if (export->hooksvc & afb_hook_flag_svc_on_event_after)
- afb_hook_svc_on_event_after(export, event, eventid, object);
+ /* hook the event after */
+ if (export->hooksvc & afb_hook_flag_api_on_event)
+ afb_hook_api_on_event_after(export, event, eventid, object);
json_object_put(object);
}
/* the interface for events */
-static const struct afb_evt_itf evt_v12_itf = {
- .broadcast = export_on_event_v12,
- .push = export_on_event_v12
+static const struct afb_evt_itf evt_itf = {
+ .broadcast = listener_of_events,
+ .push = listener_of_events
};
-/*
- * Propagates the event to the service
- */
-static void export_on_event_vdyn(void *closure, const char *event, int eventid, struct json_object *object)
+/* ensure an existing listener */
+static int ensure_listener(struct afb_export *export)
{
- struct afb_export *export = closure;
+ if (!export->listener) {
+ export->listener = afb_evt_listener_create(&evt_itf, export);
+ if (export->listener == NULL)
+ return -1;
+ }
+ return 0;
+}
- if (export->hooksvc & afb_hook_flag_svc_on_event_before)
- afb_hook_svc_on_event_before(export, event, eventid, object);
- export->on_event.vdyn(to_dynapi(export), event, object);
- if (export->hooksvc & afb_hook_flag_svc_on_event_after)
- afb_hook_svc_on_event_after(export, event, eventid, object);
- json_object_put(object);
+int afb_export_event_handler_add(
+ struct afb_export *export,
+ const char *pattern,
+ void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
+ void *closure)
+{
+ int rc;
+ struct event_handler *handler, **previous;
+
+ rc = ensure_listener(export);
+ if (rc < 0)
+ return rc;
+
+ /* search the handler */
+ previous = &export->event_handlers;
+ while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
+ previous = &handler->next;
+
+ /* error if found */
+ if (handler) {
+ ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
+ errno = EEXIST;
+ return -1;
+ }
+
+ /* create the event */
+ handler = malloc(strlen(pattern) + strlen(pattern));
+ if (!handler) {
+ ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* init and record */
+ handler->next = NULL;
+ handler->callback = callback;
+ handler->closure = closure;
+ strcpy(handler->pattern, pattern);
+ export->event_handlers = handler;
+
+ return 0;
}
-/* the interface for events */
-static const struct afb_evt_itf evt_vdyn_itf = {
- .broadcast = export_on_event_vdyn,
- .push = export_on_event_vdyn
-};
+int afb_export_event_handler_del(
+ struct afb_export *export,
+ const char *pattern,
+ void **closure)
+{
+ struct event_handler *handler, **previous;
+
+ /* search the handler */
+ previous = &export->event_handlers;
+ while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
+ previous = &handler->next;
-/*************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
+ /* error if found */
+ if (!handler) {
+ ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
+ errno = ENOENT;
+ return -1;
+ }
+
+ /* remove the found event */
+ if (closure)
+ *closure = handler->closure;
+
+ *previous = handler->next;
+ free(handler);
+ return 0;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
M E R G E D
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************/
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
-static struct afb_export *create(struct afb_apiset *apiset, const char *apiname, enum afb_api_version version)
+static struct afb_export *create(
+ struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *apiname,
+ enum afb_api_version version)
{
struct afb_export *export;
@@ -1067,96 +1217,179 @@ static struct afb_export *create(struct afb_apiset *apiset, const char *apiname,
if (common_session == NULL)
return NULL;
}
- export = calloc(1, sizeof *export);
+ export = calloc(1, sizeof *export + strlen(apiname));
if (!export)
errno = ENOMEM;
else {
- memset(export, 0, sizeof *export);
- export->apiname = strdup(apiname);
- export->dynapi.apiname = export->apiname;
+ export->refcount = 1;
+ strcpy(export->name, apiname);
+ export->api.apiname = export->name;
export->version = version;
export->state = Api_State_Pre_Init;
export->session = afb_session_addref(common_session);
- export->apiset = afb_apiset_addref(apiset);
+ export->declare_set = afb_apiset_addref(declare_set);
+ export->call_set = afb_apiset_addref(call_set);
}
return export;
}
+struct afb_export *afb_export_addref(struct afb_export *export)
+{
+ if (export)
+ __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
+ return export;
+}
+
+void afb_export_unref(struct afb_export *export)
+{
+ if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
+ afb_export_destroy(export);
+}
+
void afb_export_destroy(struct afb_export *export)
{
+ struct event_handler *handler;
+
if (export) {
+ while ((handler = export->event_handlers)) {
+ export->event_handlers = handler->next;
+ free(handler);
+ }
if (export->listener != NULL)
afb_evt_listener_unref(export->listener);
afb_session_unref(export->session);
- afb_apiset_unref(export->apiset);
- free(export->apiname);
+ afb_apiset_unref(export->declare_set);
+ afb_apiset_unref(export->call_set);
+ if (export->api.apiname != export->name)
+ free((void*)export->api.apiname);
free(export);
}
}
-struct afb_export *afb_export_create_v1(struct afb_apiset *apiset, const char *apiname, int (*init)(struct afb_service), void (*onevent)(const char*, struct json_object*))
+struct afb_export *afb_export_create_none_for_path(
+ struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *path,
+ int (*creator)(void*, struct afb_api_x3*),
+ void *closure)
{
- struct afb_export *export = create(apiset, apiname, Api_Version_1);
+ struct afb_export *export = create(declare_set, call_set, path, Api_Version_None);
+ if (export) {
+ afb_export_logmask_set(export, logmask);
+ afb_export_update_hooks(export);
+ if (creator && creator(closure, to_api_x3(export)) < 0) {
+ afb_export_unref(export);
+ export = NULL;
+ }
+ }
+ return export;
+}
+
+#if defined(WITH_LEGACY_BINDING_V1)
+struct afb_export *afb_export_create_v1(
+ struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *apiname,
+ int (*init)(struct afb_service_x1),
+ void (*onevent)(const char*, struct json_object*))
+{
+ struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_1);
if (export) {
export->init.v1 = init;
- export->on_event.v12 = onevent;
+ export->on_any_event_v12 = onevent;
export->export.v1.mode = AFB_MODE_LOCAL;
- export->export.v1.daemon.closure = export;
- afb_export_verbosity_set(export, verbosity);
- afb_export_update_hook(export);
+ export->export.v1.daemon.closure = to_api_x3(export);
+ afb_export_logmask_set(export, logmask);
+ afb_export_update_hooks(export);
}
return export;
}
+#endif
-struct afb_export *afb_export_create_v2(struct afb_apiset *apiset, const char *apiname, struct afb_binding_data_v2 *data, int (*init)(), void (*onevent)(const char*, struct json_object*))
+struct afb_export *afb_export_create_v2(
+ struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *apiname,
+ const struct afb_binding_v2 *binding,
+ struct afb_binding_data_v2 *data,
+ int (*init)(),
+ void (*onevent)(const char*, struct json_object*))
{
- struct afb_export *export = create(apiset, apiname, Api_Version_2);
+ struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_2);
if (export) {
export->init.v2 = init;
- export->on_event.v12 = onevent;
+ export->on_any_event_v12 = onevent;
+ export->desc.v2 = binding;
export->export.v2 = data;
- data->daemon.closure = export;
- data->service.closure = export;
- afb_export_verbosity_set(export, verbosity);
- afb_export_update_hook(export);
+ data->daemon.closure = to_api_x3(export);
+ data->service.closure = to_api_x3(export);
+ afb_export_logmask_set(export, logmask);
+ afb_export_update_hooks(export);
}
return export;
}
-struct afb_export *afb_export_create_vdyn(struct afb_apiset *apiset, const char *apiname, struct afb_api_dyn *apidyn)
+struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *apiname,
+ struct afb_api_v3 *apiv3)
{
- struct afb_export *export = create(apiset, apiname, Api_Version_Dyn);
+ struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_3);
if (export) {
- export->apidyn = apidyn;
- afb_export_verbosity_set(export, verbosity);
- afb_export_update_hook(export);
+ export->unsealed = 1;
+ export->desc.v3 = apiv3;
+ afb_export_logmask_set(export, logmask);
+ afb_export_update_hooks(export);
}
return export;
}
-void afb_export_rename(struct afb_export *export, const char *apiname)
+int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
+{
+ return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
+}
+
+int afb_export_rename(struct afb_export *export, const char *apiname)
{
- free(export->apiname);
- export->apiname = strdup(apiname);
- export->dynapi.apiname = export->apiname;
- afb_export_update_hook(export);
+ char *name;
+
+ if (export->declared) {
+ errno = EBUSY;
+ return -1;
+ }
+
+ /* copy the name locally */
+ name = strdup(apiname);
+ if (!name) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ if (export->api.apiname != export->name)
+ free((void*)export->api.apiname);
+ export->api.apiname = name;
+
+ afb_export_update_hooks(export);
+ return 0;
}
const char *afb_export_apiname(const struct afb_export *export)
{
- return export->apiname;
+ return export->api.apiname;
}
-void afb_export_update_hook(struct afb_export *export)
+void afb_export_update_hooks(struct afb_export *export)
{
- export->hookditf = afb_hook_flags_ditf(export->apiname);
- export->hooksvc = afb_hook_flags_svc(export->apiname);
- export->dynapi.itf = export->hookditf|export->hooksvc ? &hooked_dynapi_itf : &dynapi_itf;
+ export->hookditf = afb_hook_flags_api(export->api.apiname);
+ export->hooksvc = afb_hook_flags_api(export->api.apiname);
+ export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
switch (export->version) {
+#if defined(WITH_LEGACY_BINDING_V1)
case Api_Version_1:
export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
break;
+#endif
case Api_Version_2:
export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
@@ -1164,11 +1397,6 @@ void afb_export_update_hook(struct afb_export *export)
}
}
-struct afb_binding_interface_v1 *afb_export_get_interface_v1(struct afb_export *export)
-{
- return export->version == Api_Version_1 ? &export->export.v1 : NULL;
-}
-
int afb_export_unshare_session(struct afb_export *export)
{
if (export->session == common_session) {
@@ -1183,126 +1411,107 @@ int afb_export_unshare_session(struct afb_export *export)
return 0;
}
-void afb_export_set_apiset(struct afb_export *export, struct afb_apiset *apiset)
-{
- struct afb_apiset *prvset = export->apiset;
- export->apiset = afb_apiset_addref(apiset);
- afb_apiset_unref(prvset);
-}
-
-struct afb_apiset *afb_export_get_apiset(struct afb_export *export)
-{
- return export->apiset;
-}
-
int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
{
/* check version */
switch (export->version) {
- case Api_Version_1: case Api_Version_2: break;
+#if defined(WITH_LEGACY_BINDING_V1)
+ case Api_Version_1:
+#endif
+ case Api_Version_2:
+ break;
default:
- ERROR("invalid version 12 for API %s", export->apiname);
+ ERROR("invalid version 12 for API %s", export->api.apiname);
errno = EINVAL;
return -1;
}
- /* set the event handler */
- if (!on_event) {
- if (export->listener) {
- afb_evt_listener_unref(export->listener);
- export->listener = NULL;
- }
- export->on_event.v12 = on_event;
- } else {
- export->on_event.v12 = on_event;
- if (!export->listener) {
- export->listener = afb_evt_listener_create(&evt_v12_itf, export);
- if (export->listener == NULL)
- return -1;
- }
- }
- return 0;
+ export->on_any_event_v12 = on_event;
+ return ensure_listener(export);
}
-int afb_export_handle_events_vdyn(struct afb_export *export, void (*on_event)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
+int afb_export_handle_events_v3(struct afb_export *export, void (*on_event)(struct afb_api_x3 *api, const char *event, struct json_object *object))
{
/* check version */
switch (export->version) {
- case Api_Version_Dyn: break;
+ case Api_Version_3: break;
default:
- ERROR("invalid version Dyn for API %s", export->apiname);
+ ERROR("invalid version Dyn for API %s", export->api.apiname);
errno = EINVAL;
return -1;
}
- /* set the event handler */
- if (!on_event) {
- if (export->listener) {
- afb_evt_listener_unref(export->listener);
- export->listener = NULL;
- }
- export->on_event.vdyn = on_event;
- } else {
- export->on_event.vdyn = on_event;
- if (!export->listener) {
- export->listener = afb_evt_listener_create(&evt_vdyn_itf, export);
- if (export->listener == NULL)
- return -1;
- }
- }
- return 0;
+ export->on_any_event_v3 = on_event;
+ return ensure_listener(export);
}
-int afb_export_handle_init_vdyn(struct afb_export *export, int (*oninit)(struct afb_dynapi *dynapi))
+int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
{
if (export->state != Api_State_Pre_Init) {
- ERROR("[API %s] Bad call to 'afb_dynapi_on_init', must be in PreInit", export->apiname);
+ ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
errno = EINVAL;
return -1;
}
- export->init.vdyn = oninit;
+ export->init.v3 = oninit;
return 0;
}
+#if defined(WITH_LEGACY_BINDING_V1)
/*
* Starts a new service (v1)
*/
struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
{
- return regfun(&export->export.v1);
+ return export->desc.v1 = regfun(&export->export.v1);
}
+#endif
-int afb_export_preinit_vdyn(struct afb_export *export, int (*preinit)(void*, struct afb_dynapi*), void *closure)
+int afb_export_preinit_x3(
+ struct afb_export *export,
+ int (*preinit)(void*, struct afb_api_x3*),
+ void *closure)
{
- return preinit(closure, to_dynapi(export));
+ return preinit(closure, to_api_x3(export));
}
-int afb_export_verbosity_get(const struct afb_export *export)
+int afb_export_logmask_get(const struct afb_export *export)
{
- return export->dynapi.verbosity;
+ return export->api.logmask;
}
-void afb_export_verbosity_set(struct afb_export *export, int level)
+void afb_export_logmask_set(struct afb_export *export, int mask)
{
- export->dynapi.verbosity = level;
+ export->api.logmask = mask;
switch (export->version) {
- case Api_Version_1: export->export.v1.verbosity = level; break;
- case Api_Version_2: export->export.v2->verbosity = level; break;
+#if defined(WITH_LEGACY_BINDING_V1)
+ case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
+#endif
+ case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
}
}
-/*************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
+void *afb_export_userdata_get(const struct afb_export *export)
+{
+ return export->api.userdata;
+}
+
+void afb_export_userdata_set(struct afb_export *export, void *data)
+{
+ export->api.userdata = data;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
N E W
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************
- *************************************************************************************************************/
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************
+ ******************************************************************************/
-int afb_export_start(struct afb_export *export, int share_session, int onneed, struct afb_apiset *apiset)
+int afb_export_start(struct afb_export *export, int share_session, int onneed)
{
int rc;
@@ -1313,7 +1522,7 @@ int afb_export_start(struct afb_export *export, int share_session, int onneed, s
goto done;
/* already started: it is an error */
- ERROR("Service of API %s already started", export->apiname);
+ ERROR("Service of API %s already started", export->api.apiname);
return -1;
}
@@ -1321,49 +1530,59 @@ int afb_export_start(struct afb_export *export, int share_session, int onneed, s
if (!share_session) {
rc = afb_export_unshare_session(export);
if (rc < 0) {
- ERROR("Can't unshare the session for %s", export->apiname);
+ ERROR("Can't unshare the session for %s", export->api.apiname);
return -1;
}
}
/* set event handling */
switch (export->version) {
+#if defined(WITH_LEGACY_BINDING_V1)
case Api_Version_1:
+#endif
case Api_Version_2:
- rc = afb_export_handle_events_v12(export, export->on_event.v12);
+ if (export->on_any_event_v12)
+ rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
break;
default:
rc = 0;
break;
}
if (rc < 0) {
- ERROR("Can't set event handler for %s", export->apiname);
+ ERROR("Can't set event handler for %s", export->api.apiname);
return -1;
}
/* Starts the service */
- if (export->hooksvc & afb_hook_flag_svc_start_before)
- afb_hook_svc_start_before(export);
+ if (export->hooksvc & afb_hook_flag_api_start)
+ afb_hook_api_start_before(export);
+
export->state = Api_State_Init;
switch (export->version) {
+#if defined(WITH_LEGACY_BINDING_V1)
case Api_Version_1:
- rc = export->init.v1 ? export->init.v1((struct afb_service){ .itf = &hooked_service_itf, .closure = export }) : 0;
+ rc = export->init.v1 ? export->init.v1((struct afb_service_x1){ .itf = &hooked_service_itf, .closure = to_api_x3(export) }) : 0;
break;
+#endif
case Api_Version_2:
rc = export->init.v2 ? export->init.v2() : 0;
break;
- case Api_Version_Dyn:
- rc = export->init.vdyn ? export->init.vdyn(to_dynapi(export)) : 0;
+ case Api_Version_3:
+ rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
break;
default:
+ errno = EINVAL;
+ rc = -1;
break;
}
export->state = Api_State_Run;
- if (export->hooksvc & afb_hook_flag_svc_start_after)
- afb_hook_svc_start_after(export, rc);
+
+ if (export->hooksvc & afb_hook_flag_api_start)
+ afb_hook_api_start_after(export, rc);
+
if (rc < 0) {
/* initialisation error */
- ERROR("Initialisation of service API %s failed (%d): %m", export->apiname, rc);
+ ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
return rc;
}
@@ -1371,3 +1590,154 @@ done:
return 0;
}
+static void api_call_cb(void *closure, struct afb_xreq *xreq)
+{
+ struct afb_export *export = closure;
+
+ xreq->request.api = to_api_x3(export);
+
+ switch (export->version) {
+#if defined(WITH_LEGACY_BINDING_V1)
+ case Api_Version_1:
+ afb_api_so_v1_process_call(export->desc.v1, xreq);
+ break;
+#endif
+ case Api_Version_2:
+ afb_api_so_v2_process_call(export->desc.v2, xreq);
+ break;
+ case Api_Version_3:
+ afb_api_v3_process_call(export->desc.v3, xreq);
+ break;
+ default:
+ afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
+ break;
+ }
+}
+
+static struct json_object *api_describe_cb(void *closure)
+{
+ struct afb_export *export = closure;
+ struct json_object *result;
+
+ switch (export->version) {
+#if defined(WITH_LEGACY_BINDING_V1)
+ case Api_Version_1:
+ result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
+ break;
+#endif
+ case Api_Version_2:
+ result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
+ break;
+ case Api_Version_3:
+ result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
+ break;
+ default:
+ result = NULL;
+ break;
+ }
+ return result;
+}
+
+static int api_service_start_cb(void *closure, int share_session, int onneed)
+{
+ struct afb_export *export = closure;
+
+ return afb_export_start(export, share_session, onneed);
+}
+
+static void api_update_hooks_cb(void *closure)
+{
+ struct afb_export *export = closure;
+
+ afb_export_update_hooks(export);
+}
+
+static int api_get_logmask_cb(void *closure)
+{
+ struct afb_export *export = closure;
+
+ return afb_export_logmask_get(export);
+}
+
+static void api_set_logmask_cb(void *closure, int level)
+{
+ struct afb_export *export = closure;
+
+ afb_export_logmask_set(export, level);
+}
+
+static void api_unref_cb(void *closure)
+{
+ struct afb_export *export = closure;
+
+ afb_export_unref(export);
+}
+
+static struct afb_api_itf export_api_itf =
+{
+ .call = api_call_cb,
+ .service_start = api_service_start_cb,
+ .update_hooks = api_update_hooks_cb,
+ .get_logmask = api_get_logmask_cb,
+ .set_logmask = api_set_logmask_cb,
+ .describe = api_describe_cb,
+ .unref = api_unref_cb
+};
+
+int afb_export_declare(struct afb_export *export,
+ int noconcurrency)
+{
+ int rc;
+ struct afb_api_item afb_api;
+
+ if (export->declared)
+ rc = 0;
+ else {
+ /* init the record structure */
+ afb_api.closure = afb_export_addref(export);
+ afb_api.itf = &export_api_itf;
+ afb_api.group = noconcurrency ? export : NULL;
+
+ /* records the binding */
+ rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
+ if (rc >= 0)
+ export->declared = 1;
+ else {
+ ERROR("can't declare export %s to set %s, ABORTING it!",
+ export->api.apiname,
+ afb_apiset_name(export->declare_set));
+ afb_export_addref(export);
+ }
+ }
+
+ return rc;
+}
+
+void afb_export_undeclare(struct afb_export *export)
+{
+ if (export->declared) {
+ export->declared = 0;
+ afb_apiset_del(export->declare_set, export->api.apiname);
+ }
+}
+
+int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
+{
+ return afb_evt_event_x2_add_watch(export->listener, event);
+}
+
+int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
+{
+ return afb_evt_event_x2_remove_watch(export->listener, event);
+}
+
+void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
+{
+ afb_xreq_process(xreq, export->call_set);
+}
+
+void afb_export_context_init(struct afb_export *export, struct afb_context *context)
+{
+ afb_context_init(context, export->session, NULL);
+}
+
diff --git a/src/afb-export.h b/src/afb-export.h
index 5acca207..c9046be8 100644
--- a/src/afb-export.h
+++ b/src/afb-export.h
@@ -21,36 +21,111 @@ struct json_object;
struct afb_export;
struct afb_apiset;
-struct afb_api_dyn;
+struct afb_context;
+struct afb_xreq;
-struct afb_service;
+struct afb_binding_v2;
struct afb_binding_data_v2;
-struct afb_binding_interface_v1;
-struct afb_dynapi;
+struct afb_api_v3;
+struct afb_api_x3;
+struct afb_event_x2;
+
+extern struct afb_export *afb_export_create_none_for_path(
+ struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *path,
+ int (*creator)(void*, struct afb_api_x3*),
+ void *closure);
+
+extern struct afb_export *afb_export_create_v2(
+ struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *apiname,
+ const struct afb_binding_v2 *binding,
+ struct afb_binding_data_v2 *data,
+ int (*init)(),
+ void (*onevent)(const char*, struct json_object*));
-extern struct afb_export *afb_export_create_v1(struct afb_apiset *apiset, const char *apiname, int (*init)(struct afb_service), void (*onevent)(const char*, struct json_object*));
-extern struct afb_export *afb_export_create_v2(struct afb_apiset *apiset, const char *apiname, struct afb_binding_data_v2 *data, int (*init)(), void (*onevent)(const char*, struct json_object*));
-extern struct afb_export *afb_export_create_vdyn(struct afb_apiset *apiset, const char *apiname, struct afb_api_dyn *dynapi);
+extern struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *apiname,
+ struct afb_api_v3 *api);
+
+extern struct afb_export *afb_export_addref(struct afb_export *export);
+extern void afb_export_unref(struct afb_export *export);
extern void afb_export_destroy(struct afb_export *export);
+extern int afb_export_declare(struct afb_export *export, int noconcurrency);
+extern void afb_export_undeclare(struct afb_export *export);
+
extern const char *afb_export_apiname(const struct afb_export *export);
-extern void afb_export_rename(struct afb_export *export, const char *apiname);
-extern void afb_export_update_hook(struct afb_export *export);
+extern int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname);
+extern int afb_export_rename(struct afb_export *export, const char *apiname);
+extern void afb_export_update_hooks(struct afb_export *export);
extern int afb_export_unshare_session(struct afb_export *export);
-extern void afb_export_set_apiset(struct afb_export *export, struct afb_apiset *apiset);
-extern struct afb_apiset *afb_export_get_apiset(struct afb_export *export);
-
-extern struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*));
-extern int afb_export_preinit_vdyn(struct afb_export *export, int (*preinit)(void*, struct afb_dynapi*), void *closure);
-extern int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object));
-extern int afb_export_handle_events_vdyn(struct afb_export *export, void (*on_event)(struct afb_dynapi *dynapi, const char *event, struct json_object *object));
-extern int afb_export_handle_init_vdyn(struct afb_export *export, int (*oninit)(struct afb_dynapi *dynapi));
+extern int afb_export_preinit_x3(
+ struct afb_export *export,
+ int (*preinit)(void *,struct afb_api_x3*),
+ void *closure);
+
+extern int afb_export_handle_events_v12(
+ struct afb_export *export,
+ void (*on_event)(const char *event, struct json_object *object));
+
+
+extern int afb_export_handle_events_v3(
+ struct afb_export *export,
+ void (*on_event)(struct afb_api_x3 *api, const char *event, struct json_object *object));
+
+
+extern int afb_export_handle_init_v3(
+ struct afb_export *export,
+ int (*oninit)(struct afb_api_x3 *api));
+
+extern int afb_export_start(struct afb_export *export, int share_session, int onneed);
+
+extern int afb_export_logmask_get(const struct afb_export *export);
+extern void afb_export_logmask_set(struct afb_export *export, int mask);
+
+extern void *afb_export_userdata_get(const struct afb_export *export);
+extern void afb_export_userdata_set(struct afb_export *export, void *data);
+
+extern int afb_export_event_handler_add(
+ struct afb_export *export,
+ const char *pattern,
+ void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
+ void *closure);
+
+extern int afb_export_event_handler_del(
+ struct afb_export *export,
+ const char *pattern,
+ void **closure);
+
+extern int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event);
+extern int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event);
+extern void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq);
+extern void afb_export_context_init(struct afb_export *export, struct afb_context *context);
+extern struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api);
+extern struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export);
+
+#if defined(WITH_LEGACY_BINDING_V1)
+
+struct afb_service_x1;
+struct afb_binding_interface_v1;
+
+extern struct afb_export *afb_export_create_v1(
+ struct afb_apiset *declare_set,
+ struct afb_apiset *call_set,
+ const char *apiname,
+ int (*init)(struct afb_service_x1),
+ void (*onevent)(const char*, struct json_object*));
-extern int afb_export_start(struct afb_export *export, int share_session, int onneed, struct afb_apiset *apiset);
+extern struct afb_binding_v1 *afb_export_register_v1(
+ struct afb_export *export,
+ struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*));
-extern int afb_export_verbosity_get(const struct afb_export *export);
-extern void afb_export_verbosity_set(struct afb_export *export, int level);
+#endif
diff --git a/src/afb-hook.c b/src/afb-hook.c
index f5868b18..75e8a691 100644
--- a/src/afb-hook.c
+++ b/src/afb-hook.c
@@ -27,8 +27,8 @@
#include <json-c/json.h>
-#include <afb/afb-req.h>
-#include <afb/afb-event.h>
+#include <afb/afb-req-x1.h>
+#include <afb/afb-event-x2.h>
#include "afb-context.h"
#include "afb-hook.h"
@@ -38,10 +38,19 @@
#include "afb-export.h"
#include "afb-evt.h"
#include "afb-api.h"
+#include "afb-msg-json.h"
#include "verbose.h"
#include <fnmatch.h>
-#define MATCH(pattern,string) (!fnmatch((pattern),(string),FNM_CASEFOLD|FNM_EXTMATCH))
+#define MATCH(pattern,string) (\
+ pattern \
+ ? !fnmatch((pattern),(string),FNM_CASEFOLD|FNM_EXTMATCH|FNM_PERIOD) \
+ : (string)[0] != '.')
+
+#define MATCH_API(pattern,string) MATCH(pattern,string)
+#define MATCH_VERB(pattern,string) MATCH(pattern,string)
+#define MATCH_EVENT(pattern,string) MATCH(pattern,string)
+#define MATCH_SESSION(pattern,string) MATCH(pattern,string)
/**
* Definition of a hook for xreq
@@ -60,24 +69,12 @@ struct afb_hook_xreq {
/**
* Definition of a hook for export
*/
-struct afb_hook_ditf {
- struct afb_hook_ditf *next; /**< next hook */
+struct afb_hook_api {
+ struct afb_hook_api *next; /**< next hook */
unsigned refcount; /**< reference count */
unsigned flags; /**< hook flags */
char *api; /**< api hooked or NULL for any */
- struct afb_hook_ditf_itf *itf; /**< interface of hook */
- void *closure; /**< closure for callbacks */
-};
-
-/**
- * Definition of a hook for export
- */
-struct afb_hook_svc {
- struct afb_hook_svc *next; /**< next hook */
- unsigned refcount; /**< reference count */
- unsigned flags; /**< hook flags */
- char *api; /**< api hooked or NULL for any */
- struct afb_hook_svc_itf *itf; /**< interface of hook */
+ struct afb_hook_api_itf *itf; /**< interface of hook */
void *closure; /**< closure for callbacks */
};
@@ -123,10 +120,7 @@ static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
static struct afb_hook_xreq *list_of_xreq_hooks = NULL;
/* list of hooks for export */
-static struct afb_hook_ditf *list_of_ditf_hooks = NULL;
-
-/* list of hooks for export */
-static struct afb_hook_svc *list_of_svc_hooks = NULL;
+static struct afb_hook_api *list_of_api_hooks = NULL;
/* list of hooks for evt */
static struct afb_hook_evt *list_of_evt_hooks = NULL;
@@ -225,11 +219,11 @@ static void _hook_xreq_(const struct afb_xreq *xreq, const char *format, ...)
{
va_list ap;
va_start(ap, format);
- _hook_("xreq-%06d:%s/%s", format, ap, xreq->hookindex, xreq->request.api, xreq->request.verb);
+ _hook_("xreq-%06d:%s/%s", format, ap, xreq->hookindex, xreq->request.called_api, xreq->request.called_verb);
va_end(ap);
}
-static void hook_xreq_begin_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
+static void hook_xreq_begin_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
{
if (!xreq->cred)
_hook_xreq_(xreq, "BEGIN");
@@ -244,92 +238,87 @@ static void hook_xreq_begin_default_cb(void *closure, const struct afb_hookid *h
);
}
-static void hook_xreq_end_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
+static void hook_xreq_end_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
{
_hook_xreq_(xreq, "END");
}
-static void hook_xreq_json_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *obj)
+static void hook_xreq_json_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *obj)
{
_hook_xreq_(xreq, "json() -> %s", json_object_to_json_string(obj));
}
-static void hook_xreq_get_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *name, struct afb_arg arg)
+static void hook_xreq_get_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *name, struct afb_arg arg)
{
_hook_xreq_(xreq, "get(%s) -> { name: %s, value: %s, path: %s }", name, arg.name, arg.value, arg.path);
}
-static void hook_xreq_success_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *obj, const char *info)
-{
- _hook_xreq_(xreq, "success(%s, %s)", json_object_to_json_string(obj), info);
-}
-
-static void hook_xreq_fail_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *status, const char *info)
+static void hook_xreq_reply_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info)
{
- _hook_xreq_(xreq, "fail(%s, %s)", status, info);
+ _hook_xreq_(xreq, "reply[%s](%s, %s)", error?:"success", json_object_to_json_string(obj), info);
}
-static void hook_xreq_context_get_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, void *value)
+static void hook_xreq_legacy_context_get_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, void *value)
{
_hook_xreq_(xreq, "context_get() -> %p", value);
}
-static void hook_xreq_context_set_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, void *value, void (*free_value)(void*))
+static void hook_xreq_legacy_context_set_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, void *value, void (*free_value)(void*))
{
_hook_xreq_(xreq, "context_set(%p, %p)", value, free_value);
}
-static void hook_xreq_addref_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
+static void hook_xreq_addref_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
{
_hook_xreq_(xreq, "addref()");
}
-static void hook_xreq_unref_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
+static void hook_xreq_unref_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
{
_hook_xreq_(xreq, "unref()");
}
-static void hook_xreq_session_close_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
+static void hook_xreq_session_close_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
{
_hook_xreq_(xreq, "session_close()");
}
-static void hook_xreq_session_set_LOA_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, unsigned level, int result)
+static void hook_xreq_session_set_LOA_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, unsigned level, int result)
{
_hook_xreq_(xreq, "session_set_LOA(%u) -> %d", level, result);
}
-static void hook_xreq_subscribe_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_eventid *eventid, int result)
+static void hook_xreq_subscribe_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_event_x2 *event_x2, int result)
{
- _hook_xreq_(xreq, "subscribe(%s:%d) -> %d", afb_evt_eventid_fullname(eventid), afb_evt_eventid_id(eventid), result);
+ _hook_xreq_(xreq, "subscribe(%s:%d) -> %d", afb_evt_event_x2_fullname(event_x2), afb_evt_event_x2_id(event_x2), result);
}
-static void hook_xreq_unsubscribe_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_eventid *eventid, int result)
+static void hook_xreq_unsubscribe_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_event_x2 *event_x2, int result)
{
- _hook_xreq_(xreq, "unsubscribe(%s:%d) -> %d", afb_evt_eventid_fullname(eventid), afb_evt_eventid_id(eventid), result);
+ _hook_xreq_(xreq, "unsubscribe(%s:%d) -> %d", afb_evt_event_x2_fullname(event_x2), afb_evt_event_x2_id(event_x2), result);
}
-static void hook_xreq_subcall_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
+static void hook_xreq_subcall_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
{
_hook_xreq_(xreq, "subcall(%s/%s, %s) ...", api, verb, json_object_to_json_string(args));
}
-static void hook_xreq_subcall_result_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result)
+static void hook_xreq_subcall_result_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info)
{
- _hook_xreq_(xreq, " ...subcall... -> %d: %s", status, json_object_to_json_string(result));
+ _hook_xreq_(xreq, " ...subcall... [%s] -> %s (%s)", error?:"success", json_object_to_json_string(object), info?:"");
}
-static void hook_xreq_subcallsync_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
+static void hook_xreq_subcallsync_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
{
_hook_xreq_(xreq, "subcallsync(%s/%s, %s) ...", api, verb, json_object_to_json_string(args));
}
-static void hook_xreq_subcallsync_result_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result)
+static void hook_xreq_subcallsync_result_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *object, const char *error, const char *info)
{
- _hook_xreq_(xreq, " ...subcallsync... -> %d: %s", status, json_object_to_json_string(result));
+ _hook_xreq_(xreq, " ...subcallsync... %d [%s] -> %s (%s)", status, error?:"success", json_object_to_json_string(object), info?:"");
}
-static void hook_xreq_vverbose_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int level, const char *file, int line, const char *func, const char *fmt, va_list args)
+static void hook_xreq_vverbose_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int level, const char *file, int line, const char *func, const char *fmt, va_list args)
{
int len;
char *msg;
@@ -340,105 +329,99 @@ static void hook_xreq_vverbose_default_cb(void *closure, const struct afb_hookid
va_end(ap);
if (len < 0)
- _hook_xreq_(xreq, "vverbose(%d, %s, %d, %s) -> %s ? ? ?", level, file, line, func, fmt);
+ _hook_xreq_(xreq, "vverbose(%d:%s, %s, %d, %s) -> %s ? ? ?", level, verbose_name_of_level(level), file, line, func, fmt);
else {
- _hook_xreq_(xreq, "vverbose(%d, %s, %d, %s) -> %s", level, file, line, func, msg);
+ _hook_xreq_(xreq, "vverbose(%d:%s, %s, %d, %s) -> %s", level, verbose_name_of_level(level), file, line, func, msg);
free(msg);
}
}
-static void hook_xreq_store_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_stored_req *sreq)
+static void hook_xreq_legacy_store_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_stored_req *sreq)
{
_hook_xreq_(xreq, "store() -> %p", sreq);
}
-static void hook_xreq_unstore_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
+static void hook_xreq_legacy_unstore_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
{
_hook_xreq_(xreq, "unstore()");
}
-static void hook_xreq_subcall_req_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
-{
- _hook_xreq_(xreq, "subcall_req(%s/%s, %s) ...", api, verb, json_object_to_json_string(args));
-}
-
-static void hook_xreq_subcall_req_result_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result)
-{
- _hook_xreq_(xreq, " ...subcall_req... -> %d: %s", status, json_object_to_json_string(result));
-}
-
-static void hook_xreq_has_permission_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *permission, int result)
+static void hook_xreq_has_permission_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *permission, int result)
{
_hook_xreq_(xreq, "has_permission(%s) -> %d", permission, result);
}
-static void hook_xreq_get_application_id_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, char *result)
+static void hook_xreq_get_application_id_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, char *result)
{
_hook_xreq_(xreq, "get_application_id() -> %s", result);
}
-static void hook_xreq_context_make_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure, void *result)
+static void hook_xreq_context_make_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure, void *result)
{
_hook_xreq_(xreq, "context_make(replace=%s, %p, %p, %p) -> %p", replace?"yes":"no", create_value, free_value, create_closure, result);
}
-static void hook_xreq_get_uid_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int result)
+static void hook_xreq_get_uid_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int result)
{
_hook_xreq_(xreq, "get_uid() -> %d", result);
}
+static void hook_xreq_get_client_info_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *result)
+{
+ _hook_xreq_(xreq, "get_client_info() -> %s", json_object_to_json_string(result));
+}
+
static struct afb_hook_xreq_itf hook_xreq_default_itf = {
- .hook_xreq_begin = hook_xreq_begin_default_cb,
- .hook_xreq_end = hook_xreq_end_default_cb,
- .hook_xreq_json = hook_xreq_json_default_cb,
- .hook_xreq_get = hook_xreq_get_default_cb,
- .hook_xreq_success = hook_xreq_success_default_cb,
- .hook_xreq_fail = hook_xreq_fail_default_cb,
- .hook_xreq_context_get = hook_xreq_context_get_default_cb,
- .hook_xreq_context_set = hook_xreq_context_set_default_cb,
- .hook_xreq_addref = hook_xreq_addref_default_cb,
- .hook_xreq_unref = hook_xreq_unref_default_cb,
- .hook_xreq_session_close = hook_xreq_session_close_default_cb,
- .hook_xreq_session_set_LOA = hook_xreq_session_set_LOA_default_cb,
- .hook_xreq_subscribe = hook_xreq_subscribe_default_cb,
- .hook_xreq_unsubscribe = hook_xreq_unsubscribe_default_cb,
- .hook_xreq_subcall = hook_xreq_subcall_default_cb,
- .hook_xreq_subcall_result = hook_xreq_subcall_result_default_cb,
- .hook_xreq_subcallsync = hook_xreq_subcallsync_default_cb,
- .hook_xreq_subcallsync_result = hook_xreq_subcallsync_result_default_cb,
- .hook_xreq_vverbose = hook_xreq_vverbose_default_cb,
- .hook_xreq_store = hook_xreq_store_default_cb,
- .hook_xreq_unstore = hook_xreq_unstore_default_cb,
- .hook_xreq_subcall_req = hook_xreq_subcall_req_default_cb,
- .hook_xreq_subcall_req_result = hook_xreq_subcall_req_result_default_cb,
- .hook_xreq_has_permission = hook_xreq_has_permission_default_cb,
- .hook_xreq_get_application_id = hook_xreq_get_application_id_default_cb,
- .hook_xreq_context_make = hook_xreq_context_make_default_cb,
- .hook_xreq_get_uid = hook_xreq_get_uid_default_cb,
+ .hook_xreq_begin = hook_xreq_begin_cb,
+ .hook_xreq_end = hook_xreq_end_cb,
+ .hook_xreq_json = hook_xreq_json_cb,
+ .hook_xreq_get = hook_xreq_get_cb,
+ .hook_xreq_reply = hook_xreq_reply_cb,
+ .hook_xreq_legacy_context_get = hook_xreq_legacy_context_get_cb,
+ .hook_xreq_legacy_context_set = hook_xreq_legacy_context_set_cb,
+ .hook_xreq_addref = hook_xreq_addref_cb,
+ .hook_xreq_unref = hook_xreq_unref_cb,
+ .hook_xreq_session_close = hook_xreq_session_close_cb,
+ .hook_xreq_session_set_LOA = hook_xreq_session_set_LOA_cb,
+ .hook_xreq_subscribe = hook_xreq_subscribe_cb,
+ .hook_xreq_unsubscribe = hook_xreq_unsubscribe_cb,
+ .hook_xreq_subcall = hook_xreq_subcall_cb,
+ .hook_xreq_subcall_result = hook_xreq_subcall_result_cb,
+ .hook_xreq_subcallsync = hook_xreq_subcallsync_cb,
+ .hook_xreq_subcallsync_result = hook_xreq_subcallsync_result_cb,
+ .hook_xreq_vverbose = hook_xreq_vverbose_cb,
+ .hook_xreq_legacy_store = hook_xreq_legacy_store_cb,
+ .hook_xreq_legacy_unstore = hook_xreq_legacy_unstore_cb,
+ .hook_xreq_has_permission = hook_xreq_has_permission_cb,
+ .hook_xreq_get_application_id = hook_xreq_get_application_id_cb,
+ .hook_xreq_context_make = hook_xreq_context_make_cb,
+ .hook_xreq_get_uid = hook_xreq_get_uid_cb,
+ .hook_xreq_get_client_info = hook_xreq_get_client_info_cb,
};
/******************************************************************************
* section: hooks for tracing requests
*****************************************************************************/
-#define _HOOK_XREQ_(what,...) \
+#define _HOOK_XREQ_2_(flag,func,...) \
struct afb_hook_xreq *hook; \
struct afb_hookid hookid; \
pthread_rwlock_rdlock(&rwlock); \
init_hookid(&hookid); \
hook = list_of_xreq_hooks; \
while (hook) { \
- if (hook->itf->hook_xreq_##what \
- && (hook->flags & afb_hook_flag_req_##what) != 0 \
+ if (hook->itf->hook_xreq_##func \
+ && (hook->flags & afb_hook_flag_req_##flag) != 0 \
&& (!hook->session || hook->session == xreq->context.session) \
- && (!hook->api || !strcasecmp(hook->api, xreq->request.api)) \
- && (!hook->verb || !strcasecmp(hook->verb, xreq->request.verb))) { \
- hook->itf->hook_xreq_##what(hook->closure, &hookid, __VA_ARGS__); \
+ && MATCH_API(hook->api, xreq->request.called_api) \
+ && MATCH_VERB(hook->verb, xreq->request.called_verb)) { \
+ hook->itf->hook_xreq_##func(hook->closure, &hookid, __VA_ARGS__); \
} \
hook = hook->next; \
} \
pthread_rwlock_unlock(&rwlock);
+#define _HOOK_XREQ_(what,...) _HOOK_XREQ_2_(what,what,__VA_ARGS__)
void afb_hook_xreq_begin(const struct afb_xreq *xreq)
{
@@ -462,25 +445,20 @@ struct afb_arg afb_hook_xreq_get(const struct afb_xreq *xreq, const char *name,
return arg;
}
-void afb_hook_xreq_success(const struct afb_xreq *xreq, struct json_object *obj, const char *info)
+void afb_hook_xreq_reply(const struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info)
{
- _HOOK_XREQ_(success, xreq, obj, info);
+ _HOOK_XREQ_(reply, xreq, obj, error, info);
}
-void afb_hook_xreq_fail(const struct afb_xreq *xreq, const char *status, const char *info)
+void *afb_hook_xreq_legacy_context_get(const struct afb_xreq *xreq, void *value)
{
- _HOOK_XREQ_(fail, xreq, status, info);
-}
-
-void *afb_hook_xreq_context_get(const struct afb_xreq *xreq, void *value)
-{
- _HOOK_XREQ_(context_get, xreq, value);
+ _HOOK_XREQ_(legacy_context_get, xreq, value);
return value;
}
-void afb_hook_xreq_context_set(const struct afb_xreq *xreq, void *value, void (*free_value)(void*))
+void afb_hook_xreq_legacy_context_set(const struct afb_xreq *xreq, void *value, void (*free_value)(void*))
{
- _HOOK_XREQ_(context_set, xreq, value, free_value);
+ _HOOK_XREQ_(legacy_context_set, xreq, value, free_value);
}
void afb_hook_xreq_addref(const struct afb_xreq *xreq)
@@ -504,36 +482,36 @@ int afb_hook_xreq_session_set_LOA(const struct afb_xreq *xreq, unsigned level, i
return result;
}
-int afb_hook_xreq_subscribe(const struct afb_xreq *xreq, struct afb_eventid *eventid, int result)
+int afb_hook_xreq_subscribe(const struct afb_xreq *xreq, struct afb_event_x2 *event_x2, int result)
{
- _HOOK_XREQ_(subscribe, xreq, eventid, result);
+ _HOOK_XREQ_(subscribe, xreq, event_x2, result);
return result;
}
-int afb_hook_xreq_unsubscribe(const struct afb_xreq *xreq, struct afb_eventid *eventid, int result)
+int afb_hook_xreq_unsubscribe(const struct afb_xreq *xreq, struct afb_event_x2 *event_x2, int result)
{
- _HOOK_XREQ_(unsubscribe, xreq, eventid, result);
+ _HOOK_XREQ_(unsubscribe, xreq, event_x2, result);
return result;
}
-void afb_hook_xreq_subcall(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
+void afb_hook_xreq_subcall(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, int flags)
{
_HOOK_XREQ_(subcall, xreq, api, verb, args);
}
-void afb_hook_xreq_subcall_result(const struct afb_xreq *xreq, int status, struct json_object *result)
+void afb_hook_xreq_subcall_result(const struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info)
{
- _HOOK_XREQ_(subcall_result, xreq, status, result);
+ _HOOK_XREQ_(subcall_result, xreq, object, error, info);
}
-void afb_hook_xreq_subcallsync(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
+void afb_hook_xreq_subcallsync(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, int flags)
{
_HOOK_XREQ_(subcallsync, xreq, api, verb, args);
}
-int afb_hook_xreq_subcallsync_result(const struct afb_xreq *xreq, int status, struct json_object *result)
+int afb_hook_xreq_subcallsync_result(const struct afb_xreq *xreq, int status, struct json_object *object, const char *error, const char *info)
{
- _HOOK_XREQ_(subcallsync_result, xreq, status, result);
+ _HOOK_XREQ_(subcallsync_result, xreq, status, object, error, info);
return status;
}
@@ -542,24 +520,14 @@ void afb_hook_xreq_vverbose(const struct afb_xreq *xreq, int level, const char *
_HOOK_XREQ_(vverbose, xreq, level, file ?: "?", line, func ?: "?", fmt, args);
}
-void afb_hook_xreq_store(const struct afb_xreq *xreq, struct afb_stored_req *sreq)
-{
- _HOOK_XREQ_(store, xreq, sreq);
-}
-
-void afb_hook_xreq_unstore(const struct afb_xreq *xreq)
-{
- _HOOK_XREQ_(unstore, xreq);
-}
-
-void afb_hook_xreq_subcall_req(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
+void afb_hook_xreq_legacy_store(const struct afb_xreq *xreq, struct afb_stored_req *sreq)
{
- _HOOK_XREQ_(subcall_req, xreq, api, verb, args);
+ _HOOK_XREQ_(legacy_store, xreq, sreq);
}
-void afb_hook_xreq_subcall_req_result(const struct afb_xreq *xreq, int status, struct json_object *result)
+void afb_hook_xreq_legacy_unstore(const struct afb_xreq *xreq)
{
- _HOOK_XREQ_(subcall_req_result, xreq, status, result);
+ _HOOK_XREQ_(legacy_unstore, xreq);
}
int afb_hook_xreq_has_permission(const struct afb_xreq *xreq, const char *permission, int result)
@@ -586,6 +554,12 @@ int afb_hook_xreq_get_uid(const struct afb_xreq *xreq, int result)
return result;
}
+struct json_object *afb_hook_xreq_get_client_info(const struct afb_xreq *xreq, struct json_object *result)
+{
+ _HOOK_XREQ_(get_client_info, xreq, result);
+ return result;
+}
+
/******************************************************************************
* section: hooking xreqs
*****************************************************************************/
@@ -600,21 +574,19 @@ void afb_hook_init_xreq(struct afb_xreq *xreq)
/* scan hook list to get the expected flags */
flags = 0;
- if (afb_api_is_hookable(xreq->request.api)) {
- pthread_rwlock_rdlock(&rwlock);
- hook = list_of_xreq_hooks;
- while (hook) {
- f = hook->flags & afb_hook_flags_req_all;
- add = f != 0
- && (!hook->session || hook->session == xreq->context.session)
- && (!hook->api || !strcasecmp(hook->api, xreq->request.api))
- && (!hook->verb || !strcasecmp(hook->verb, xreq->request.verb));
- if (add)
- flags |= f;
- hook = hook->next;
- }
- pthread_rwlock_unlock(&rwlock);
+ pthread_rwlock_rdlock(&rwlock);
+ hook = list_of_xreq_hooks;
+ while (hook) {
+ f = hook->flags & afb_hook_flags_req_all;
+ add = f != 0
+ && (!hook->session || hook->session == xreq->context.session)
+ && MATCH_API(hook->api, xreq->request.called_api)
+ && MATCH_VERB(hook->verb, xreq->request.called_verb);
+ if (add)
+ flags |= f;
+ hook = hook->next;
}
+ pthread_rwlock_unlock(&rwlock);
/* store the hooking data */
xreq->hookflags = flags;
@@ -705,40 +677,40 @@ void afb_hook_unref_xreq(struct afb_hook_xreq *hook)
* section: default callbacks for tracing daemon interface
*****************************************************************************/
-static void _hook_ditf_(const struct afb_export *export, const char *format, ...)
+static void _hook_api_(const struct afb_export *export, const char *format, ...)
{
va_list ap;
va_start(ap, format);
- _hook_("export-%s", format, ap, afb_export_apiname(export));
+ _hook_("api-%s", format, ap, afb_export_apiname(export));
va_end(ap);
}
-static void hook_ditf_event_broadcast_before_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object)
+static void hook_api_event_broadcast_before_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object)
{
- _hook_ditf_(export, "event_broadcast.before(%s, %s)....", name, json_object_to_json_string(object));
+ _hook_api_(export, "event_broadcast.before(%s, %s)....", name, json_object_to_json_string(object));
}
-static void hook_ditf_event_broadcast_after_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object, int result)
+static void hook_api_event_broadcast_after_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object, int result)
{
- _hook_ditf_(export, "event_broadcast.after(%s, %s) -> %d", name, json_object_to_json_string(object), result);
+ _hook_api_(export, "event_broadcast.after(%s, %s) -> %d", name, json_object_to_json_string(object), result);
}
-static void hook_ditf_get_event_loop_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_event *result)
+static void hook_api_get_event_loop_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_event *result)
{
- _hook_ditf_(export, "get_event_loop() -> %p", result);
+ _hook_api_(export, "get_event_loop() -> %p", result);
}
-static void hook_ditf_get_user_bus_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result)
+static void hook_api_get_user_bus_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result)
{
- _hook_ditf_(export, "get_user_bus() -> %p", result);
+ _hook_api_(export, "get_user_bus() -> %p", result);
}
-static void hook_ditf_get_system_bus_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result)
+static void hook_api_get_system_bus_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result)
{
- _hook_ditf_(export, "get_system_bus() -> %p", result);
+ _hook_api_(export, "get_system_bus() -> %p", result);
}
-static void hook_ditf_vverbose_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
+static void hook_api_vverbose_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
{
int len;
char *msg;
@@ -749,427 +721,489 @@ static void hook_ditf_vverbose_cb(void *closure, const struct afb_hookid *hookid
va_end(ap);
if (len < 0)
- _hook_ditf_(export, "vverbose(%d, %s, %d, %s) -> %s ? ? ?", level, file, line, function, fmt);
+ _hook_api_(export, "vverbose(%d:%s, %s, %d, %s) -> %s ? ? ?", level, verbose_name_of_level(level), file, line, function, fmt);
else {
- _hook_ditf_(export, "vverbose(%d, %s, %d, %s) -> %s", level, file, line, function, msg);
+ _hook_api_(export, "vverbose(%d:%s, %s, %d, %s) -> %s", level, verbose_name_of_level(level), file, line, function, msg);
free(msg);
}
}
-static void hook_ditf_event_make_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_eventid *result)
+static void hook_api_event_make_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_event_x2 *result)
{
- _hook_ditf_(export, "event_make(%s) -> %s:%d", name, afb_evt_eventid_fullname(result), afb_evt_eventid_id(result));
+ _hook_api_(export, "event_make(%s) -> %s:%d", name, afb_evt_event_x2_fullname(result), afb_evt_event_x2_id(result));
}
-static void hook_ditf_rootdir_get_fd_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
+static void hook_api_rootdir_get_fd_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
{
char path[PATH_MAX];
if (result < 0)
- _hook_ditf_(export, "rootdir_get_fd() -> %d, %m", result);
+ _hook_api_(export, "rootdir_get_fd() -> %d, %m", result);
else {
sprintf(path, "/proc/self/fd/%d", result);
readlink(path, path, sizeof path);
- _hook_ditf_(export, "rootdir_get_fd() -> %d = %s", result, path);
+ _hook_api_(export, "rootdir_get_fd() -> %d = %s", result, path);
}
}
-static void hook_ditf_rootdir_open_locale_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *filename, int flags, const char *locale, int result)
+static void hook_api_rootdir_open_locale_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *filename, int flags, const char *locale, int result)
{
char path[PATH_MAX];
if (!locale)
locale = "(null)";
if (result < 0)
- _hook_ditf_(export, "rootdir_open_locale(%s, %d, %s) -> %d, %m", filename, flags, locale, result);
+ _hook_api_(export, "rootdir_open_locale(%s, %d, %s) -> %d, %m", filename, flags, locale, result);
else {
sprintf(path, "/proc/self/fd/%d", result);
readlink(path, path, sizeof path);
- _hook_ditf_(export, "rootdir_open_locale(%s, %d, %s) -> %d = %s", filename, flags, locale, result, path);
+ _hook_api_(export, "rootdir_open_locale(%s, %d, %s) -> %d = %s", filename, flags, locale, result, path);
}
}
-static void hook_ditf_queue_job_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result)
+static void hook_api_queue_job_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result)
+{
+ _hook_api_(export, "queue_job(%p, %p, %p, %d) -> %d", callback, argument, group, timeout, result);
+}
+
+static void hook_api_unstore_req_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct afb_stored_req *sreq)
+{
+ _hook_api_(export, "unstore_req(%p)", sreq);
+}
+
+static void hook_api_require_api_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized)
+{
+ _hook_api_(export, "require_api(%s, %d)...", name, initialized);
+}
+
+static void hook_api_require_api_result_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized, int result)
+{
+ _hook_api_(export, "...require_api(%s, %d) -> %d", name, initialized, result);
+}
+
+static void hook_api_add_alias_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *alias, int result)
+{
+ _hook_api_(export, "add_alias(%s -> %s) -> %d", api, alias?:"<null>", result);
+}
+
+static void hook_api_start_before_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export)
+{
+ _hook_api_(export, "start.before");
+}
+
+static void hook_api_start_after_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status)
+{
+ _hook_api_(export, "start.after -> %d", status);
+}
+
+static void hook_api_on_event_before_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int event_x2, struct json_object *object)
+{
+ _hook_api_(export, "on_event.before(%s, %d, %s)", event, event_x2, json_object_to_json_string(object));
+}
+
+static void hook_api_on_event_after_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int event_x2, struct json_object *object)
+{
+ _hook_api_(export, "on_event.after(%s, %d, %s)", event, event_x2, json_object_to_json_string(object));
+}
+
+static void hook_api_call_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
+{
+ _hook_api_(export, "call(%s/%s, %s) ...", api, verb, json_object_to_json_string(args));
+}
+
+static void hook_api_call_result_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct json_object *object, const char *error, const char *info)
+{
+ _hook_api_(export, " ...call... [%s] -> %s (%s)", error?:"success", json_object_to_json_string(object), info?:"");
+}
+
+static void hook_api_callsync_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
+{
+ _hook_api_(export, "callsync(%s/%s, %s) ...", api, verb, json_object_to_json_string(args));
+}
+
+static void hook_api_callsync_result_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *object, const char *error, const char *info)
+{
+ _hook_api_(export, " ...callsync... %d [%s] -> %s (%s)", status, error?:"success", json_object_to_json_string(object), info?:"");
+}
+
+static void hook_api_new_api_before_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *info, int noconcurrency)
+{
+ _hook_api_(export, "new_api.before %s (%s)%s ...", api, info?:"", noconcurrency?" no-concurrency" : "");
+}
+
+static void hook_api_new_api_after_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *api)
+{
+ _hook_api_(export, "... new_api.after %s -> %s (%d)", api, result >= 0 ? "OK" : "ERROR", result);
+}
+
+static void hook_api_api_set_verbs_v2_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const struct afb_verb_v2 *verbs)
+{
+ _hook_api_(export, "set_verbs_v2 -> %s (%d)", result >= 0 ? "OK" : "ERROR", result);
+}
+
+static void hook_api_api_set_verbs_v3_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const struct afb_verb_v3 *verbs)
+{
+ _hook_api_(export, "set_verbs_v3 -> %s (%d)", result >= 0 ? "OK" : "ERROR", result);
+}
+
+static void hook_api_api_add_verb_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *verb, const char *info, int glob)
+{
+ _hook_api_(export, "add_verb(%s%s [%s]) -> %s (%d)", verb, glob?" (GLOB)":"", info?:"", result >= 0 ? "OK" : "ERROR", result);
+}
+
+static void hook_api_api_del_verb_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *verb)
+{
+ _hook_api_(export, "del_verb(%s) -> %s (%d)", verb, result >= 0 ? "OK" : "ERROR", result);
+}
+
+static void hook_api_api_set_on_event_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
+{
+ _hook_api_(export, "set_on_event -> %s (%d)", result >= 0 ? "OK" : "ERROR", result);
+}
+
+static void hook_api_api_set_on_init_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
+{
+ _hook_api_(export, "set_on_init -> %s (%d)", result >= 0 ? "OK" : "ERROR", result);
+}
+
+static void hook_api_api_seal_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export)
+{
+ _hook_api_(export, "seal");
+}
+
+static void hook_api_event_handler_add_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *pattern)
+{
+ _hook_api_(export, "event_handler_add(%s) -> %s (%d)", pattern, result >= 0 ? "OK" : "ERROR", result);
+}
+
+static void hook_api_event_handler_del_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *pattern)
+{
+ _hook_api_(export, "event_handler_del(%s) -> %s (%d)", pattern, result >= 0 ? "OK" : "ERROR", result);
+}
+
+static void hook_api_class_provide_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *name)
{
- _hook_ditf_(export, "queue_job(%p, %p, %p, %d) -> %d", callback, argument, group, timeout, result);
+ _hook_api_(export, "class_provide(%s) -> %s (%d)", name, result >= 0 ? "OK" : "ERROR", result);
}
-static void hook_ditf_unstore_req_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct afb_stored_req *sreq)
+static void hook_api_class_require_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *name)
{
- _hook_ditf_(export, "unstore_req(%p)", sreq);
+ _hook_api_(export, "class_require(%s) -> %s (%d)", name, result >= 0 ? "OK" : "ERROR", result);
}
-static void hook_ditf_require_api_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized)
+static void hook_api_delete_api_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
{
- _hook_ditf_(export, "require_api(%s, %d)...", name, initialized);
+ _hook_api_(export, "delete_api -> %s (%d)", result >= 0 ? "OK" : "ERROR", result);
}
-static void hook_ditf_require_api_result_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized, int result)
+static void hook_api_on_event_handler_before_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int event_x2, struct json_object *object, const char *pattern)
{
- _hook_ditf_(export, "...require_api(%s, %d) -> %d", name, initialized, result);
+ _hook_api_(export, "on_event_handler[%s].before(%s, %d, %s)", pattern, event, event_x2, json_object_to_json_string(object));
}
-static void hook_ditf_rename_api_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *oldname, const char *newname, int result)
+static void hook_api_on_event_handler_after_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int event_x2, struct json_object *object, const char *pattern)
{
- _hook_ditf_(export, "rename_api(%s -> %s) -> %d", oldname, newname, result);
+ _hook_api_(export, "on_event_handler[%s].after(%s, %d, %s)", pattern, event, event_x2, json_object_to_json_string(object));
}
-static struct afb_hook_ditf_itf hook_ditf_default_itf = {
- .hook_ditf_event_broadcast_before = hook_ditf_event_broadcast_before_cb,
- .hook_ditf_event_broadcast_after = hook_ditf_event_broadcast_after_cb,
- .hook_ditf_get_event_loop = hook_ditf_get_event_loop_cb,
- .hook_ditf_get_user_bus = hook_ditf_get_user_bus_cb,
- .hook_ditf_get_system_bus = hook_ditf_get_system_bus_cb,
- .hook_ditf_vverbose = hook_ditf_vverbose_cb,
- .hook_ditf_event_make = hook_ditf_event_make_cb,
- .hook_ditf_rootdir_get_fd = hook_ditf_rootdir_get_fd_cb,
- .hook_ditf_rootdir_open_locale = hook_ditf_rootdir_open_locale_cb,
- .hook_ditf_queue_job = hook_ditf_queue_job_cb,
- .hook_ditf_unstore_req = hook_ditf_unstore_req_cb,
- .hook_ditf_require_api = hook_ditf_require_api_cb,
- .hook_ditf_require_api_result = hook_ditf_require_api_result_cb,
- .hook_ditf_rename_api = hook_ditf_rename_api_cb
+static struct afb_hook_api_itf hook_api_default_itf = {
+ .hook_api_event_broadcast_before = hook_api_event_broadcast_before_cb,
+ .hook_api_event_broadcast_after = hook_api_event_broadcast_after_cb,
+ .hook_api_get_event_loop = hook_api_get_event_loop_cb,
+ .hook_api_get_user_bus = hook_api_get_user_bus_cb,
+ .hook_api_get_system_bus = hook_api_get_system_bus_cb,
+ .hook_api_vverbose = hook_api_vverbose_cb,
+ .hook_api_event_make = hook_api_event_make_cb,
+ .hook_api_rootdir_get_fd = hook_api_rootdir_get_fd_cb,
+ .hook_api_rootdir_open_locale = hook_api_rootdir_open_locale_cb,
+ .hook_api_queue_job = hook_api_queue_job_cb,
+ .hook_api_legacy_unstore_req = hook_api_unstore_req_cb,
+ .hook_api_require_api = hook_api_require_api_cb,
+ .hook_api_require_api_result = hook_api_require_api_result_cb,
+ .hook_api_add_alias = hook_api_add_alias_cb,
+ .hook_api_start_before = hook_api_start_before_cb,
+ .hook_api_start_after = hook_api_start_after_cb,
+ .hook_api_on_event_before = hook_api_on_event_before_cb,
+ .hook_api_on_event_after = hook_api_on_event_after_cb,
+ .hook_api_call = hook_api_call_cb,
+ .hook_api_call_result = hook_api_call_result_cb,
+ .hook_api_callsync = hook_api_callsync_cb,
+ .hook_api_callsync_result = hook_api_callsync_result_cb,
+ .hook_api_new_api_before = hook_api_new_api_before_cb,
+ .hook_api_new_api_after = hook_api_new_api_after_cb,
+ .hook_api_api_set_verbs_v2 = hook_api_api_set_verbs_v2_cb,
+ .hook_api_api_set_verbs_v3 = hook_api_api_set_verbs_v3_cb,
+ .hook_api_api_add_verb = hook_api_api_add_verb_cb,
+ .hook_api_api_del_verb = hook_api_api_del_verb_cb,
+ .hook_api_api_set_on_event = hook_api_api_set_on_event_cb,
+ .hook_api_api_set_on_init = hook_api_api_set_on_init_cb,
+ .hook_api_api_seal = hook_api_api_seal_cb,
+ .hook_api_event_handler_add = hook_api_event_handler_add_cb,
+ .hook_api_event_handler_del = hook_api_event_handler_del_cb,
+ .hook_api_class_provide = hook_api_class_provide_cb,
+ .hook_api_class_require = hook_api_class_require_cb,
+ .hook_api_delete_api = hook_api_delete_api_cb,
+ .hook_api_on_event_handler_before = hook_api_on_event_handler_before_cb,
+ .hook_api_on_event_handler_after = hook_api_on_event_handler_after_cb,
};
/******************************************************************************
* section: hooks for tracing daemon interface (export)
*****************************************************************************/
-#define _HOOK_DITF_(what,...) \
- struct afb_hook_ditf *hook; \
+#define _HOOK_API_2_(flag,func,...) \
+ struct afb_hook_api *hook; \
struct afb_hookid hookid; \
const char *apiname = afb_export_apiname(export); \
pthread_rwlock_rdlock(&rwlock); \
init_hookid(&hookid); \
- hook = list_of_ditf_hooks; \
+ hook = list_of_api_hooks; \
while (hook) { \
- if (hook->itf->hook_ditf_##what \
- && (hook->flags & afb_hook_flag_ditf_##what) != 0 \
- && (!hook->api || !strcasecmp(hook->api, apiname))) { \
- hook->itf->hook_ditf_##what(hook->closure, &hookid, __VA_ARGS__); \
+ if (hook->itf->hook_api_##func \
+ && (hook->flags & afb_hook_flag_api_##flag) != 0 \
+ && MATCH_API(hook->api, apiname)) { \
+ hook->itf->hook_api_##func(hook->closure, &hookid, __VA_ARGS__); \
} \
hook = hook->next; \
} \
pthread_rwlock_unlock(&rwlock);
-void afb_hook_ditf_event_broadcast_before(const struct afb_export *export, const char *name, struct json_object *object)
+#define _HOOK_API_(what,...) _HOOK_API_2_(what,what,__VA_ARGS__)
+
+void afb_hook_api_event_broadcast_before(const struct afb_export *export, const char *name, struct json_object *object)
{
- _HOOK_DITF_(event_broadcast_before, export, name, object);
+ _HOOK_API_2_(event_broadcast, event_broadcast_before, export, name, object);
}
-int afb_hook_ditf_event_broadcast_after(const struct afb_export *export, const char *name, struct json_object *object, int result)
+int afb_hook_api_event_broadcast_after(const struct afb_export *export, const char *name, struct json_object *object, int result)
{
- _HOOK_DITF_(event_broadcast_after, export, name, object, result);
+ _HOOK_API_2_(event_broadcast, event_broadcast_after, export, name, object, result);
return result;
}
-struct sd_event *afb_hook_ditf_get_event_loop(const struct afb_export *export, struct sd_event *result)
+struct sd_event *afb_hook_api_get_event_loop(const struct afb_export *export, struct sd_event *result)
{
- _HOOK_DITF_(get_event_loop, export, result);
+ _HOOK_API_(get_event_loop, export, result);
return result;
}
-struct sd_bus *afb_hook_ditf_get_user_bus(const struct afb_export *export, struct sd_bus *result)
+struct sd_bus *afb_hook_api_get_user_bus(const struct afb_export *export, struct sd_bus *result)
{
- _HOOK_DITF_(get_user_bus, export, result);
+ _HOOK_API_(get_user_bus, export, result);
return result;
}
-struct sd_bus *afb_hook_ditf_get_system_bus(const struct afb_export *export, struct sd_bus *result)
+struct sd_bus *afb_hook_api_get_system_bus(const struct afb_export *export, struct sd_bus *result)
{
- _HOOK_DITF_(get_system_bus, export, result);
+ _HOOK_API_(get_system_bus, export, result);
return result;
}
-void afb_hook_ditf_vverbose(const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
+void afb_hook_api_vverbose(const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
{
- _HOOK_DITF_(vverbose, export, level, file, line, function, fmt, args);
+ _HOOK_API_(vverbose, export, level, file, line, function, fmt, args);
}
-struct afb_eventid *afb_hook_ditf_event_make(const struct afb_export *export, const char *name, struct afb_eventid *result)
+struct afb_event_x2 *afb_hook_api_event_make(const struct afb_export *export, const char *name, struct afb_event_x2 *result)
{
- _HOOK_DITF_(event_make, export, name, result);
+ _HOOK_API_(event_make, export, name, result);
return result;
}
-int afb_hook_ditf_rootdir_get_fd(const struct afb_export *export, int result)
+int afb_hook_api_rootdir_get_fd(const struct afb_export *export, int result)
{
- _HOOK_DITF_(rootdir_get_fd, export, result);
+ _HOOK_API_(rootdir_get_fd, export, result);
return result;
}
-int afb_hook_ditf_rootdir_open_locale(const struct afb_export *export, const char *filename, int flags, const char *locale, int result)
+int afb_hook_api_rootdir_open_locale(const struct afb_export *export, const char *filename, int flags, const char *locale, int result)
{
- _HOOK_DITF_(rootdir_open_locale, export, filename, flags, locale, result);
+ _HOOK_API_(rootdir_open_locale, export, filename, flags, locale, result);
return result;
}
-int afb_hook_ditf_queue_job(const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result)
+int afb_hook_api_queue_job(const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result)
{
- _HOOK_DITF_(queue_job, export, callback, argument, group, timeout, result);
+ _HOOK_API_(queue_job, export, callback, argument, group, timeout, result);
return result;
}
-void afb_hook_ditf_unstore_req(const struct afb_export *export, struct afb_stored_req *sreq)
+void afb_hook_api_legacy_unstore_req(const struct afb_export *export, struct afb_stored_req *sreq)
{
- _HOOK_DITF_(unstore_req, export, sreq);
+ _HOOK_API_(legacy_unstore_req, export, sreq);
}
-void afb_hook_ditf_require_api(const struct afb_export *export, const char *name, int initialized)
+void afb_hook_api_require_api(const struct afb_export *export, const char *name, int initialized)
{
- _HOOK_DITF_(require_api, export, name, initialized);
+ _HOOK_API_(require_api, export, name, initialized);
}
-int afb_hook_ditf_require_api_result(const struct afb_export *export, const char *name, int initialized, int result)
+int afb_hook_api_require_api_result(const struct afb_export *export, const char *name, int initialized, int result)
{
- _HOOK_DITF_(require_api_result, export, name, initialized, result);
+ _HOOK_API_2_(require_api, require_api_result, export, name, initialized, result);
return result;
}
-int afb_hook_ditf_rename_api(const struct afb_export *export, const char *oldname, const char *newname, int result)
+int afb_hook_api_add_alias(const struct afb_export *export, const char *api, const char *alias, int result)
{
- _HOOK_DITF_(rename_api, export, oldname, newname, result);
+ _HOOK_API_(add_alias, export, api, alias, result);
return result;
}
-/******************************************************************************
- * section: hooking export
- *****************************************************************************/
-
-int afb_hook_flags_ditf(const char *api)
+void afb_hook_api_start_before(const struct afb_export *export)
{
- int flags;
- struct afb_hook_ditf *hook;
-
- flags = 0;
- if (!api || afb_api_is_hookable(api)) {
- pthread_rwlock_rdlock(&rwlock);
- hook = list_of_ditf_hooks;
- while (hook) {
- if (!api || !hook->api || !strcasecmp(hook->api, api))
- flags |= hook->flags;
- hook = hook->next;
- }
- pthread_rwlock_unlock(&rwlock);
- }
- return flags;
+ _HOOK_API_2_(start, start_before, export);
}
-struct afb_hook_ditf *afb_hook_create_ditf(const char *api, int flags, struct afb_hook_ditf_itf *itf, void *closure)
+int afb_hook_api_start_after(const struct afb_export *export, int status)
{
- struct afb_hook_ditf *hook;
-
- /* alloc the result */
- hook = calloc(1, sizeof *hook);
- if (hook == NULL)
- return NULL;
-
- /* get a copy of the names */
- hook->api = api ? strdup(api) : NULL;
- if (api && !hook->api) {
- free(hook);
- return NULL;
- }
-
- /* initialise the rest */
- hook->refcount = 1;
- hook->flags = flags;
- hook->itf = itf ? itf : &hook_ditf_default_itf;
- hook->closure = closure;
+ _HOOK_API_2_(start, start_after, export, status);
+ return status;
+}
- /* record the hook */
- pthread_rwlock_wrlock(&rwlock);
- hook->next = list_of_ditf_hooks;
- list_of_ditf_hooks = hook;
- pthread_rwlock_unlock(&rwlock);
+void afb_hook_api_on_event_before(const struct afb_export *export, const char *event, int event_x2, struct json_object *object)
+{
+ _HOOK_API_2_(on_event, on_event_before, export, event, event_x2, object);
+}
- /* returns it */
- return hook;
+void afb_hook_api_on_event_after(const struct afb_export *export, const char *event, int event_x2, struct json_object *object)
+{
+ _HOOK_API_2_(on_event, on_event_after, export, event, event_x2, object);
}
-struct afb_hook_ditf *afb_hook_addref_ditf(struct afb_hook_ditf *hook)
+void afb_hook_api_call(const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
{
- pthread_rwlock_wrlock(&rwlock);
- hook->refcount++;
- pthread_rwlock_unlock(&rwlock);
- return hook;
+ _HOOK_API_(call, export, api, verb, args);
}
-void afb_hook_unref_ditf(struct afb_hook_ditf *hook)
+void afb_hook_api_call_result(const struct afb_export *export, struct json_object *object, const char*error, const char *info)
{
- struct afb_hook_ditf **prv;
+ _HOOK_API_2_(call, call_result, export, object, error, info);
- if (hook) {
- pthread_rwlock_wrlock(&rwlock);
- if (--hook->refcount)
- hook = NULL;
- else {
- /* unlink */
- prv = &list_of_ditf_hooks;
- while (*prv && *prv != hook)
- prv = &(*prv)->next;
- if(*prv)
- *prv = hook->next;
- }
- pthread_rwlock_unlock(&rwlock);
- if (hook) {
- /* free */
- free(hook->api);
- free(hook);
- }
- }
}
-/******************************************************************************
- * section: default callbacks for tracing service interface (export)
- *****************************************************************************/
-
-static void _hook_svc_(const struct afb_export *export, const char *format, ...)
+void afb_hook_api_callsync(const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
{
- va_list ap;
- va_start(ap, format);
- _hook_("export-%s", format, ap, afb_export_apiname(export));
- va_end(ap);
+ _HOOK_API_(callsync, export, api, verb, args);
}
-static void hook_svc_start_before_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export)
+int afb_hook_api_callsync_result(const struct afb_export *export, int status, struct json_object *object, const char *error, const char *info)
{
- _hook_svc_(export, "start.before");
+ _HOOK_API_2_(callsync, callsync_result, export, status, object, error, info);
+ return status;
}
-static void hook_svc_start_after_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status)
+void afb_hook_api_new_api_before(const struct afb_export *export, const char *api, const char *info, int noconcurrency)
{
- _hook_svc_(export, "start.after -> %d", status);
+ _HOOK_API_2_(new_api, new_api_before, export, api, info, noconcurrency);
}
-static void hook_svc_on_event_before_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object)
+int afb_hook_api_new_api_after(const struct afb_export *export, int result, const char *api)
{
- _hook_svc_(export, "on_event.before(%s, %d, %s)", event, eventid, json_object_to_json_string(object));
+ _HOOK_API_2_(new_api, new_api_after, export, result, api);
+ return result;
}
-static void hook_svc_on_event_after_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object)
+int afb_hook_api_api_set_verbs_v2(const struct afb_export *export, int result, const struct afb_verb_v2 *verbs)
{
- _hook_svc_(export, "on_event.after(%s, %d, %s)", event, eventid, json_object_to_json_string(object));
+ _HOOK_API_2_(api_set_verbs, api_set_verbs_v2, export, result, verbs);
+ return result;
}
-static void hook_svc_call_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
+int afb_hook_api_api_set_verbs_v3(const struct afb_export *export, int result, const struct afb_verb_v3 *verbs)
{
- _hook_svc_(export, "call(%s/%s, %s) ...", api, verb, json_object_to_json_string(args));
+ _HOOK_API_2_(api_set_verbs, api_set_verbs_v3, export, result, verbs);
+ return result;
}
-static void hook_svc_call_result_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result)
+int afb_hook_api_api_add_verb(const struct afb_export *export, int result, const char *verb, const char *info, int glob)
{
- _hook_svc_(export, " ...call... -> %d: %s", status, json_object_to_json_string(result));
+ _HOOK_API_(api_add_verb, export, result, verb, info, glob);
+ return result;
}
-static void hook_svc_callsync_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
+int afb_hook_api_api_del_verb(const struct afb_export *export, int result, const char *verb)
{
- _hook_svc_(export, "callsync(%s/%s, %s) ...", api, verb, json_object_to_json_string(args));
+ _HOOK_API_(api_del_verb, export, result, verb);
+ return result;
}
-static void hook_svc_callsync_result_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result)
+int afb_hook_api_api_set_on_event(const struct afb_export *export, int result)
{
- _hook_svc_(export, " ...callsync... -> %d: %s", status, json_object_to_json_string(result));
+ _HOOK_API_(api_set_on_event, export, result);
+ return result;
}
-static struct afb_hook_svc_itf hook_svc_default_itf = {
- .hook_svc_start_before = hook_svc_start_before_default_cb,
- .hook_svc_start_after = hook_svc_start_after_default_cb,
- .hook_svc_on_event_before = hook_svc_on_event_before_default_cb,
- .hook_svc_on_event_after = hook_svc_on_event_after_default_cb,
- .hook_svc_call = hook_svc_call_default_cb,
- .hook_svc_call_result = hook_svc_call_result_default_cb,
- .hook_svc_callsync = hook_svc_callsync_default_cb,
- .hook_svc_callsync_result = hook_svc_callsync_result_default_cb
-};
-
-/******************************************************************************
- * section: hooks for tracing service interface (export)
- *****************************************************************************/
-
-#define _HOOK_SVC_(what,...) \
- struct afb_hook_svc *hook; \
- struct afb_hookid hookid; \
- const char *apiname = afb_export_apiname(export); \
- pthread_rwlock_rdlock(&rwlock); \
- init_hookid(&hookid); \
- hook = list_of_svc_hooks; \
- while (hook) { \
- if (hook->itf->hook_svc_##what \
- && (hook->flags & afb_hook_flag_svc_##what) != 0 \
- && (!hook->api || !strcasecmp(hook->api, apiname))) { \
- hook->itf->hook_svc_##what(hook->closure, &hookid, __VA_ARGS__); \
- } \
- hook = hook->next; \
- } \
- pthread_rwlock_unlock(&rwlock);
-
-void afb_hook_svc_start_before(const struct afb_export *export)
+int afb_hook_api_api_set_on_init(const struct afb_export *export, int result)
{
- _HOOK_SVC_(start_before, export);
+ _HOOK_API_(api_set_on_init, export, result);
+ return result;
}
-int afb_hook_svc_start_after(const struct afb_export *export, int status)
+void afb_hook_api_api_seal(const struct afb_export *export)
{
- _HOOK_SVC_(start_after, export, status);
- return status;
+ _HOOK_API_(api_seal, export);
}
-void afb_hook_svc_on_event_before(const struct afb_export *export, const char *event, int eventid, struct json_object *object)
+int afb_hook_api_event_handler_add(const struct afb_export *export, int result, const char *pattern)
{
- _HOOK_SVC_(on_event_before, export, event, eventid, object);
+ _HOOK_API_(event_handler_add, export, result, pattern);
+ return result;
}
-
-void afb_hook_svc_on_event_after(const struct afb_export *export, const char *event, int eventid, struct json_object *object)
+int afb_hook_api_event_handler_del(const struct afb_export *export, int result, const char *pattern)
{
- _HOOK_SVC_(on_event_after, export, event, eventid, object);
+ _HOOK_API_(event_handler_del, export, result, pattern);
+ return result;
}
-
-void afb_hook_svc_call(const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
+int afb_hook_api_class_provide(const struct afb_export *export, int result, const char *name)
{
- _HOOK_SVC_(call, export, api, verb, args);
+ _HOOK_API_(class_provide, export, result, name);
+ return result;
+}
+int afb_hook_api_class_require(const struct afb_export *export, int result, const char *name)
+{
+ _HOOK_API_(class_require, export, result, name);
+ return result;
}
-void afb_hook_svc_call_result(const struct afb_export *export, int status, struct json_object *result)
+int afb_hook_api_delete_api(const struct afb_export *export, int result)
{
- _HOOK_SVC_(call_result, export, status, result);
+ _HOOK_API_(delete_api, export, result);
+ return result;
}
-void afb_hook_svc_callsync(const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
+void afb_hook_api_on_event_handler_before(const struct afb_export *export, const char *event, int event_x2, struct json_object *object, const char *pattern)
{
- _HOOK_SVC_(callsync, export, api, verb, args);
+ _HOOK_API_2_(on_event_handler, on_event_handler_before, export, event, event_x2, object, pattern);
}
-int afb_hook_svc_callsync_result(const struct afb_export *export, int status, struct json_object *result)
+void afb_hook_api_on_event_handler_after(const struct afb_export *export, const char *event, int event_x2, struct json_object *object, const char *pattern)
{
- _HOOK_SVC_(callsync_result, export, status, result);
- return status;
+ _HOOK_API_2_(on_event_handler, on_event_handler_after, export, event, event_x2, object, pattern);
}
/******************************************************************************
- * section: hooking services (export)
+ * section: hooking export
*****************************************************************************/
-int afb_hook_flags_svc(const char *api)
+int afb_hook_flags_api(const char *api)
{
int flags;
- struct afb_hook_svc *hook;
+ struct afb_hook_api *hook;
flags = 0;
- if (!api || afb_api_is_hookable(api)) {
- pthread_rwlock_rdlock(&rwlock);
- hook = list_of_svc_hooks;
- while (hook) {
- if (!api || !hook->api || !strcasecmp(hook->api, api))
- flags |= hook->flags;
- hook = hook->next;
- }
- pthread_rwlock_unlock(&rwlock);
+ pthread_rwlock_rdlock(&rwlock);
+ hook = list_of_api_hooks;
+ while (hook) {
+ if (!api || MATCH_API(hook->api, api))
+ flags |= hook->flags;
+ hook = hook->next;
}
+ pthread_rwlock_unlock(&rwlock);
return flags;
}
-struct afb_hook_svc *afb_hook_create_svc(const char *api, int flags, struct afb_hook_svc_itf *itf, void *closure)
+struct afb_hook_api *afb_hook_create_api(const char *api, int flags, struct afb_hook_api_itf *itf, void *closure)
{
- struct afb_hook_svc *hook;
+ struct afb_hook_api *hook;
/* alloc the result */
hook = calloc(1, sizeof *hook);
@@ -1186,20 +1220,20 @@ struct afb_hook_svc *afb_hook_create_svc(const char *api, int flags, struct afb_
/* initialise the rest */
hook->refcount = 1;
hook->flags = flags;
- hook->itf = itf ? itf : &hook_svc_default_itf;
+ hook->itf = itf ? itf : &hook_api_default_itf;
hook->closure = closure;
/* record the hook */
pthread_rwlock_wrlock(&rwlock);
- hook->next = list_of_svc_hooks;
- list_of_svc_hooks = hook;
+ hook->next = list_of_api_hooks;
+ list_of_api_hooks = hook;
pthread_rwlock_unlock(&rwlock);
/* returns it */
return hook;
}
-struct afb_hook_svc *afb_hook_addref_svc(struct afb_hook_svc *hook)
+struct afb_hook_api *afb_hook_addref_api(struct afb_hook_api *hook)
{
pthread_rwlock_wrlock(&rwlock);
hook->refcount++;
@@ -1207,9 +1241,9 @@ struct afb_hook_svc *afb_hook_addref_svc(struct afb_hook_svc *hook)
return hook;
}
-void afb_hook_unref_svc(struct afb_hook_svc *hook)
+void afb_hook_unref_api(struct afb_hook_api *hook)
{
- struct afb_hook_svc **prv;
+ struct afb_hook_api **prv;
if (hook) {
pthread_rwlock_wrlock(&rwlock);
@@ -1217,7 +1251,7 @@ void afb_hook_unref_svc(struct afb_hook_svc *hook)
hook = NULL;
else {
/* unlink */
- prv = &list_of_svc_hooks;
+ prv = &list_of_api_hooks;
while (*prv && *prv != hook)
prv = &(*prv)->next;
if(*prv)
@@ -1244,56 +1278,56 @@ static void _hook_evt_(const char *evt, int id, const char *format, ...)
va_end(ap);
}
-static void hook_evt_create_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
+static void hook_evt_create_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
{
_hook_evt_(evt, id, "create");
}
-static void hook_evt_push_before_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj)
+static void hook_evt_push_before_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj)
{
_hook_evt_(evt, id, "push.before(%s)", json_object_to_json_string(obj));
}
-static void hook_evt_push_after_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj, int result)
+static void hook_evt_push_after_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj, int result)
{
_hook_evt_(evt, id, "push.after(%s) -> %d", json_object_to_json_string(obj), result);
}
-static void hook_evt_broadcast_before_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj)
+static void hook_evt_broadcast_before_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj)
{
_hook_evt_(evt, id, "broadcast.before(%s)", json_object_to_json_string(obj));
}
-static void hook_evt_broadcast_after_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj, int result)
+static void hook_evt_broadcast_after_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj, int result)
{
_hook_evt_(evt, id, "broadcast.after(%s) -> %d", json_object_to_json_string(obj), result);
}
-static void hook_evt_name_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, const char *result)
+static void hook_evt_name_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, const char *result)
{
_hook_evt_(evt, id, "name -> %s", result);
}
-static void hook_evt_addref_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
+static void hook_evt_addref_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
{
_hook_evt_(evt, id, "addref");
}
-static void hook_evt_unref_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
+static void hook_evt_unref_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
{
_hook_evt_(evt, id, "unref");
}
static struct afb_hook_evt_itf hook_evt_default_itf = {
- .hook_evt_create = hook_evt_create_default_cb,
- .hook_evt_push_before = hook_evt_push_before_default_cb,
- .hook_evt_push_after = hook_evt_push_after_default_cb,
- .hook_evt_broadcast_before = hook_evt_broadcast_before_default_cb,
- .hook_evt_broadcast_after = hook_evt_broadcast_after_default_cb,
- .hook_evt_name = hook_evt_name_default_cb,
- .hook_evt_addref = hook_evt_addref_default_cb,
- .hook_evt_unref = hook_evt_unref_default_cb
+ .hook_evt_create = hook_evt_create_cb,
+ .hook_evt_push_before = hook_evt_push_before_cb,
+ .hook_evt_push_after = hook_evt_push_after_cb,
+ .hook_evt_broadcast_before = hook_evt_broadcast_before_cb,
+ .hook_evt_broadcast_after = hook_evt_broadcast_after_cb,
+ .hook_evt_name = hook_evt_name_cb,
+ .hook_evt_addref = hook_evt_addref_cb,
+ .hook_evt_unref = hook_evt_unref_cb
};
/******************************************************************************
@@ -1309,7 +1343,7 @@ static struct afb_hook_evt_itf hook_evt_default_itf = {
while (hook) { \
if (hook->itf->hook_evt_##what \
&& (hook->flags & afb_hook_flag_evt_##what) != 0 \
- && (!hook->pattern || MATCH(hook->pattern, evt))) { \
+ && MATCH_EVENT(hook->pattern, evt)) { \
hook->itf->hook_evt_##what(hook->closure, &hookid, __VA_ARGS__); \
} \
hook = hook->next; \
@@ -1368,16 +1402,14 @@ int afb_hook_flags_evt(const char *name)
struct afb_hook_evt *hook;
flags = 0;
- if (!name || afb_api_is_hookable(name)) {
- pthread_rwlock_rdlock(&rwlock);
- hook = list_of_evt_hooks;
- while (hook) {
- if (!name || !hook->pattern || MATCH(hook->pattern, name))
- flags |= hook->flags;
- hook = hook->next;
- }
- pthread_rwlock_unlock(&rwlock);
+ pthread_rwlock_rdlock(&rwlock);
+ hook = list_of_evt_hooks;
+ while (hook) {
+ if (!name || MATCH_EVENT(hook->pattern, name))
+ flags |= hook->flags;
+ hook = hook->next;
}
+ pthread_rwlock_unlock(&rwlock);
return flags;
}
@@ -1458,43 +1490,43 @@ static void _hook_session_(struct afb_session *session, const char *format, ...)
va_end(ap);
}
-static void hook_session_create_default_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+static void hook_session_create_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
{
_hook_session_(session, "create -> token=%s", afb_session_token(session));
}
-static void hook_session_close_default_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+static void hook_session_close_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
{
_hook_session_(session, "close");
}
-static void hook_session_destroy_default_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+static void hook_session_destroy_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
{
_hook_session_(session, "destroy");
}
-static void hook_session_renew_default_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+static void hook_session_renew_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
{
_hook_session_(session, "renew -> token=%s", afb_session_token(session));
}
-static void hook_session_addref_default_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+static void hook_session_addref_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
{
_hook_session_(session, "addref");
}
-static void hook_session_unref_default_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+static void hook_session_unref_cb(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
{
_hook_session_(session, "unref");
}
static struct afb_hook_session_itf hook_session_default_itf = {
- .hook_session_create = hook_session_create_default_cb,
- .hook_session_close = hook_session_close_default_cb,
- .hook_session_destroy = hook_session_destroy_default_cb,
- .hook_session_renew = hook_session_renew_default_cb,
- .hook_session_addref = hook_session_addref_default_cb,
- .hook_session_unref = hook_session_unref_default_cb
+ .hook_session_create = hook_session_create_cb,
+ .hook_session_close = hook_session_close_cb,
+ .hook_session_destroy = hook_session_destroy_cb,
+ .hook_session_renew = hook_session_renew_cb,
+ .hook_session_addref = hook_session_addref_cb,
+ .hook_session_unref = hook_session_unref_cb
};
/******************************************************************************
@@ -1511,7 +1543,7 @@ static struct afb_hook_session_itf hook_session_default_itf = {
while (hook) { \
if (hook->itf->hook_session_##what \
&& (hook->flags & afb_hook_flag_session_##what) != 0 \
- && (!hook->pattern || MATCH(hook->pattern, (sessid?:(sessid=afb_session_uuid(session)))))) { \
+ && MATCH_SESSION(hook->pattern, (sessid?:(sessid=afb_session_uuid(session))))) { \
hook->itf->hook_session_##what(hook->closure, &hookid, __VA_ARGS__); \
} \
hook = hook->next; \
@@ -1630,7 +1662,7 @@ static void _hook_global_(const char *format, ...)
va_end(ap);
}
-static void hook_global_vverbose_default_cb(void *closure, const struct afb_hookid *hookid, int level, const char *file, int line, const char *func, const char *fmt, va_list args)
+static void hook_global_vverbose_cb(void *closure, const struct afb_hookid *hookid, int level, const char *file, int line, const char *func, const char *fmt, va_list args)
{
int len;
char *msg;
@@ -1641,15 +1673,15 @@ static void hook_global_vverbose_default_cb(void *closure, const struct afb_hook
va_end(ap);
if (len < 0)
- _hook_global_("vverbose(%d, %s, %d, %s) -> %s ? ? ?", level, file, line, func, fmt);
+ _hook_global_("vverbose(%d:%s, %s, %d, %s) -> %s ? ? ?", level, verbose_name_of_level(level), file, line, func, fmt);
else {
- _hook_global_("vverbose(%d, %s, %d, %s) -> %s", level, file, line, func, msg);
+ _hook_global_("vverbose(%d:%s, %s, %d, %s) -> %s", level, verbose_name_of_level(level), file, line, func, msg);
free(msg);
}
}
static struct afb_hook_global_itf hook_global_default_itf = {
- .hook_global_vverbose = hook_global_vverbose_default_cb
+ .hook_global_vverbose = hook_global_vverbose_cb
};
/******************************************************************************
diff --git a/src/afb-hook.h b/src/afb-hook.h
index 52d83355..f315cc08 100644
--- a/src/afb-hook.h
+++ b/src/afb-hook.h
@@ -24,7 +24,9 @@ struct req;
struct afb_context;
struct json_object;
struct afb_arg;
-struct afb_eventid;
+struct afb_event_x2;
+struct afb_verb_v2;
+struct afb_verb_v3;
struct afb_session;
struct afb_xreq;
struct afb_export;
@@ -32,8 +34,7 @@ struct afb_stored_req;
struct sd_bus;
struct sd_event;
struct afb_hook_xreq;
-struct afb_hook_ditf;
-struct afb_hook_svc;
+struct afb_hook_api;
struct afb_hook_evt;
struct afb_hook_session;
struct afb_hook_global;
@@ -56,10 +57,10 @@ struct afb_hookid
#define afb_hook_flag_req_end 0x00000002
#define afb_hook_flag_req_json 0x00000004
#define afb_hook_flag_req_get 0x00000008
-#define afb_hook_flag_req_success 0x00000010
-#define afb_hook_flag_req_fail 0x00000020
-#define afb_hook_flag_req_context_get 0x00000040
-#define afb_hook_flag_req_context_set 0x00000080
+#define afb_hook_flag_req_reply 0x00000010
+#define afb_hook_flag_req_get_client_info 0x00000020
+#define afb_hook_flag_req_legacy_context_get 0x00000040
+#define afb_hook_flag_req_legacy_context_set 0x00000080
#define afb_hook_flag_req_addref 0x00000100
#define afb_hook_flag_req_unref 0x00000200
#define afb_hook_flag_req_session_close 0x00000400
@@ -71,35 +72,31 @@ struct afb_hookid
#define afb_hook_flag_req_subcallsync 0x00010000
#define afb_hook_flag_req_subcallsync_result 0x00020000
#define afb_hook_flag_req_vverbose 0x00040000
-#define afb_hook_flag_req_store 0x00080000
-#define afb_hook_flag_req_unstore 0x00100000
-#define afb_hook_flag_req_subcall_req 0x00200000
-#define afb_hook_flag_req_subcall_req_result 0x00400000
-#define afb_hook_flag_req_has_permission 0x00800000
-#define afb_hook_flag_req_get_application_id 0x01000000
-#define afb_hook_flag_req_context_make 0x02000000
-#define afb_hook_flag_req_get_uid 0x04000000
+#define afb_hook_flag_req_legacy_store 0x00080000
+#define afb_hook_flag_req_legacy_unstore 0x00100000
+#define afb_hook_flag_req_has_permission 0x00200000
+#define afb_hook_flag_req_get_application_id 0x00400000
+#define afb_hook_flag_req_context_make 0x00800000
+#define afb_hook_flag_req_get_uid 0x01000000
/* common flags */
#define afb_hook_flags_req_life (afb_hook_flag_req_begin|afb_hook_flag_req_end)
#define afb_hook_flags_req_args (afb_hook_flag_req_json|afb_hook_flag_req_get)
-#define afb_hook_flags_req_result (afb_hook_flag_req_success|afb_hook_flag_req_fail)
#define afb_hook_flags_req_session (afb_hook_flag_req_session_close|afb_hook_flag_req_session_set_LOA)
#define afb_hook_flags_req_event (afb_hook_flag_req_subscribe|afb_hook_flag_req_unsubscribe)
#define afb_hook_flags_req_subcalls (afb_hook_flag_req_subcall|afb_hook_flag_req_subcall_result\
- |afb_hook_flag_req_subcall_req|afb_hook_flag_req_subcall_req_result\
|afb_hook_flag_req_subcallsync|afb_hook_flag_req_subcallsync_result)
#define afb_hook_flags_req_security (afb_hook_flag_req_has_permission|afb_hook_flag_req_get_application_id\
- |afb_hook_flag_req_get_uid)
+ |afb_hook_flag_req_get_uid|afb_hook_flag_req_get_client_info)
/* extra flags */
#define afb_hook_flags_req_ref (afb_hook_flag_req_addref|afb_hook_flag_req_unref)
-#define afb_hook_flags_req_context (afb_hook_flag_req_context_get|afb_hook_flag_req_context_set\
+#define afb_hook_flags_req_context (afb_hook_flag_req_legacy_context_get|afb_hook_flag_req_legacy_context_set\
|afb_hook_flag_req_context_make)
-#define afb_hook_flags_req_stores (afb_hook_flag_req_store|afb_hook_flag_req_unstore)
+#define afb_hook_flags_req_stores (afb_hook_flag_req_legacy_store|afb_hook_flag_req_legacy_unstore)
/* predefined groups */
-#define afb_hook_flags_req_common (afb_hook_flags_req_life|afb_hook_flags_req_args|afb_hook_flags_req_result\
+#define afb_hook_flags_req_common (afb_hook_flags_req_life|afb_hook_flags_req_args|afb_hook_flag_req_reply\
|afb_hook_flags_req_session|afb_hook_flags_req_event|afb_hook_flags_req_subcalls\
|afb_hook_flag_req_vverbose|afb_hook_flags_req_security)
#define afb_hook_flags_req_extra (afb_hook_flags_req_common|afb_hook_flags_req_ref|afb_hook_flags_req_context\
@@ -111,29 +108,27 @@ struct afb_hook_xreq_itf {
void (*hook_xreq_end)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq);
void (*hook_xreq_json)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *obj);
void (*hook_xreq_get)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *name, struct afb_arg arg);
- void (*hook_xreq_success)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *obj, const char *info);
- void (*hook_xreq_fail)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *status, const char *info);
- void (*hook_xreq_context_get)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, void *value);
- void (*hook_xreq_context_set)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, void *value, void (*free_value)(void*));
+ void (*hook_xreq_reply)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info);
+ void (*hook_xreq_legacy_context_get)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, void *value);
+ void (*hook_xreq_legacy_context_set)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, void *value, void (*free_value)(void*));
void (*hook_xreq_addref)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq);
void (*hook_xreq_unref)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq);
void (*hook_xreq_session_close)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq);
void (*hook_xreq_session_set_LOA)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, unsigned level, int result);
- void (*hook_xreq_subscribe)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_eventid *eventid, int result);
- void (*hook_xreq_unsubscribe)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_eventid *eventid, int result);
+ void (*hook_xreq_subscribe)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_event_x2 *event_x2, int result);
+ void (*hook_xreq_unsubscribe)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_event_x2 *event_x2, int result);
void (*hook_xreq_subcall)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args);
- void (*hook_xreq_subcall_result)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result);
+ void (*hook_xreq_subcall_result)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info);
void (*hook_xreq_subcallsync)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args);
- void (*hook_xreq_subcallsync_result)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result);
+ void (*hook_xreq_subcallsync_result)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *object, const char *error, const char *info);
void (*hook_xreq_vverbose)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int level, const char *file, int line, const char *func, const char *fmt, va_list args);
- void (*hook_xreq_store)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_stored_req *sreq);
- void (*hook_xreq_unstore)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq);
- void (*hook_xreq_subcall_req)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args);
- void (*hook_xreq_subcall_req_result)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result);
+ void (*hook_xreq_legacy_store)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_stored_req *sreq);
+ void (*hook_xreq_legacy_unstore)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq);
void (*hook_xreq_has_permission)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *permission, int result);
void (*hook_xreq_get_application_id)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, char *result);
void (*hook_xreq_context_make)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure, void *result);
void (*hook_xreq_get_uid)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int result);
+ void (*hook_xreq_get_client_info)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *result);
};
extern void afb_hook_init_xreq(struct afb_xreq *xreq);
@@ -147,145 +142,220 @@ extern void afb_hook_xreq_begin(const struct afb_xreq *xreq);
extern void afb_hook_xreq_end(const struct afb_xreq *xreq);
extern struct json_object *afb_hook_xreq_json(const struct afb_xreq *xreq, struct json_object *obj);
extern struct afb_arg afb_hook_xreq_get(const struct afb_xreq *xreq, const char *name, struct afb_arg arg);
-extern void afb_hook_xreq_success(const struct afb_xreq *xreq, struct json_object *obj, const char *info);
-extern void afb_hook_xreq_fail(const struct afb_xreq *xreq, const char *status, const char *info);
-extern void *afb_hook_xreq_context_get(const struct afb_xreq *xreq, void *value);
-extern void afb_hook_xreq_context_set(const struct afb_xreq *xreq, void *value, void (*free_value)(void*));
+extern void afb_hook_xreq_reply(const struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info);
+extern void *afb_hook_xreq_legacy_context_get(const struct afb_xreq *xreq, void *value);
+extern void afb_hook_xreq_legacy_context_set(const struct afb_xreq *xreq, void *value, void (*free_value)(void*));
extern void afb_hook_xreq_addref(const struct afb_xreq *xreq);
extern void afb_hook_xreq_unref(const struct afb_xreq *xreq);
extern void afb_hook_xreq_session_close(const struct afb_xreq *xreq);
extern int afb_hook_xreq_session_set_LOA(const struct afb_xreq *xreq, unsigned level, int result);
-extern int afb_hook_xreq_subscribe(const struct afb_xreq *xreq, struct afb_eventid *eventid, int result);
-extern int afb_hook_xreq_unsubscribe(const struct afb_xreq *xreq, struct afb_eventid *eventid, int result);
-extern void afb_hook_xreq_subcall(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args);
-extern void afb_hook_xreq_subcall_result(const struct afb_xreq *xreq, int status, struct json_object *result);
-extern void afb_hook_xreq_subcallsync(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args);
-extern int afb_hook_xreq_subcallsync_result(const struct afb_xreq *xreq, int status, struct json_object *result);
+extern int afb_hook_xreq_subscribe(const struct afb_xreq *xreq, struct afb_event_x2 *event_x2, int result);
+extern int afb_hook_xreq_unsubscribe(const struct afb_xreq *xreq, struct afb_event_x2 *event_x2, int result);
+extern void afb_hook_xreq_subcall(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, int flags);
+extern void afb_hook_xreq_subcall_result(const struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info);
+extern void afb_hook_xreq_subcallsync(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, int flags);
+extern int afb_hook_xreq_subcallsync_result(const struct afb_xreq *xreq, int status, struct json_object *object, const char *error, const char *info);
extern void afb_hook_xreq_vverbose(const struct afb_xreq *xreq, int level, const char *file, int line, const char *func, const char *fmt, va_list args);
-extern void afb_hook_xreq_store(const struct afb_xreq *xreq, struct afb_stored_req *sreq);
-extern void afb_hook_xreq_unstore(const struct afb_xreq *xreq);
-extern void afb_hook_xreq_subcall_req(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args);
-extern void afb_hook_xreq_subcall_req_result(const struct afb_xreq *xreq, int status, struct json_object *result);
+extern void afb_hook_xreq_legacy_store(const struct afb_xreq *xreq, struct afb_stored_req *sreq);
+extern void afb_hook_xreq_legacy_unstore(const struct afb_xreq *xreq);
extern int afb_hook_xreq_has_permission(const struct afb_xreq *xreq, const char *permission, int result);
extern char *afb_hook_xreq_get_application_id(const struct afb_xreq *xreq, char *result);
extern void *afb_hook_xreq_context_make(const struct afb_xreq *xreq, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure, void *result);
extern int afb_hook_xreq_get_uid(const struct afb_xreq *xreq, int result);
+extern struct json_object *afb_hook_xreq_get_client_info(const struct afb_xreq *xreq, struct json_object *result);
/*********************************************************
-* section hooking export (daemon interface)
+* section hooking apis
*********************************************************/
-#define afb_hook_flag_ditf_vverbose 0x000001
-#define afb_hook_flag_ditf_event_make 0x000002
-#define afb_hook_flag_ditf_event_broadcast_before 0x000004
-#define afb_hook_flag_ditf_event_broadcast_after 0x000008
-#define afb_hook_flag_ditf_get_event_loop 0x000010
-#define afb_hook_flag_ditf_get_user_bus 0x000020
-#define afb_hook_flag_ditf_get_system_bus 0x000040
-#define afb_hook_flag_ditf_rootdir_get_fd 0x000080
-#define afb_hook_flag_ditf_rootdir_open_locale 0x000100
-#define afb_hook_flag_ditf_queue_job 0x000200
-#define afb_hook_flag_ditf_unstore_req 0x000400
-#define afb_hook_flag_ditf_require_api 0x000800
-#define afb_hook_flag_ditf_require_api_result 0x001000
-#define afb_hook_flag_ditf_rename_api 0x002000
-
-#define afb_hook_flags_ditf_common (afb_hook_flag_ditf_vverbose\
- |afb_hook_flag_ditf_event_make\
- |afb_hook_flag_ditf_event_broadcast_before\
- |afb_hook_flag_ditf_event_broadcast_after\
- |afb_hook_flag_ditf_rename_api)
-#define afb_hook_flags_ditf_extra (afb_hook_flag_ditf_get_event_loop\
- |afb_hook_flag_ditf_get_user_bus\
- |afb_hook_flag_ditf_get_system_bus\
- |afb_hook_flag_ditf_rootdir_get_fd\
- |afb_hook_flag_ditf_rootdir_open_locale\
- |afb_hook_flag_ditf_queue_job\
- |afb_hook_flag_ditf_unstore_req\
- |afb_hook_flag_ditf_require_api\
- |afb_hook_flag_ditf_require_api_result)
-
-#define afb_hook_flags_ditf_all (afb_hook_flags_ditf_common|afb_hook_flags_ditf_extra)
-
-struct afb_hook_ditf_itf {
- void (*hook_ditf_event_broadcast_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object);
- void (*hook_ditf_event_broadcast_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object, int result);
- void (*hook_ditf_get_event_loop)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_event *result);
- void (*hook_ditf_get_user_bus)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result);
- void (*hook_ditf_get_system_bus)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result);
- void (*hook_ditf_vverbose)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args);
- void (*hook_ditf_event_make)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_eventid *result);
- void (*hook_ditf_rootdir_get_fd)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result);
- void (*hook_ditf_rootdir_open_locale)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *filename, int flags, const char *locale, int result);
- void (*hook_ditf_queue_job)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result);
- void (*hook_ditf_unstore_req)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct afb_stored_req *sreq);
- void (*hook_ditf_require_api)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized);
- void (*hook_ditf_require_api_result)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized, int result);
- void (*hook_ditf_rename_api)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *oldname, const char *newname, int result);
-};
+#define afb_hook_flag_api_vverbose 0x00000001
+#define afb_hook_flag_api_get_event_loop 0x00000002
+#define afb_hook_flag_api_get_user_bus 0x00000004
+#define afb_hook_flag_api_get_system_bus 0x00000008
+#define afb_hook_flag_api_rootdir_get_fd 0x00000010
+#define afb_hook_flag_api_rootdir_open_locale 0x00000020
+#define afb_hook_flag_api_queue_job 0x00000040
+#define afb_hook_flag_api_require_api 0x00000080
+#define afb_hook_flag_api_add_alias 0x00000100
+#define afb_hook_flag_api_event_broadcast 0x00000200
+#define afb_hook_flag_api_event_make 0x00000400
+#define afb_hook_flag_api_new_api 0x00000800
+#define afb_hook_flag_api_api_set_verbs 0x00001000
+#define afb_hook_flag_api_api_add_verb 0x00002000
+#define afb_hook_flag_api_api_del_verb 0x00004000
+#define afb_hook_flag_api_api_set_on_event 0x00008000
+#define afb_hook_flag_api_api_set_on_init 0x00010000
+#define afb_hook_flag_api_api_seal 0x00020000
+#define afb_hook_flag_api_event_handler_add 0x00040000
+#define afb_hook_flag_api_event_handler_del 0x00080000
+#define afb_hook_flag_api_call 0x00100000
+#define afb_hook_flag_api_callsync 0x00200000
+#define afb_hook_flag_api_class_provide 0x00400000
+#define afb_hook_flag_api_class_require 0x00800000
+#define afb_hook_flag_api_delete_api 0x01000000
+#define afb_hook_flag_api_start 0x02000000
+#define afb_hook_flag_api_on_event 0x04000000
+#define afb_hook_flag_api_legacy_unstore_req 0x08000000
+#define afb_hook_flag_api_on_event_handler 0x10000000
+
+/* common flags */
+/* extra flags */
+/* predefined groups */
-extern void afb_hook_ditf_event_broadcast_before(const struct afb_export *export, const char *name, struct json_object *object);
-extern int afb_hook_ditf_event_broadcast_after(const struct afb_export *export, const char *name, struct json_object *object, int result);
-extern struct sd_event *afb_hook_ditf_get_event_loop(const struct afb_export *export, struct sd_event *result);
-extern struct sd_bus *afb_hook_ditf_get_user_bus(const struct afb_export *export, struct sd_bus *result);
-extern struct sd_bus *afb_hook_ditf_get_system_bus(const struct afb_export *export, struct sd_bus *result);
-extern void afb_hook_ditf_vverbose(const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args);
-extern struct afb_eventid *afb_hook_ditf_event_make(const struct afb_export *export, const char *name, struct afb_eventid *result);
-extern int afb_hook_ditf_rootdir_get_fd(const struct afb_export *export, int result);
-extern int afb_hook_ditf_rootdir_open_locale(const struct afb_export *export, const char *filename, int flags, const char *locale, int result);
-extern int afb_hook_ditf_queue_job(const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result);
-extern void afb_hook_ditf_unstore_req(const struct afb_export *export, struct afb_stored_req *sreq);
-extern void afb_hook_ditf_require_api(const struct afb_export *export, const char *name, int initialized);
-extern int afb_hook_ditf_require_api_result(const struct afb_export *export, const char *name, int initialized, int result);
-extern int afb_hook_ditf_rename_api(const struct afb_export *export, const char *oldname, const char *newname, int result);
-
-extern int afb_hook_flags_ditf(const char *api);
-extern struct afb_hook_ditf *afb_hook_create_ditf(const char *api, int flags, struct afb_hook_ditf_itf *itf, void *closure);
-extern struct afb_hook_ditf *afb_hook_addref_ditf(struct afb_hook_ditf *hook);
-extern void afb_hook_unref_ditf(struct afb_hook_ditf *hook);
+#define afb_hook_flags_api_common (afb_hook_flag_api_vverbose\
+ |afb_hook_flag_api_event_broadcast\
+ |afb_hook_flag_api_event_make\
+ |afb_hook_flag_api_call\
+ |afb_hook_flag_api_callsync\
+ |afb_hook_flag_api_start\
+ |afb_hook_flag_api_queue_job)
+
+
+#define afb_hook_flags_api_extra (afb_hook_flag_api_get_event_loop\
+ |afb_hook_flag_api_get_user_bus\
+ |afb_hook_flag_api_get_system_bus\
+ |afb_hook_flag_api_rootdir_get_fd\
+ |afb_hook_flag_api_rootdir_open_locale\
+ |afb_hook_flag_api_legacy_unstore_req)
+
+
+#define afb_hook_flags_api_api (afb_hook_flag_api_new_api\
+ |afb_hook_flag_api_api_set_verbs\
+ |afb_hook_flag_api_api_add_verb\
+ |afb_hook_flag_api_api_del_verb\
+ |afb_hook_flag_api_api_set_on_event\
+ |afb_hook_flag_api_api_set_on_init\
+ |afb_hook_flag_api_api_seal\
+ |afb_hook_flag_api_class_provide\
+ |afb_hook_flag_api_class_require\
+ |afb_hook_flag_api_require_api\
+ |afb_hook_flag_api_add_alias\
+ |afb_hook_flag_api_delete_api)
+
+#define afb_hook_flags_api_event (afb_hook_flag_api_event_broadcast\
+ |afb_hook_flag_api_event_make\
+ |afb_hook_flag_api_event_handler_add\
+ |afb_hook_flag_api_event_handler_del\
+ |afb_hook_flag_api_on_event\
+ |afb_hook_flag_api_on_event_handler)
+
+#define afb_hook_flags_api_all (afb_hook_flags_api_common\
+ |afb_hook_flags_api_extra\
+ |afb_hook_flags_api_api\
+ |afb_hook_flags_api_event)
/*********************************************************
-* section hooking export (service interface)
+*********************************************************/
+#define afb_hook_flags_api_svc_all (afb_hook_flag_api_start|afb_hook_flag_api_start\
+ |afb_hook_flag_api_on_event|afb_hook_flag_api_on_event\
+ |afb_hook_flag_api_call|afb_hook_flag_api_call\
+ |afb_hook_flag_api_callsync|afb_hook_flag_api_callsync)
+
+#define afb_hook_flags_api_ditf_common (afb_hook_flag_api_vverbose\
+ |afb_hook_flag_api_event_make\
+ |afb_hook_flag_api_event_broadcast\
+ |afb_hook_flag_api_event_broadcast\
+ |afb_hook_flag_api_add_alias)
+
+#define afb_hook_flags_api_ditf_extra (afb_hook_flag_api_get_event_loop\
+ |afb_hook_flag_api_get_user_bus\
+ |afb_hook_flag_api_get_system_bus\
+ |afb_hook_flag_api_rootdir_get_fd\
+ |afb_hook_flag_api_rootdir_open_locale\
+ |afb_hook_flag_api_queue_job\
+ |afb_hook_flag_api_legacy_unstore_req\
+ |afb_hook_flag_api_require_api\
+ |afb_hook_flag_api_require_api)
+
+#define afb_hook_flags_api_ditf_all (afb_hook_flags_api_ditf_common|afb_hook_flags_api_ditf_extra)
+/*********************************************************
*********************************************************/
-#define afb_hook_flag_svc_start_before 0x000001
-#define afb_hook_flag_svc_start_after 0x000002
-#define afb_hook_flag_svc_on_event_before 0x000004
-#define afb_hook_flag_svc_on_event_after 0x000008
-#define afb_hook_flag_svc_call 0x000010
-#define afb_hook_flag_svc_call_result 0x000020
-#define afb_hook_flag_svc_callsync 0x000040
-#define afb_hook_flag_svc_callsync_result 0x000080
-
-#define afb_hook_flags_svc_all (afb_hook_flag_svc_start_before|afb_hook_flag_svc_start_after\
- |afb_hook_flag_svc_on_event_before|afb_hook_flag_svc_on_event_after\
- |afb_hook_flag_svc_call|afb_hook_flag_svc_call_result\
- |afb_hook_flag_svc_callsync|afb_hook_flag_svc_callsync_result)
-
-struct afb_hook_svc_itf {
- void (*hook_svc_start_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export);
- void (*hook_svc_start_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status);
- void (*hook_svc_on_event_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object);
- void (*hook_svc_on_event_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int eventid, struct json_object *object);
- void (*hook_svc_call)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args);
- void (*hook_svc_call_result)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result);
- void (*hook_svc_callsync)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args);
- void (*hook_svc_callsync_result)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result);
-};
-extern void afb_hook_svc_start_before(const struct afb_export *export);
-extern int afb_hook_svc_start_after(const struct afb_export *export, int status);
-extern void afb_hook_svc_on_event_before(const struct afb_export *export, const char *event, int eventid, struct json_object *object);
-extern void afb_hook_svc_on_event_after(const struct afb_export *export, const char *event, int eventid, struct json_object *object);
-extern void afb_hook_svc_call(const struct afb_export *export, const char *api, const char *verb, struct json_object *args);
-extern void afb_hook_svc_call_result(const struct afb_export *export, int status, struct json_object *result);
-extern void afb_hook_svc_callsync(const struct afb_export *export, const char *api, const char *verb, struct json_object *args);
-extern int afb_hook_svc_callsync_result(const struct afb_export *export, int status, struct json_object *result);
+struct afb_hook_api_itf {
+ void (*hook_api_event_broadcast_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object);
+ void (*hook_api_event_broadcast_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object, int result);
+ void (*hook_api_get_event_loop)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_event *result);
+ void (*hook_api_get_user_bus)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result);
+ void (*hook_api_get_system_bus)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result);
+ void (*hook_api_vverbose)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args);
+ void (*hook_api_event_make)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_event_x2 *result);
+ void (*hook_api_rootdir_get_fd)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result);
+ void (*hook_api_rootdir_open_locale)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *filename, int flags, const char *locale, int result);
+ void (*hook_api_queue_job)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result);
+ void (*hook_api_legacy_unstore_req)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct afb_stored_req *sreq);
+ void (*hook_api_require_api)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized);
+ void (*hook_api_require_api_result)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized, int result);
+ void (*hook_api_add_alias)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *oldname, const char *newname, int result);
+ void (*hook_api_start_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export);
+ void (*hook_api_start_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status);
+ void (*hook_api_on_event_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int event_x2, struct json_object *object);
+ void (*hook_api_on_event_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int event_x2, struct json_object *object);
+ void (*hook_api_call)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args);
+ void (*hook_api_call_result)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct json_object *object, const char *error, const char *info);
+ void (*hook_api_callsync)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args);
+ void (*hook_api_callsync_result)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, struct json_object *object, const char *error, const char *info);
+ void (*hook_api_new_api_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *info, int noconcurrency);
+ void (*hook_api_new_api_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *api);
+ void (*hook_api_api_set_verbs_v2)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const struct afb_verb_v2 *verbs);
+ void (*hook_api_api_set_verbs_v3)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const struct afb_verb_v3 *verbs);
+ void (*hook_api_api_add_verb)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *verb, const char *info, int glob);
+ void (*hook_api_api_del_verb)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *verb);
+ void (*hook_api_api_set_on_event)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result);
+ void (*hook_api_api_set_on_init)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result);
+ void (*hook_api_api_seal)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export);
+ void (*hook_api_event_handler_add)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *pattern);
+ void (*hook_api_event_handler_del)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *pattern);
+ void (*hook_api_class_provide)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *name);
+ void (*hook_api_class_require)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *name);
+ void (*hook_api_delete_api)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result);
+ void (*hook_api_on_event_handler_before)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int event_x2, struct json_object *object, const char *pattern);
+ void (*hook_api_on_event_handler_after)(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int event_x2, struct json_object *object, const char *pattern);
+};
-extern int afb_hook_flags_svc(const char *api);
-extern struct afb_hook_svc *afb_hook_create_svc(const char *api, int flags, struct afb_hook_svc_itf *itf, void *closure);
-extern struct afb_hook_svc *afb_hook_addref_svc(struct afb_hook_svc *hook);
-extern void afb_hook_unref_svc(struct afb_hook_svc *hook);
+extern void afb_hook_api_event_broadcast_before(const struct afb_export *export, const char *name, struct json_object *object);
+extern int afb_hook_api_event_broadcast_after(const struct afb_export *export, const char *name, struct json_object *object, int result);
+extern struct sd_event *afb_hook_api_get_event_loop(const struct afb_export *export, struct sd_event *result);
+extern struct sd_bus *afb_hook_api_get_user_bus(const struct afb_export *export, struct sd_bus *result);
+extern struct sd_bus *afb_hook_api_get_system_bus(const struct afb_export *export, struct sd_bus *result);
+extern void afb_hook_api_vverbose(const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args);
+extern struct afb_event_x2 *afb_hook_api_event_make(const struct afb_export *export, const char *name, struct afb_event_x2 *result);
+extern int afb_hook_api_rootdir_get_fd(const struct afb_export *export, int result);
+extern int afb_hook_api_rootdir_open_locale(const struct afb_export *export, const char *filename, int flags, const char *locale, int result);
+extern int afb_hook_api_queue_job(const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result);
+extern void afb_hook_api_legacy_unstore_req(const struct afb_export *export, struct afb_stored_req *sreq);
+extern void afb_hook_api_require_api(const struct afb_export *export, const char *name, int initialized);
+extern int afb_hook_api_require_api_result(const struct afb_export *export, const char *name, int initialized, int result);
+extern int afb_hook_api_add_alias(const struct afb_export *export, const char *api, const char *alias, int result);
+extern void afb_hook_api_start_before(const struct afb_export *export);
+extern int afb_hook_api_start_after(const struct afb_export *export, int status);
+extern void afb_hook_api_on_event_before(const struct afb_export *export, const char *event, int event_x2, struct json_object *object);
+extern void afb_hook_api_on_event_after(const struct afb_export *export, const char *event, int event_x2, struct json_object *object);
+extern void afb_hook_api_call(const struct afb_export *export, const char *api, const char *verb, struct json_object *args);
+extern void afb_hook_api_call_result(const struct afb_export *export, struct json_object *object, const char *error, const char *info);
+extern void afb_hook_api_callsync(const struct afb_export *export, const char *api, const char *verb, struct json_object *args);
+extern int afb_hook_api_callsync_result(const struct afb_export *export, int result, struct json_object *object, const char *error, const char *info);
+extern void afb_hook_api_new_api_before(const struct afb_export *export, const char *api, const char *info, int noconcurrency);
+extern int afb_hook_api_new_api_after(const struct afb_export *export, int result, const char *api);
+extern int afb_hook_api_api_set_verbs_v2(const struct afb_export *export, int result, const struct afb_verb_v2 *verbs);
+extern int afb_hook_api_api_set_verbs_v3(const struct afb_export *export, int result, const struct afb_verb_v3 *verbs);
+extern int afb_hook_api_api_add_verb(const struct afb_export *export, int result, const char *verb, const char *info, int glob);
+extern int afb_hook_api_api_del_verb(const struct afb_export *export, int result, const char *verb);
+extern int afb_hook_api_api_set_on_event(const struct afb_export *export, int result);
+extern int afb_hook_api_api_set_on_init(const struct afb_export *export, int result);
+extern void afb_hook_api_api_seal(const struct afb_export *export);
+extern int afb_hook_api_event_handler_add(const struct afb_export *export, int result, const char *pattern);
+extern int afb_hook_api_event_handler_del(const struct afb_export *export, int result, const char *pattern);
+extern int afb_hook_api_class_provide(const struct afb_export *export, int result, const char *name);
+extern int afb_hook_api_class_require(const struct afb_export *export, int result, const char *name);
+extern int afb_hook_api_delete_api(const struct afb_export *export, int result);
+extern void afb_hook_api_on_event_handler_before(const struct afb_export *export, const char *event, int event_x2, struct json_object *object, const char *pattern);
+extern void afb_hook_api_on_event_handler_after(const struct afb_export *export, const char *event, int event_x2, struct json_object *object, const char *pattern);
+
+extern int afb_hook_flags_api(const char *api);
+extern struct afb_hook_api *afb_hook_create_api(const char *api, int flags, struct afb_hook_api_itf *itf, void *closure);
+extern struct afb_hook_api *afb_hook_addref_api(struct afb_hook_api *hook);
+extern void afb_hook_unref_api(struct afb_hook_api *hook);
/*********************************************************
* section hooking evt (event interface)
@@ -384,3 +454,4 @@ extern struct afb_hook_global *afb_hook_create_global(int flags, struct afb_hook
extern struct afb_hook_global *afb_hook_addref_global(struct afb_hook_global *hook);
extern void afb_hook_unref_global(struct afb_hook_global *hook);
+
diff --git a/src/afb-hreq.c b/src/afb-hreq.c
index 012debbd..e5dcf642 100644
--- a/src/afb-hreq.c
+++ b/src/afb-hreq.c
@@ -73,15 +73,13 @@ struct hreq_data {
static struct json_object *req_json(struct afb_xreq *xreq);
static struct afb_arg req_get(struct afb_xreq *xreq, const char *name);
-static void req_fail(struct afb_xreq *xreq, const char *status, const char *info);
-static void req_success(struct afb_xreq *xreq, json_object *obj, const char *info);
+static void req_reply(struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info);
static void req_destroy(struct afb_xreq *xreq);
const struct afb_xreq_query_itf afb_hreq_xreq_query_itf = {
.json = req_json,
.get = req_get,
- .success = req_success,
- .fail = req_fail,
+ .reply = req_reply,
.unref = req_destroy
};
@@ -332,8 +330,8 @@ static void req_destroy(struct afb_xreq *xreq)
}
afb_context_disconnect(&hreq->xreq.context);
json_object_put(hreq->json);
- free((char*)hreq->xreq.request.api);
- free((char*)hreq->xreq.request.verb);
+ free((char*)hreq->xreq.request.called_api);
+ free((char*)hreq->xreq.request.called_verb);
afb_cred_unref(hreq->xreq.cred);
free(hreq);
}
@@ -900,39 +898,32 @@ static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t ma
return len ? : (ssize_t)MHD_CONTENT_READER_END_OF_STREAM;
}
-static void req_reply(struct afb_hreq *hreq, unsigned retcode, const char *status, const char *info, json_object *resp)
+static void req_reply(struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info)
{
- struct json_object *reply;
+ struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq);
+ struct json_object *sub, *reply;
const char *reqid;
struct MHD_Response *response;
+ /* create the reply */
+ reply = afb_msg_json_reply(object, error, info, &xreq->context);
+
+ /* append the req id on need */
reqid = afb_hreq_get_argument(hreq, long_key_for_reqid);
if (reqid == NULL)
reqid = afb_hreq_get_argument(hreq, short_key_for_reqid);
-
- reply = afb_msg_json_reply(status, info, resp, &hreq->xreq.context, reqid);
+ if (reqid != NULL && json_object_object_get_ex(reply, "request", &sub))
+ json_object_object_add(sub, "reqid", json_object_new_string(reqid));
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);
-}
-
-static void req_fail(struct afb_xreq *xreq, const char *status, const char *info)
-{
- struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq);
- req_reply(hreq, MHD_HTTP_OK, status, info, NULL);
-}
-
-static void req_success(struct afb_xreq *xreq, json_object *obj, const char *info)
-{
- struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq);
- req_reply(hreq, MHD_HTTP_OK, "success", info, obj);
+ afb_hreq_reply(hreq, MHD_HTTP_OK, response, NULL);
}
void afb_hreq_call(struct afb_hreq *hreq, struct afb_apiset *apiset, const char *api, size_t lenapi, const char *verb, size_t lenverb)
{
- hreq->xreq.request.api = strndup(api, lenapi);
- hreq->xreq.request.verb = strndup(verb, lenverb);
- if (hreq->xreq.request.api == NULL || hreq->xreq.request.verb == NULL) {
+ hreq->xreq.request.called_api = strndup(api, lenapi);
+ hreq->xreq.request.called_verb = strndup(verb, lenverb);
+ if (hreq->xreq.request.called_api == NULL || hreq->xreq.request.called_verb == NULL) {
ERROR("Out of memory");
afb_hreq_reply_error(hreq, MHD_HTTP_INTERNAL_SERVER_ERROR);
} else if (afb_hreq_init_context(hreq) < 0) {
diff --git a/src/afb-monitor.c b/src/afb-monitor.c
index 18ea606b..a50e2c65 100644
--- a/src/afb-monitor.c
+++ b/src/afb-monitor.c
@@ -21,12 +21,12 @@
#include <json-c/json.h>
-#define AFB_BINDING_VERSION 0
+#define AFB_BINDING_VERSION 3
#include <afb/afb-binding.h>
#include "afb-api.h"
#include "afb-apiset.h"
-#include "afb-api-so-v2.h"
+#include "afb-api-v3.h"
#include "afb-evt.h"
#include "afb-xreq.h"
#include "afb-trace.h"
@@ -36,13 +36,12 @@
#include "monitor-api.inc"
-extern struct afb_apiset *main_apiset;
+static struct afb_apiset *target_set;
-static struct afb_binding_data_v2 datav2;
-
-int afb_monitor_init()
+int afb_monitor_init(struct afb_apiset *declare_set, struct afb_apiset *call_set)
{
- return afb_api_so_v2_add_binding(&_afb_binding_v2_monitor, NULL, main_apiset, &datav2);
+ target_set = call_set;
+ return -!afb_api_v3_from_binding(&_afb_binding_monitor, declare_set, call_set);
}
/******************************************************************************
@@ -66,28 +65,28 @@ static int decode_verbosity(struct json_object *v)
int level = -1;
if (!wrap_json_unpack(v, "i", &level)) {
- level = level < Verbosity_Level_Error ? Verbosity_Level_Error : level > Verbosity_Level_Debug ? Verbosity_Level_Debug : level;
+ level = level < _VERBOSITY_(Log_Level_Error) ? _VERBOSITY_(Log_Level_Error) : level > _VERBOSITY_(Log_Level_Debug) ? _VERBOSITY_(Log_Level_Debug) : level;
} else if (!wrap_json_unpack(v, "s", &s)) {
switch(*s&~' ') {
case 'D':
if (!strcasecmp(s, _debug_))
- level = Verbosity_Level_Debug;
+ level = _VERBOSITY_(Log_Level_Debug);
break;
case 'I':
if (!strcasecmp(s, _info_))
- level = Verbosity_Level_Info;
+ level = _VERBOSITY_(Log_Level_Info);
break;
case 'N':
if (!strcasecmp(s, _notice_))
- level = Verbosity_Level_Notice;
+ level = _VERBOSITY_(Log_Level_Notice);
break;
case 'W':
if (!strcasecmp(s, _warning_))
- level = Verbosity_Level_Warning;
+ level = _VERBOSITY_(Log_Level_Warning);
break;
case 'E':
if (!strcasecmp(s, _error_))
- level = Verbosity_Level_Error;
+ level = _VERBOSITY_(Log_Level_Error);
break;
}
}
@@ -100,9 +99,10 @@ static int decode_verbosity(struct json_object *v)
* @param the name of the api to set
* @param closure the verbosity to set as an integer casted to a pointer
*/
-static void set_verbosity_to_all_cb(struct afb_apiset *set, const char *name, void *closure)
+static void set_verbosity_to_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias)
{
- afb_apiset_set_verbosity(set, name, (int)(intptr_t)closure);
+ if (!isalias)
+ afb_apiset_set_logmask(set, name, (int)(intptr_t)closure);
}
/**
@@ -112,12 +112,13 @@ static void set_verbosity_to_all_cb(struct afb_apiset *set, const char *name, vo
*/
static void set_verbosity_to(const char *name, int level)
{
+ int mask = verbosity_to_mask(level);
if (!name || !name[0])
- verbosity = level;
+ verbosity_set(level);
else if (name[0] == '*' && !name[1])
- afb_apiset_enum(main_apiset, 1, set_verbosity_to_all_cb, (void*)(intptr_t)level);
+ afb_apiset_enum(target_set, 1, set_verbosity_to_all_cb, (void*)(intptr_t)mask);
else
- afb_apiset_set_verbosity(main_apiset, name, level);
+ afb_apiset_set_logmask(target_set, name, mask);
}
/**
@@ -154,12 +155,12 @@ static void set_verbosity(struct json_object *spec)
*/
static struct json_object *encode_verbosity(int level)
{
- switch(level) {
- case Verbosity_Level_Error: return json_object_new_string(_error_);
- case Verbosity_Level_Warning: return json_object_new_string(_warning_);
- case Verbosity_Level_Notice: return json_object_new_string(_notice_);
- case Verbosity_Level_Info: return json_object_new_string(_info_);
- case Verbosity_Level_Debug: return json_object_new_string(_debug_);
+ switch(_DEVERBOSITY_(level)) {
+ case Log_Level_Error: return json_object_new_string(_error_);
+ case Log_Level_Warning: return json_object_new_string(_warning_);
+ case Log_Level_Notice: return json_object_new_string(_notice_);
+ case Log_Level_Info: return json_object_new_string(_info_);
+ case Log_Level_Debug: return json_object_new_string(_debug_);
default: return json_object_new_int(level);
}
}
@@ -170,12 +171,12 @@ static struct json_object *encode_verbosity(int level)
* @param the name of the api to set
* @param closure the json object to build
*/
-static void get_verbosity_of_all_cb(struct afb_apiset *set, const char *name, void *closure)
+static void get_verbosity_of_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias)
{
struct json_object *resu = closure;
- int l = afb_apiset_get_verbosity(set, name);
- if (l >= 0)
- json_object_object_add(resu, name, encode_verbosity(l));
+ int m = afb_apiset_get_logmask(set, name);
+ if (m >= 0)
+ json_object_object_add(resu, name, encode_verbosity(verbosity_from_mask(m)));
}
/**
@@ -185,15 +186,15 @@ static void get_verbosity_of_all_cb(struct afb_apiset *set, const char *name, vo
*/
static void get_verbosity_of(struct json_object *resu, const char *name)
{
- int l;
+ int m;
if (!name || !name[0])
- json_object_object_add(resu, "", encode_verbosity(verbosity));
+ json_object_object_add(resu, "", encode_verbosity(verbosity_get()));
else if (name[0] == '*' && !name[1])
- afb_apiset_enum(main_apiset, 1, get_verbosity_of_all_cb, resu);
+ afb_apiset_enum(target_set, 1, get_verbosity_of_all_cb, resu);
else {
- l = afb_apiset_get_verbosity(main_apiset, name);
- if (l >= 0)
- json_object_object_add(resu, name, encode_verbosity(l));
+ m = afb_apiset_get_logmask(target_set, name);
+ if (m >= 0)
+ json_object_object_add(resu, name, encode_verbosity(verbosity_from_mask(m)));
}
}
@@ -242,8 +243,8 @@ static void get_one_api(struct json_object *resu, const char *name, struct json_
{
struct json_object *o;
- o = afb_apiset_describe(main_apiset, name);
- if (o || afb_apiset_lookup(main_apiset, name, 1))
+ o = afb_apiset_describe(target_set, name);
+ if (o || afb_apiset_lookup(target_set, name, 1))
json_object_object_add(resu, name, o);
}
@@ -253,7 +254,7 @@ static void get_one_api(struct json_object *resu, const char *name, struct json_
* @param the name of the api to set
* @param closure the json object to build
*/
-static void get_apis_of_all_cb(struct afb_apiset *set, const char *name, void *closure)
+static void get_apis_of_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias)
{
struct json_object *resu = closure;
get_one_api(resu, name, NULL);
@@ -285,7 +286,7 @@ static struct json_object *get_apis(struct json_object *spec)
} else if (json_object_is_type(spec, json_type_string)) {
get_one_api(resu, json_object_get_string(spec), NULL);
} else if (json_object_get_boolean(spec)) {
- afb_apiset_enum(main_apiset, 1, get_apis_of_all_cb, resu);
+ afb_apiset_enum(target_set, 1, get_apis_of_all_cb, resu);
}
return resu;
}
@@ -298,7 +299,7 @@ static const char _verbosity_[] = "verbosity";
static const char _apis_[] = "apis";
static const char _refresh_token_[] = "refresh-token";
-static void f_get(struct afb_req req)
+static void f_get(afb_req_t req)
{
struct json_object *r;
struct json_object *apis = NULL;
@@ -314,7 +315,7 @@ static void f_get(struct afb_req req)
afb_req_success(req, r, NULL);
}
-static void f_set(struct afb_req req)
+static void f_set(afb_req_t req)
{
struct json_object *verbosity = NULL;
@@ -325,9 +326,9 @@ static void f_set(struct afb_req req)
afb_req_success(req, NULL, NULL);
}
-static void *context_create()
+static void *context_create(void *closure)
{
- return afb_trace_create(_afb_binding_v2_monitor.api, NULL);
+ return afb_trace_create(_afb_binding_monitor.api, NULL);
}
static void context_destroy(void *pointer)
@@ -336,14 +337,14 @@ static void context_destroy(void *pointer)
afb_trace_unref(trace);
}
-static void f_trace(struct afb_req req)
+static void f_trace(afb_req_t req)
{
int rc;
struct json_object *add = NULL;
struct json_object *drop = NULL;
struct afb_trace *trace;
- trace = afb_req_context(req, context_create, context_destroy);
+ trace = afb_req_context(req, 0, context_create, context_destroy, NULL);
wrap_json_unpack(afb_req_json(req), "{s?o s?o}", "add", &add, "drop", &drop);
if (add) {
rc = afb_trace_add(req, add, trace);
@@ -357,15 +358,15 @@ static void f_trace(struct afb_req req)
}
afb_req_success(req, NULL, NULL);
end:
- afb_apiset_update_hooks(main_apiset, NULL);
+ afb_apiset_update_hooks(target_set, NULL);
afb_evt_update_hooks();
}
-static void f_session(struct afb_req req)
+static void f_session(afb_req_t req)
{
struct json_object *r = NULL;
int refresh = 0;
- struct afb_xreq *xreq = xreq_from_request(req.closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
/* check right to call it */
if (xreq->context.super) {
@@ -387,4 +388,3 @@ static void f_session(struct afb_req req)
afb_req_success(req, r, NULL);
}
-
diff --git a/src/afb-monitor.h b/src/afb-monitor.h
index 1f3c1446..407116d2 100644
--- a/src/afb-monitor.h
+++ b/src/afb-monitor.h
@@ -18,4 +18,6 @@
#pragma once
-extern int afb_monitor_init();
+struct afb_apiset;
+
+extern int afb_monitor_init(struct afb_apiset *declare_set, struct afb_apiset *call_set);
diff --git a/src/afb-msg-json.c b/src/afb-msg-json.c
index 7597f80f..ceeee1a4 100644
--- a/src/afb-msg-json.c
+++ b/src/afb-msg-json.c
@@ -22,7 +22,9 @@
#include "afb-msg-json.h"
#include "afb-context.h"
-struct json_object *afb_msg_json_reply(const char *status, const char *info, struct json_object *resp, struct afb_context *context, const char *reqid)
+static const char _success_[] = "success";
+
+struct json_object *afb_msg_json_reply(struct json_object *resp, const char *error, const char *info, struct afb_context *context)
{
json_object *msg, *request;
const char *token, *uuid;
@@ -37,14 +39,11 @@ struct json_object *afb_msg_json_reply(const char *status, const char *info, str
request = json_object_new_object();
json_object_object_add(msg, "request", request);
- json_object_object_add(request, "status", json_object_new_string(status));
+ json_object_object_add(request, "status", json_object_new_string(error ?: _success_));
if (info != NULL)
json_object_object_add(request, "info", json_object_new_string(info));
- if (reqid != NULL)
- json_object_object_add(request, "reqid", json_object_new_string(reqid));
-
if (context != NULL) {
token = afb_context_sent_token(context);
if (token != NULL)
@@ -58,16 +57,6 @@ struct json_object *afb_msg_json_reply(const char *status, const char *info, str
return msg;
}
-struct json_object *afb_msg_json_reply_ok(const char *info, struct json_object *resp, struct afb_context *context, const char *reqid)
-{
- return afb_msg_json_reply("success", info, resp, context, reqid);
-}
-
-struct json_object *afb_msg_json_reply_error(const char *status, const char *info, struct afb_context *context, const char *reqid)
-{
- return afb_msg_json_reply(status, info, NULL, context, reqid);
-}
-
struct json_object *afb_msg_json_event(const char *event, struct json_object *object)
{
json_object *msg;
@@ -88,7 +77,7 @@ struct json_object *afb_msg_json_event(const char *event, struct json_object *ob
struct json_object *afb_msg_json_internal_error()
{
- return afb_msg_json_reply_error("failed", "internal error", NULL, NULL);
+ return afb_msg_json_reply(NULL, "failed", "internal error", NULL);
}
diff --git a/src/afb-msg-json.h b/src/afb-msg-json.h
index e18ca0a9..ee3ed20c 100644
--- a/src/afb-msg-json.h
+++ b/src/afb-msg-json.h
@@ -21,9 +21,7 @@ struct json_object;
struct afb_context;
struct afb_arg;
-extern struct json_object *afb_msg_json_reply(const char *status, const char *info, struct json_object *resp, struct afb_context *context, const char *reqid);
-extern struct json_object *afb_msg_json_reply_ok(const char *info, struct json_object *resp, struct afb_context *context, const char *reqid);
-extern struct json_object *afb_msg_json_reply_error(const char *status, const char *info, struct afb_context *context, const char *reqid);
+extern struct json_object *afb_msg_json_reply(struct json_object *resp, const char *status, const char *info, struct afb_context *context);
extern struct json_object *afb_msg_json_event(const char *event, struct json_object *object);
diff --git a/src/afb-proto-ws.c b/src/afb-proto-ws.c
index e1993abe..f9313545 100644
--- a/src/afb-proto-ws.c
+++ b/src/afb-proto-ws.c
@@ -61,8 +61,6 @@ The server must reply to the previous actions by
The server can also within the context of a call
- - make a subcall
-
- subscribe or unsubscribe an event
For the purpose of handling events the server can:
@@ -75,42 +73,17 @@ For the purpose of handling events the server can:
/************** constants for protocol definition *************************/
#define CHAR_FOR_CALL 'C'
-#define CHAR_FOR_ANSWER_SUCCESS 'T'
-#define CHAR_FOR_ANSWER_FAIL 'F'
+#define CHAR_FOR_REPLY 'Y'
#define CHAR_FOR_EVT_BROADCAST '*'
#define CHAR_FOR_EVT_ADD '+'
#define CHAR_FOR_EVT_DEL '-'
#define CHAR_FOR_EVT_PUSH '!'
#define CHAR_FOR_EVT_SUBSCRIBE 'S'
#define CHAR_FOR_EVT_UNSUBSCRIBE 'U'
-#define CHAR_FOR_SUBCALL_CALL 'B'
-#define CHAR_FOR_SUBCALL_REPLY 'R'
#define CHAR_FOR_DESCRIBE 'D'
#define CHAR_FOR_DESCRIPTION 'd'
-/******************* handling subcalls *****************************/
-
-/**
- * Structure on server side for recording pending
- * subcalls.
- */
-struct server_subcall
-{
- struct server_subcall *next; /**< next subcall for the client */
- uint32_t subcallid; /**< the subcallid */
- void (*callback)(void*, int, struct json_object*); /**< callback on completion */
- void *closure; /**< closure of the callback */
-};
-
-/**
- * Structure for sending back replies on client side
- */
-struct afb_proto_ws_subcall
-{
- struct afb_proto_ws *protows; /**< proto descriptor */
- void *buffer;
- uint32_t subcallid; /**< subcallid for the reply */
-};
+/******************* handling calls *****************************/
/*
* structure for recording calls on client side
@@ -182,9 +155,6 @@ struct afb_proto_ws
/* emitted calls (client side) */
struct client_call *calls;
- /* pending subcalls (server side) */
- struct server_subcall *subcalls;
-
/* pending description (client side) */
struct client_describe *describes;
@@ -237,6 +207,7 @@ static char *readbuf_get(struct readbuf *rb, uint32_t length)
return before;
}
+__attribute__((unused))
static int readbuf_char(struct readbuf *rb, char *value)
{
if (rb->head >= rb->end)
@@ -256,16 +227,35 @@ static int readbuf_uint32(struct readbuf *rb, uint32_t *value)
return 1;
}
-static int readbuf_string(struct readbuf *rb, const char **value, size_t *length)
+static int _readbuf_string_(struct readbuf *rb, const char **value, size_t *length, int nulok)
{
uint32_t len;
- if (!readbuf_uint32(rb, &len) || !len)
+ if (!readbuf_uint32(rb, &len))
return 0;
+ if (!len) {
+ if (!nulok)
+ return 0;
+ *value = NULL;
+ if (length)
+ *length = 0;
+ return 1;
+ }
if (length)
*length = (size_t)(len - 1);
return (*value = readbuf_get(rb, len)) != NULL && rb->head[-1] == 0;
}
+
+static int readbuf_string(struct readbuf *rb, const char **value, size_t *length)
+{
+ return _readbuf_string_(rb, value, length, 0);
+}
+
+static int readbuf_nullstring(struct readbuf *rb, const char **value, size_t *length)
+{
+ return _readbuf_string_(rb, value, length, 1);
+}
+
static int readbuf_object(struct readbuf *rb, struct json_object **object)
{
const char *string;
@@ -326,6 +316,11 @@ static int writebuf_string(struct writebuf *wb, const char *value)
return writebuf_string_length(wb, value, strlen(value));
}
+static int writebuf_nullstring(struct writebuf *wb, const char *value)
+{
+ return value ? writebuf_string_length(wb, value, strlen(value)) : writebuf_uint32(wb, 0);
+}
+
static int writebuf_object(struct writebuf *wb, struct json_object *object)
{
const char *string = json_object_to_json_string_ext(object, JSON_C_TO_STRING_PLAIN);
@@ -349,15 +344,16 @@ void afb_proto_ws_call_unref(struct afb_proto_ws_call *call)
free(call);
}
-int afb_proto_ws_call_success(struct afb_proto_ws_call *call, struct json_object *obj, const char *info)
+int afb_proto_ws_call_reply(struct afb_proto_ws_call *call, struct json_object *obj, const char *error, const char *info)
{
int rc = -1;
struct writebuf wb = { .count = 0 };
struct afb_proto_ws *protows = call->protows;
- if (writebuf_char(&wb, CHAR_FOR_ANSWER_SUCCESS)
+ if (writebuf_char(&wb, CHAR_FOR_REPLY)
&& writebuf_uint32(&wb, call->callid)
- && writebuf_string(&wb, info ?: "")
+ && writebuf_nullstring(&wb, error)
+ && writebuf_nullstring(&wb, info)
&& writebuf_object(&wb, obj)) {
pthread_mutex_lock(&protows->mutex);
rc = afb_ws_binary_v(protows->ws, wb.iovec, wb.count);
@@ -371,73 +367,6 @@ success:
return rc;
}
-int afb_proto_ws_call_fail(struct afb_proto_ws_call *call, const char *status, const char *info)
-{
- int rc = -1;
- struct writebuf wb = { .count = 0 };
- struct afb_proto_ws *protows = call->protows;
-
- if (writebuf_char(&wb, CHAR_FOR_ANSWER_FAIL)
- && writebuf_uint32(&wb, call->callid)
- && writebuf_string(&wb, status)
- && writebuf_string(&wb, info ? : "")) {
- pthread_mutex_lock(&protows->mutex);
- rc = afb_ws_binary_v(protows->ws, wb.iovec, wb.count);
- pthread_mutex_unlock(&protows->mutex);
- if (rc >= 0) {
- rc = 0;
- goto success;
- }
- }
-success:
- return rc;
-}
-
-int afb_proto_ws_call_subcall(struct afb_proto_ws_call *call, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure)
-{
- int rc = -1;
- struct writebuf wb = { .count = 0 };
- struct server_subcall *sc, *osc;
- struct afb_proto_ws *protows = call->protows;
-
- sc = malloc(sizeof *sc);
- if (!sc)
- errno = ENOMEM;
- else {
- sc->callback = callback;
- sc->closure = cb_closure;
-
- pthread_mutex_lock(&protows->mutex);
- sc->subcallid = ptr2id(sc);
- do {
- sc->subcallid++;
- osc = protows->subcalls;
- while(osc && osc->subcallid != sc->subcallid)
- osc = osc->next;
- } while (osc);
- sc->next = protows->subcalls;
- protows->subcalls = sc;
- pthread_mutex_unlock(&protows->mutex);
-
- if (writebuf_char(&wb, CHAR_FOR_SUBCALL_CALL)
- && writebuf_uint32(&wb, sc->subcallid)
- && writebuf_uint32(&wb, call->callid)
- && writebuf_string(&wb, api)
- && writebuf_string(&wb, verb)
- && writebuf_object(&wb, args)) {
- pthread_mutex_lock(&protows->mutex);
- rc = afb_ws_binary_v(protows->ws, wb.iovec, wb.count);
- pthread_mutex_unlock(&protows->mutex);
- if (rc >= 0) {
- rc = 0;
- goto success;
- }
- }
- }
-success:
- return rc;
-}
-
int afb_proto_ws_call_subscribe(struct afb_proto_ws_call *call, const char *event_name, int event_id)
{
int rc = -1;
@@ -613,113 +542,23 @@ static void client_on_event_push(struct afb_proto_ws *protows, struct readbuf *r
protows->client_itf->on_event_push(protows->closure, event_name, (int)event_id, object);
}
-static void client_on_reply_success(struct afb_proto_ws *protows, struct readbuf *rb)
+static void client_on_reply(struct afb_proto_ws *protows, struct readbuf *rb)
{
struct client_call *call;
struct json_object *object;
- const char *info;
-
- if (!client_msg_call_get(protows, rb, &call))
- return;
-
- if (readbuf_string(rb, &info, NULL) && readbuf_object(rb, &object)) {
- protows->client_itf->on_reply_success(protows->closure, call->request, object, info);
- } else {
- protows->client_itf->on_reply_fail(protows->closure, call->request, "proto-error", "can't process success");
- }
- client_call_destroy(call);
-}
-
-static void client_on_reply_fail(struct afb_proto_ws *protows, struct readbuf *rb)
-{
- struct client_call *call;
- const char *info, *status;
+ const char *error, *info;
if (!client_msg_call_get(protows, rb, &call))
return;
-
- if (readbuf_string(rb, &status, NULL) && readbuf_string(rb, &info, NULL)) {
- protows->client_itf->on_reply_fail(protows->closure, call->request, status, info);
+ if (readbuf_nullstring(rb, &error, NULL) && readbuf_nullstring(rb, &info, NULL) && readbuf_object(rb, &object)) {
+ protows->client_itf->on_reply(protows->closure, call->request, object, error, info);
} else {
- protows->client_itf->on_reply_fail(protows->closure, call->request, "proto-error", "can't process fail");
+ protows->client_itf->on_reply(protows->closure, call->request, NULL, "proto-error", "can't process success");
}
client_call_destroy(call);
}
-/* send a subcall reply */
-static int client_send_subcall_reply(struct afb_proto_ws *protows, uint32_t subcallid, int status, json_object *object)
-{
- struct writebuf wb = { .count = 0 };
- char ie = status < 0;
- int rc;
-
- if (writebuf_char(&wb, CHAR_FOR_SUBCALL_REPLY)
- && writebuf_uint32(&wb, subcallid)
- && writebuf_char(&wb, ie)
- && writebuf_object(&wb, object)) {
- pthread_mutex_lock(&protows->mutex);
- rc = afb_ws_binary_v(protows->ws, wb.iovec, wb.count);
- pthread_mutex_unlock(&protows->mutex);
- if (rc >= 0)
- return 0;
- }
- return -1;
-}
-
-/* callback for subcall reply */
-int afb_proto_ws_subcall_reply(struct afb_proto_ws_subcall *subcall, int status, struct json_object *result)
-{
- int rc = client_send_subcall_reply(subcall->protows, subcall->subcallid, status, result);
- afb_proto_ws_unref(subcall->protows);
- free(subcall->buffer);
- free(subcall);
- return rc;
-}
-
-/* received a subcall request */
-static void client_on_subcall(struct afb_proto_ws *protows, struct readbuf *rb)
-{
- struct afb_proto_ws_subcall *subcall;
- struct client_call *call;
- const char *api, *verb;
- uint32_t subcallid;
- struct json_object *object;
-
- /* get the subcallid */
- if (!readbuf_uint32(rb, &subcallid))
- return;
-
- /* if not expected drop it */
- if (!protows->client_itf->on_subcall)
- goto error;
-
- /* retrieve the message data */
- if (!client_msg_call_get(protows, rb, &call))
- goto error;
-
- /* allocation of the subcall */
- subcall = malloc(sizeof *subcall);
- if (!subcall)
- goto error;
-
- /* make the call */
- if (readbuf_string(rb, &api, NULL)
- && readbuf_string(rb, &verb, NULL)
- && readbuf_object(rb, &object)) {
- afb_proto_ws_addref(protows);
- subcall->protows = protows;
- subcall->subcallid = subcallid;
- subcall->buffer = rb->base;
- rb->base = NULL;
- protows->client_itf->on_subcall(protows->closure, subcall, call->request, api, verb, object);
- return;
- }
- free(subcall);
-error:
- client_send_subcall_reply(protows, subcallid, 1, NULL);
-}
-
static void client_on_description(struct afb_proto_ws *protows, struct readbuf *rb)
{
uint32_t descid;
@@ -751,11 +590,8 @@ static void client_on_binary_job(int sig, void *closure)
if (!sig) {
switch (*binary->rb.head++) {
- case CHAR_FOR_ANSWER_SUCCESS: /* success */
- client_on_reply_success(binary->protows, &binary->rb);
- break;
- case CHAR_FOR_ANSWER_FAIL: /* fail */
- client_on_reply_fail(binary->protows, &binary->rb);
+ case CHAR_FOR_REPLY: /* reply */
+ client_on_reply(binary->protows, &binary->rb);
break;
case CHAR_FOR_EVT_BROADCAST: /* broadcast */
client_on_event_broadcast(binary->protows, &binary->rb);
@@ -775,9 +611,6 @@ static void client_on_binary_job(int sig, void *closure)
case CHAR_FOR_EVT_UNSUBSCRIBE: /* unsubscribe event for a request */
client_on_event_unsubscribe(binary->protows, &binary->rb);
break;
- case CHAR_FOR_SUBCALL_CALL: /* subcall */
- client_on_subcall(binary->protows, &binary->rb);
- break;
case CHAR_FOR_DESCRIPTION: /* description */
client_on_description(binary->protows, &binary->rb);
break;
@@ -819,7 +652,8 @@ int afb_proto_ws_client_call(
const char *verb,
struct json_object *args,
const char *sessionid,
- void *request
+ void *request,
+ const char *user_creds
)
{
int rc = -1;
@@ -849,7 +683,8 @@ int afb_proto_ws_client_call(
|| !writebuf_uint32(&wb, call->callid)
|| !writebuf_string(&wb, verb)
|| !writebuf_string(&wb, sessionid)
- || !writebuf_object(&wb, args)) {
+ || !writebuf_object(&wb, args)
+ || !writebuf_nullstring(&wb, user_creds)) {
errno = EINVAL;
goto clean;
}
@@ -929,7 +764,7 @@ error:
static void server_on_call(struct afb_proto_ws *protows, struct readbuf *rb)
{
struct afb_proto_ws_call *call;
- const char *uuid, *verb;
+ const char *uuid, *verb, *user_creds;
uint32_t callid;
size_t lenverb;
struct json_object *object;
@@ -940,7 +775,8 @@ static void server_on_call(struct afb_proto_ws *protows, struct readbuf *rb)
if (!readbuf_uint32(rb, &callid)
|| !readbuf_string(rb, &verb, &lenverb)
|| !readbuf_string(rb, &uuid, NULL)
- || !readbuf_object(rb, &object))
+ || !readbuf_object(rb, &object)
+ || !readbuf_nullstring(rb, &user_creds, NULL))
goto overflow;
/* create the request */
@@ -954,7 +790,7 @@ static void server_on_call(struct afb_proto_ws *protows, struct readbuf *rb)
call->buffer = rb->base;
rb->base = NULL; /* don't free the buffer */
- protows->server_itf->on_call(protows->closure, call, verb, object, uuid);
+ protows->server_itf->on_call(protows->closure, call, verb, object, uuid, user_creds);
return;
out_of_memory:
@@ -964,39 +800,6 @@ overflow:
afb_proto_ws_unref(protows);
}
-/* on subcall reply */
-static void server_on_subcall_reply(struct afb_proto_ws *protows, struct readbuf *rb)
-{
- char ie;
- uint32_t subcallid;
- struct json_object *object;
- struct server_subcall *sc, **psc;
-
- /* reads the call message data */
- if (!readbuf_uint32(rb, &subcallid)
- || !readbuf_char(rb, &ie)
- || !readbuf_object(rb, &object)) {
- /* TODO bad protocol */
- return;
- }
-
- /* search the subcall and unlink it */
- pthread_mutex_lock(&protows->mutex);
- psc = &protows->subcalls;
- while ((sc = *psc) && sc->subcallid != subcallid)
- psc = &sc->next;
- if (!sc) {
- pthread_mutex_unlock(&protows->mutex);
- json_object_put(object);
- /* TODO subcall not found */
- } else {
- *psc = sc->next;
- pthread_mutex_unlock(&protows->mutex);
- sc->callback(sc->closure, -(int)ie, object);
- free(sc);
- }
-}
-
static int server_send_description(struct afb_proto_ws *protows, uint32_t descid, struct json_object *descobj)
{
int rc;
@@ -1055,9 +858,6 @@ static void server_on_binary_job(int sig, void *closure)
case CHAR_FOR_CALL:
server_on_call(binary->protows, &binary->rb);
break;
- case CHAR_FOR_SUBCALL_REPLY:
- server_on_subcall_reply(binary->protows, &binary->rb);
- break;
case CHAR_FOR_DESCRIBE:
server_on_describe(binary->protows, &binary->rb);
break;
@@ -1139,17 +939,8 @@ int afb_proto_ws_server_event_broadcast(struct afb_proto_ws *protows, const char
static void on_hangup(void *closure)
{
struct afb_proto_ws *protows = closure;
- struct server_subcall *sc, *nsc;
struct client_describe *cd, *ncd;
- nsc = protows->subcalls;
- while (nsc) {
- sc= nsc;
- nsc = sc->next;
- sc->callback(sc->closure, 1, NULL);
- free(sc);
- }
-
ncd = protows->describes;
while (ncd) {
cd= ncd;
@@ -1202,7 +993,6 @@ static struct afb_proto_ws *afb_proto_ws_create(struct fdev *fdev, const struct
if (protows->ws != NULL) {
protows->fdev = fdev;
protows->refcount = 1;
- protows->subcalls = NULL;
protows->closure = closure;
protows->server_itf = itfs;
protows->client_itf = itfc;
diff --git a/src/afb-proto-ws.h b/src/afb-proto-ws.h
index d674af3d..342313e7 100644
--- a/src/afb-proto-ws.h
+++ b/src/afb-proto-ws.h
@@ -18,17 +18,21 @@
#pragma once
+/*
+ * Defined since version 3, the value AFB_PROTO_WS_VERSION can be used to
+ * track versions of afb-proto-ws.
+ */
+#define AFB_PROTO_WS_VERSION 3
+
struct fdev;
struct afb_proto_ws;
struct afb_proto_ws_call;
-struct afb_proto_ws_subcall;
struct afb_proto_ws_describe;
struct afb_proto_ws_client_itf
{
/* can't be NULL */
- void (*on_reply_success)(void *closure, void *request, struct json_object *result, const char *info);
- void (*on_reply_fail)(void *closure, void *request, const char *status, const char *info);
+ void (*on_reply)(void *closure, void *request, struct json_object *obj, const char *error, const char *info);
/* can be NULL */
void (*on_event_create)(void *closure, const char *event_name, int event_id);
@@ -37,13 +41,11 @@ struct afb_proto_ws_client_itf
void (*on_event_unsubscribe)(void *closure, void *request, const char *event_name, int event_id);
void (*on_event_push)(void *closure, const char *event_name, int event_id, struct json_object *data);
void (*on_event_broadcast)(void *closure, const char *event_name, struct json_object *data);
-
- void (*on_subcall)(void *closure, struct afb_proto_ws_subcall *subcall, void *request, const char *api, const char *verb, struct json_object *args);
};
struct afb_proto_ws_server_itf
{
- void (*on_call)(void *closure, struct afb_proto_ws_call *call, const char *verb, struct json_object *args, const char *sessionid);
+ void (*on_call)(void *closure, struct afb_proto_ws_call *call, const char *verb, struct json_object *args, const char *sessionid, const char *user_creds);
void (*on_describe)(void *closure, struct afb_proto_ws_describe *describe);
};
@@ -61,7 +63,7 @@ extern void afb_proto_ws_on_hangup(struct afb_proto_ws *protows, void (*on_hangu
-extern int afb_proto_ws_client_call(struct afb_proto_ws *protows, const char *verb, struct json_object *args, const char *sessionid, void *request);
+extern int afb_proto_ws_client_call(struct afb_proto_ws *protows, const char *verb, struct json_object *args, const char *sessionid, void *request, const char *user_creds);
extern int afb_proto_ws_client_describe(struct afb_proto_ws *protows, void (*callback)(void*, struct json_object*), void *closure);
extern int afb_proto_ws_server_event_create(struct afb_proto_ws *protows, const char *event_name, int event_id);
@@ -72,14 +74,9 @@ extern int afb_proto_ws_server_event_broadcast(struct afb_proto_ws *protows, con
extern void afb_proto_ws_call_addref(struct afb_proto_ws_call *call);
extern void afb_proto_ws_call_unref(struct afb_proto_ws_call *call);
-extern int afb_proto_ws_call_success(struct afb_proto_ws_call *call, struct json_object *obj, const char *info);
-extern int afb_proto_ws_call_fail(struct afb_proto_ws_call *call, const char *status, const char *info);
+extern int afb_proto_ws_call_reply(struct afb_proto_ws_call *call, struct json_object *obj, const char *error, const char *info);
-extern int afb_proto_ws_call_subcall(struct afb_proto_ws_call *call, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure);
extern int afb_proto_ws_call_subscribe(struct afb_proto_ws_call *call, const char *event_name, int event_id);
extern int afb_proto_ws_call_unsubscribe(struct afb_proto_ws_call *call, const char *event_name, int event_id);
-extern int afb_proto_ws_subcall_reply(struct afb_proto_ws_subcall *subcall, int status, struct json_object *result);
-
extern int afb_proto_ws_describe_put(struct afb_proto_ws_describe *describe, struct json_object *description);
-
diff --git a/src/afb-session.c b/src/afb-session.c
index 8c0f77b8..16fc69bb 100644
--- a/src/afb-session.c
+++ b/src/afb-session.c
@@ -27,11 +27,10 @@
#include <uuid/uuid.h>
#include <errno.h>
-#include <json-c/json.h>
-
#include "afb-session.h"
#include "afb-hook.h"
#include "verbose.h"
+#include "pearson.h"
#define SIZEUUID 37
#define HEADCOUNT 16
@@ -43,41 +42,45 @@
#define MAX_EXPIRATION (_MAXEXP_ >= 0 ? _MAXEXP_ : _MAXEXP2_)
#define NOW (time_now())
-/* structure for a cookie added to sessions */
+/**
+ * structure for a cookie added to sessions
+ */
struct cookie
{
- struct cookie *next; /* link to next cookie */
- const void *key; /* pointer key */
- void *value; /* value */
- void (*freecb)(void*); /* function to call when session is closed */
+ struct cookie *next; /**< link to next cookie */
+ const void *key; /**< pointer key */
+ void *value; /**< value */
+ void (*freecb)(void*); /**< function to call when session is closed */
};
-/*
+/**
* structure for session
*/
struct afb_session
{
- struct afb_session *next; /* link to the next */
- unsigned refcount; /* external reference count of the session */
- int timeout; /* timeout of the session */
- time_t expiration; /* expiration time of the token */
- pthread_mutex_t mutex; /* mutex of the session */
- struct cookie *cookies[COOKIECOUNT]; /* cookies of the session */
- uint8_t closed: 1; /* is the session closed ? */
- uint8_t autoclose: 1; /* close the session when unreferenced */
- uint8_t notinset: 1; /* session removed from the set of sessions */
- char uuid[SIZEUUID]; /* long term authentication of remote client */
- char token[SIZEUUID]; /* short term authentication of remote client */
+ struct afb_session *next; /**< link to the next */
+ unsigned refcount; /**< external reference count of the session */
+ int timeout; /**< timeout of the session */
+ time_t expiration; /**< expiration time of the token */
+ pthread_mutex_t mutex; /**< mutex of the session */
+ struct cookie *cookies[COOKIECOUNT]; /**< cookies of the session */
+ uint8_t closed: 1; /**< is the session closed ? */
+ uint8_t autoclose: 1; /**< close the session when unreferenced */
+ uint8_t notinset: 1; /**< session removed from the set of sessions */
+ char uuid[SIZEUUID]; /**< long term authentication of remote client */
+ char token[SIZEUUID]; /**< short term authentication of remote client */
};
-/* Session UUID are store in a simple array [for 10 sessions this should be enough] */
+/**
+ * structure for managing sessions
+ */
static struct {
- int count; /* current number of sessions */
- int max; /* maximum count of sessions */
- int timeout; /* common initial timeout */
- struct afb_session *heads[HEADCOUNT]; /* sessions */
- char initok[SIZEUUID]; /* common initial token */
- pthread_mutex_t mutex; /* declare a mutex to protect hash table */
+ int count; /**< current number of sessions */
+ int max; /**< maximum count of sessions */
+ int timeout; /**< common initial timeout */
+ struct afb_session *heads[HEADCOUNT]; /**< sessions */
+ char initok[SIZEUUID]; /**< common initial token */
+ pthread_mutex_t mutex; /**< declare a mutex to protect hash table */
} sessions = {
.count = 0,
.max = 10,
@@ -87,7 +90,9 @@ static struct {
.mutex = PTHREAD_MUTEX_INITIALIZER
};
-/* Get the actual raw time */
+/**
+ * Get the actual raw time
+ */
static inline time_t time_now()
{
struct timespec ts;
@@ -95,7 +100,9 @@ static inline time_t time_now()
return ts.tv_sec;
}
-/* generate a new fresh 'uuid' */
+/**
+ * generate a new fresh 'uuid'
+ */
static void new_uuid(char uuid[SIZEUUID])
{
uuid_t newuuid;
@@ -103,26 +110,6 @@ static void new_uuid(char uuid[SIZEUUID])
uuid_unparse_lower(newuuid, uuid);
}
-/*
- * Returns a tiny hash value for the 'text'.
- *
- * Tiny hash function inspired from pearson
- */
-static uint8_t pearson4(const char *text)
-{
- static uint8_t T[16] = {
- 4, 1, 6, 0, 9, 14, 11, 5,
- 2, 3, 12, 15, 10, 7, 8, 13
- };
- uint8_t r, c;
-
- for (r = 0; (c = (uint8_t)*text) ; text++) {
- r = T[r ^ (15 & c)];
- r = T[r ^ (c >> 4)];
- }
- return r; // % HEADCOUNT;
-}
-
/* lock the set of sessions for exclusive access */
static inline void sessionset_lock()
{
@@ -155,7 +142,7 @@ static struct afb_session *sessionset_search(const char *uuid, uint8_t hashidx)
static int sessionset_add(struct afb_session *session, uint8_t hashidx)
{
/* check availability */
- if (sessions.count >= sessions.max) {
+ if (sessions.max && sessions.count >= sessions.max) {
errno = EBUSY;
return -1;
}
@@ -321,7 +308,7 @@ static time_t sessionset_cleanup (int force)
* @param max_session_count maximum allowed session count in the same time
* @param timeout the initial default timeout of sessions
* @param initok the initial default token of sessions
- *
+ *
*/
int afb_session_init (int max_session_count, int timeout, const char *initok)
{
@@ -513,7 +500,7 @@ void afb_session_close (struct afb_session *session)
* Set the 'autoclose' flag of the 'session'
*
* A session whose autoclose flag is true will close as
- * soon as it is no more referenced.
+ * soon as it is no more referenced.
*
* @param session the session to set
* @param autoclose the value to set
@@ -694,8 +681,7 @@ void *afb_session_get_cookie(struct afb_session *session, const void *key)
* @param value the value to store at key
* @param freecb a function to use when the cookie value is to remove (or null)
*
- * @return the data staored for the key or NULL if the key isn't found
- *
+ * @return 0 in case of success or -1 in case of error
*/
int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*))
{
diff --git a/src/afb-stub-ws.c b/src/afb-stub-ws.c
index e725d5ad..68bc8c7c 100644
--- a/src/afb-stub-ws.c
+++ b/src/afb-stub-ws.c
@@ -34,7 +34,7 @@
#include <json-c/json.h>
-#include <afb/afb-event.h>
+#include <afb/afb-event-x2.h>
#include "afb-session.h"
#include "afb-cred.h"
@@ -52,29 +52,6 @@
struct afb_stub_ws;
-/******************* handling subcalls *****************************/
-
-/**
- * Structure on server side for recording pending
- * subcalls.
- */
-struct server_subcall
-{
- struct server_subcall *next; /**< next subcall for the client */
- uint32_t subcallid; /**< the subcallid */
- void (*callback)(void*, int, struct json_object*); /**< callback on completion */
- void *closure; /**< closure of the callback */
-};
-
-/**
- * Structure for sending back replies on client side
- */
-struct client_subcall
-{
- struct afb_stub_ws *stubws; /**< stub descriptor */
- uint32_t subcallid; /**< subcallid for the reply */
-};
-
/*
* structure for recording calls on client side
*/
@@ -100,7 +77,7 @@ struct server_req {
struct client_event
{
struct client_event *next;
- struct afb_eventid *eventid;
+ struct afb_event_x2 *event;
int id;
int refcount;
};
@@ -152,7 +129,7 @@ struct afb_stub_ws
/* event replica (client side) */
struct client_event *events;
- /* credentials (server side) */
+ /* credentials of the client (server side) */
struct afb_cred *cred;
/* sessions (server side) */
@@ -183,57 +160,37 @@ static void server_req_destroy_cb(struct afb_xreq *xreq)
free(wreq);
}
-static void server_req_success_cb(struct afb_xreq *xreq, struct json_object *obj, const char *info)
+static void server_req_reply_cb(struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info)
{
int rc;
struct server_req *wreq = CONTAINER_OF_XREQ(struct server_req, xreq);
- rc = afb_proto_ws_call_success(wreq->call, obj, info);
+ rc = afb_proto_ws_call_reply(wreq->call, obj, error, info);
if (rc < 0)
- ERROR("error while sending success");
+ ERROR("error while sending reply");
json_object_put(obj);
}
-static void server_req_fail_cb(struct afb_xreq *xreq, const char *status, const char *info)
+static int server_req_subscribe_cb(struct afb_xreq *xreq, struct afb_event_x2 *event)
{
int rc;
struct server_req *wreq = CONTAINER_OF_XREQ(struct server_req, xreq);
- rc = afb_proto_ws_call_fail(wreq->call, status, info);
- if (rc < 0)
- ERROR("error while sending fail");
-}
-
-static void server_req_subcall_cb(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure)
-{
- int rc;
- struct server_req *wreq = CONTAINER_OF_XREQ(struct server_req, xreq);
-
- rc = afb_proto_ws_call_subcall(wreq->call, api, verb, args, callback, cb_closure);
- if (rc < 0)
- ERROR("error while sending subcall");
-}
-
-static int server_req_subscribe_cb(struct afb_xreq *xreq, struct afb_eventid *event)
-{
- int rc;
- struct server_req *wreq = CONTAINER_OF_XREQ(struct server_req, xreq);
-
- rc = afb_evt_eventid_add_watch(wreq->stubws->listener, event);
+ rc = afb_evt_event_x2_add_watch(wreq->stubws->listener, event);
if (rc >= 0)
- rc = afb_proto_ws_call_subscribe(wreq->call, afb_evt_eventid_fullname(event), afb_evt_eventid_id(event));
+ rc = afb_proto_ws_call_subscribe(wreq->call, afb_evt_event_x2_fullname(event), afb_evt_event_x2_id(event));
if (rc < 0)
ERROR("error while subscribing event");
return rc;
}
-static int server_req_unsubscribe_cb(struct afb_xreq *xreq, struct afb_eventid *event)
+static int server_req_unsubscribe_cb(struct afb_xreq *xreq, struct afb_event_x2 *event)
{
int rc, rc2;
struct server_req *wreq = CONTAINER_OF_XREQ(struct server_req, xreq);
- rc = afb_proto_ws_call_unsubscribe(wreq->call, afb_evt_eventid_fullname(event), afb_evt_eventid_id(event));
- rc2 = afb_evt_eventid_remove_watch(wreq->stubws->listener, event);
+ rc = afb_proto_ws_call_unsubscribe(wreq->call, afb_evt_event_x2_fullname(event), afb_evt_event_x2_id(event));
+ rc2 = afb_evt_event_x2_remove_watch(wreq->stubws->listener, event);
if (rc >= 0 && rc2 < 0)
rc = rc2;
if (rc < 0)
@@ -242,10 +199,8 @@ static int server_req_unsubscribe_cb(struct afb_xreq *xreq, struct afb_eventid *
}
static const struct afb_xreq_query_itf server_req_xreq_itf = {
- .success = server_req_success_cb,
- .fail = server_req_fail_cb,
+ .reply = server_req_reply_cb,
.unref = server_req_destroy_cb,
- .subcall = server_req_subcall_cb,
.subscribe = server_req_subscribe_cb,
.unsubscribe = server_req_unsubscribe_cb
};
@@ -258,7 +213,7 @@ static struct client_event *client_event_search(struct afb_stub_ws *stubws, uint
struct client_event *ev;
ev = stubws->events;
- while (ev != NULL && (ev->id != eventid || 0 != strcmp(afb_evt_eventid_fullname(ev->eventid), name)))
+ while (ev != NULL && (ev->id != eventid || 0 != strcmp(afb_evt_event_x2_fullname(ev->event), name)))
ev = ev->next;
return ev;
@@ -269,7 +224,13 @@ static void client_call_cb(void * closure, struct afb_xreq *xreq)
{
struct afb_stub_ws *stubws = closure;
- afb_proto_ws_client_call(stubws->proto, xreq->request.verb, afb_xreq_json(xreq), afb_session_uuid(xreq->context.session), xreq);
+ afb_proto_ws_client_call(
+ stubws->proto,
+ xreq->request.called_verb,
+ afb_xreq_json(xreq),
+ afb_session_uuid(xreq->context.session),
+ xreq,
+ xreq_on_behalf_cred_export(xreq));
afb_xreq_unhooked_addref(xreq);
}
@@ -339,19 +300,11 @@ static void server_event_broadcast(void *closure, const char *event, int eventid
/*****************************************************/
-static void on_reply_success(void *closure, void *request, struct json_object *result, const char *info)
-{
- struct afb_xreq *xreq = request;
-
- afb_xreq_success(xreq, result, *info ? info : NULL);
- afb_xreq_unhooked_unref(xreq);
-}
-
-static void on_reply_fail(void *closure, void *request, const char *status, const char *info)
+static void on_reply(void *closure, void *request, struct json_object *object, const char *error, const char *info)
{
struct afb_xreq *xreq = request;
- afb_xreq_fail(xreq, status, *info ? info : NULL);
+ afb_xreq_reply(xreq, object, error, info);
afb_xreq_unhooked_unref(xreq);
}
@@ -370,8 +323,8 @@ static void on_event_create(void *closure, const char *event_name, int event_id)
/* no conflict, try to add it */
ev = malloc(sizeof *ev);
if (ev != NULL) {
- ev->eventid = afb_evt_eventid_create(event_name);
- if (ev->eventid != NULL) {
+ ev->event = afb_evt_event_x2_create(event_name);
+ if (ev->event != NULL) {
ev->refcount = 1;
ev->id = event_id;
ev->next = stubws->events;
@@ -404,7 +357,7 @@ static void on_event_remove(void *closure, const char *event_name, int event_id)
*prv = ev->next;
/* destroys the event */
- afb_evt_eventid_unref(ev->eventid);
+ afb_evt_event_x2_unref(ev->event);
free(ev);
}
@@ -419,7 +372,7 @@ static void on_event_subscribe(void *closure, void *request, const char *event_n
if (ev == NULL)
return;
- if (afb_xreq_subscribe(xreq, ev->eventid) < 0)
+ if (afb_xreq_subscribe(xreq, ev->event) < 0)
ERROR("can't subscribe: %m");
}
@@ -434,7 +387,7 @@ static void on_event_unsubscribe(void *closure, void *request, const char *event
if (ev == NULL)
return;
- if (afb_xreq_unsubscribe(xreq, ev->eventid) < 0)
+ if (afb_xreq_unsubscribe(xreq, ev->event) < 0)
ERROR("can't unsubscribe: %m");
}
@@ -446,7 +399,7 @@ static void on_event_push(void *closure, const char *event_name, int event_id, s
/* check conflicts */
ev = client_event_search(stubws, event_id, event_name);
if (ev)
- afb_evt_eventid_push(ev->eventid, data);
+ afb_evt_event_x2_push(ev->event, data);
else
ERROR("unreadable push event");
}
@@ -456,19 +409,6 @@ static void on_event_broadcast(void *closure, const char *event_name, struct jso
afb_evt_broadcast(event_name, data);
}
-static void client_subcall_reply_cb(void *closure, int status, json_object *object, struct afb_request *request)
-{
- struct afb_proto_ws_subcall *subcall = closure;
- afb_proto_ws_subcall_reply(subcall, status, object);
-}
-
-static void on_subcall(void *closure, struct afb_proto_ws_subcall *subcall, void *request, const char *api, const char *verb, struct json_object *args)
-{
- struct afb_xreq *xreq = request;
-
- afb_xreq_subcall(xreq, api, verb, args, client_subcall_reply_cb, subcall);
-}
-
/*****************************************************/
static void record_session(struct afb_stub_ws *stubws, struct afb_session *session)
@@ -514,7 +454,7 @@ static void release_all_sessions(struct afb_stub_ws *stubws)
/*****************************************************/
-static void on_call(void *closure, struct afb_proto_ws_call *call, const char *verb, struct json_object *args, const char *sessionid)
+static void on_call(void *closure, struct afb_proto_ws_call *call, const char *verb, struct json_object *args, const char *sessionid, const char *user_creds)
{
struct afb_stub_ws *stubws = closure;
struct server_req *wreq;
@@ -539,9 +479,9 @@ static void on_call(void *closure, struct afb_proto_ws_call *call, const char *v
afb_session_set_autoclose(wreq->xreq.context.session, 1);
/* makes the call */
- wreq->xreq.cred = afb_cred_addref(stubws->cred);
- wreq->xreq.request.api = stubws->apiname;
- wreq->xreq.request.verb = verb;
+ wreq->xreq.cred = afb_cred_mixed_on_behalf_import(stubws->cred, sessionid, user_creds);
+ wreq->xreq.request.called_api = stubws->apiname;
+ wreq->xreq.request.called_verb = verb;
wreq->xreq.json = args;
afb_xreq_process(&wreq->xreq, stubws->apiset);
return;
@@ -551,7 +491,7 @@ unconnected:
out_of_memory:
json_object_put(args);
afb_stub_ws_unref(stubws);
- afb_proto_ws_call_fail(call, "internal-error", NULL);
+ afb_proto_ws_call_reply(call, NULL, "internal-error", NULL);
afb_proto_ws_call_unref(call);
}
@@ -601,15 +541,13 @@ static void on_describe(void *closure, struct afb_proto_ws_describe *describe)
static const struct afb_proto_ws_client_itf client_itf =
{
- .on_reply_success = on_reply_success,
- .on_reply_fail = on_reply_fail,
+ .on_reply = on_reply,
.on_event_create = on_event_create,
.on_event_remove = on_event_remove,
.on_event_subscribe = on_event_subscribe,
.on_event_unsubscribe = on_event_unsubscribe,
.on_event_push = on_event_push,
.on_event_broadcast = on_event_broadcast,
- .on_subcall = on_subcall
};
static const struct afb_proto_ws_server_itf server_itf =
@@ -642,7 +580,7 @@ static void drop_all_events(struct afb_stub_ws *stubws)
while (ev) {
nxt = ev->next;
- afb_evt_eventid_unref(ev->eventid);
+ afb_evt_event_x2_unref(ev->event);
free(ev);
ev = nxt;
}
@@ -738,9 +676,9 @@ const char *afb_stub_ws_name(struct afb_stub_ws *stubws)
return stubws->apiname;
}
-struct afb_api afb_stub_ws_client_api(struct afb_stub_ws *stubws)
+struct afb_api_item afb_stub_ws_client_api(struct afb_stub_ws *stubws)
{
- struct afb_api api;
+ struct afb_api_item api;
assert(!stubws->listener); /* check client */
api.closure = stubws;
diff --git a/src/afb-stub-ws.h b/src/afb-stub-ws.h
index aa643363..e14eac17 100644
--- a/src/afb-stub-ws.h
+++ b/src/afb-stub-ws.h
@@ -21,7 +21,7 @@
struct fdev;
struct afb_stub_ws;
struct afb_apiset;
-struct afb_api;
+struct afb_api_item;
extern struct afb_stub_ws *afb_stub_ws_create_client(struct fdev *fdev, const char *apiname, struct afb_apiset *apiset);
@@ -35,7 +35,7 @@ extern void afb_stub_ws_on_hangup(struct afb_stub_ws *stubws, void (*on_hangup)(
extern const char *afb_stub_ws_name(struct afb_stub_ws *stubws);
-extern struct afb_api afb_stub_ws_client_api(struct afb_stub_ws *stubws);
+extern struct afb_api_item afb_stub_ws_client_api(struct afb_stub_ws *stubws);
extern int afb_stub_ws_client_add(struct afb_stub_ws *stubws, struct afb_apiset *apiset);
diff --git a/src/afb-supervision.c b/src/afb-supervision.c
index f1024c3c..79a9d3fd 100644
--- a/src/afb-supervision.c
+++ b/src/afb-supervision.c
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#define _GNU_SOURCE
#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO
@@ -29,7 +28,9 @@
#include <sys/un.h>
#include <json-c/json.h>
-#include <afb/afb-binding-v2.h>
+
+#define AFB_BINDING_VERSION 3
+#include <afb/afb-binding.h>
#include "afb-cred.h"
#include "afb-api.h"
@@ -252,7 +253,7 @@ int afb_supervision_init()
/* init the apiset */
rc = afb_apiset_add(supervision_apiset, supervision_apiname,
- (struct afb_api){ .itf = &supervision_api_itf, .closure = NULL});
+ (struct afb_api_item){ .itf = &supervision_api_itf, .closure = NULL});
if (rc < 0) {
ERROR("Can't create supervision's apiset: %m");
afb_apiset_unref(supervision_apiset);
@@ -298,14 +299,14 @@ static void on_supervision_call(void *closure, struct afb_xreq *xreq)
struct json_object *args, *drop, *add, *sub, *list;
const char *api, *verb, *uuid;
struct afb_session *session;
- const struct afb_api *xapi;
- struct afb_req req;
+ const struct afb_api_item *xapi;
+ afb_req_t req;
/* search the verb */
i = (int)(sizeof verbs / sizeof *verbs);
- while(--i >= 0 && strcasecmp(verbs[i], xreq->request.verb));
+ while(--i >= 0 && strcasecmp(verbs[i], xreq->request.called_verb));
if (i < 0) {
- afb_xreq_fail_unknown_verb(xreq);
+ afb_xreq_reply_unknown_verb(xreq);
return;
}
@@ -324,32 +325,32 @@ static void on_supervision_call(void *closure, struct afb_xreq *xreq)
if (wrap_json_unpack(args, "s", &uuid))
wrap_json_unpack(args, "{ss}", "uuid", &uuid);
if (!uuid)
- afb_xreq_fail(xreq, "invalid", NULL);
+ afb_xreq_reply(xreq, NULL, "invalid", NULL);
else {
session = afb_session_search(uuid);
if (!session)
- afb_xreq_fail(xreq, "not-found", NULL);
+ afb_xreq_reply(xreq, NULL, "not-found", NULL);
else {
afb_session_close(session);
afb_session_unref(session);
afb_session_purge();
- afb_xreq_success(xreq, NULL, NULL);
+ afb_xreq_reply(xreq, NULL, NULL, NULL);
}
}
break;
case Slist:
list = json_object_new_object();
afb_session_foreach(slist, list);
- afb_xreq_success(xreq, list, NULL);
+ afb_xreq_reply(xreq, list, NULL, NULL);
break;
case Config:
- afb_xreq_success(xreq, afb_config_json(main_config), NULL);
+ afb_xreq_reply(xreq, afb_config_json(main_config), NULL, NULL);
break;
case Trace:
if (!trace)
trace = afb_trace_create(supervisor_apiname, NULL /* not bound to any session */);
- req = xreq_to_req(xreq);
+ req = xreq_to_req_x2(xreq);
add = drop = NULL;
wrap_json_unpack(args, "{s?o s?o}", "add", &add, "drop", &drop);
if (add) {
@@ -367,16 +368,16 @@ static void on_supervision_call(void *closure, struct afb_xreq *xreq)
case Do:
sub = NULL;
if (wrap_json_unpack(args, "{ss ss s?o*}", "api", &api, "verb", &verb, "args", &sub))
- afb_xreq_fail(xreq, "error", "bad request");
+ afb_xreq_reply(xreq, NULL, "error", "bad request");
else {
xapi = afb_apiset_lookup_started(main_apiset, api, 1);
if (!xapi)
- afb_xreq_fail_unknown_api(xreq);
+ afb_xreq_reply_unknown_api(xreq);
else {
afb_cred_unref(xreq->cred);
xreq->cred = NULL;
- xreq->request.api = api;
- xreq->request.verb = verb;
+ xreq->request.called_api = api;
+ xreq->request.called_verb = verb;
xreq->json = json_object_get(sub);
xapi->itf->call(xapi->closure, xreq);
json_object_put(args);
@@ -384,11 +385,11 @@ static void on_supervision_call(void *closure, struct afb_xreq *xreq)
}
break;
case Wait:
- afb_req_success(req, NULL, NULL);
+ afb_xreq_reply(xreq, NULL, NULL, NULL);
afb_debug_wait("supervisor");
break;
case Break:
- afb_req_success(req, NULL, NULL);
+ afb_xreq_reply(xreq, NULL, NULL, NULL);
afb_debug_break("supervisor");
break;
}
diff --git a/src/afb-trace.c b/src/afb-trace.c
index 5404a5af..a603951c 100644
--- a/src/afb-trace.c
+++ b/src/afb-trace.c
@@ -28,7 +28,7 @@
#include <json-c/json.h>
-#define AFB_BINDING_VERSION 0
+#define AFB_BINDING_VERSION 3
#include <afb/afb-binding.h>
#include "afb-hook.h"
@@ -74,7 +74,7 @@ struct tag {
/* struct for events */
struct event {
struct event *next; /* link to the next event */
- struct afb_evtid *evtid; /* the event */
+ struct afb_evtid *evtid; /* the event */
};
/* struct for sessions */
@@ -95,13 +95,16 @@ struct hook {
/* types of hooks */
enum trace_type
{
- Trace_Type_Xreq, /* xreq hooks */
- Trace_Type_Ditf, /* export hooks */
- Trace_Type_Svc, /* export hooks */
- Trace_Type_Evt, /* evt hooks */
- Trace_Type_Session, /* session hooks */
- Trace_Type_Global, /* global hooks */
- Trace_Type_Count /* count of types of hooks */
+ Trace_Type_Xreq, /* xreq hooks */
+ Trace_Type_Api, /* api hooks */
+ Trace_Type_Evt, /* evt hooks */
+ Trace_Type_Session, /* session hooks */
+ Trace_Type_Global, /* global hooks */
+#if !defined(REMOVE_LEGACY_TRACE)
+ Trace_Legacy_Type_Ditf, /* export hooks */
+ Trace_Legacy_Type_Svc, /* export hooks */
+#endif
+ Trace_Type_Count, /* count of types of hooks */
};
/* client data */
@@ -168,8 +171,15 @@ static struct json_object *timestamp(const struct afb_hookid *hookid)
{
char ts[50];
- snprintf(ts, sizeof ts, "%llu.%06lu", (long long unsigned)hookid->time.tv_sec, (long unsigned)(hookid->time.tv_nsec / 1000));
+ snprintf(ts, sizeof ts, "%llu.%06lu",
+ (long long unsigned)hookid->time.tv_sec,
+ (long unsigned)((hookid->time.tv_nsec + 500) / 1000));
+
+ return json_object_new_double_s(0.0f, ts); /* the real value isn't used */
+#if 0
return json_object_new_string(ts);
+ return json_object_new_double_s(0f, ts); /* the real value isn't used */
+#endif
}
/* verbosity level name or NULL */
@@ -222,38 +232,35 @@ static struct flag xreq_flags[] = { /* must be sorted by names */
{ "begin", afb_hook_flag_req_begin },
{ "common", afb_hook_flags_req_common },
{ "context", afb_hook_flags_req_context },
- { "context_get", afb_hook_flag_req_context_get },
+ { "context_get", afb_hook_flag_req_legacy_context_get },
{ "context_make", afb_hook_flag_req_context_make },
- { "context_set", afb_hook_flag_req_context_set },
+ { "context_set", afb_hook_flag_req_legacy_context_set },
{ "end", afb_hook_flag_req_end },
{ "event", afb_hook_flags_req_event },
{ "extra", afb_hook_flags_req_extra },
- { "fail", afb_hook_flag_req_fail },
{ "get", afb_hook_flag_req_get },
{ "get_application_id", afb_hook_flag_req_get_application_id },
+ { "get_client_info", afb_hook_flag_req_get_client_info },
{ "get_uid", afb_hook_flag_req_get_uid },
{ "has_permission", afb_hook_flag_req_has_permission },
{ "json", afb_hook_flag_req_json },
{ "life", afb_hook_flags_req_life },
{ "ref", afb_hook_flags_req_ref },
- { "result", afb_hook_flags_req_result },
+ { "reply", afb_hook_flag_req_reply },
{ "security", afb_hook_flags_req_security },
{ "session", afb_hook_flags_req_session },
{ "session_close", afb_hook_flag_req_session_close },
{ "session_set_LOA", afb_hook_flag_req_session_set_LOA },
- { "store", afb_hook_flag_req_store },
+ { "store", afb_hook_flag_req_legacy_store },
{ "stores", afb_hook_flags_req_stores },
{ "subcall", afb_hook_flag_req_subcall },
- { "subcall_req", afb_hook_flag_req_subcall_req },
- { "subcall_req_result", afb_hook_flag_req_subcall_req_result },
{ "subcall_result", afb_hook_flag_req_subcall_result },
{ "subcalls", afb_hook_flags_req_subcalls },
{ "subcallsync", afb_hook_flag_req_subcallsync },
{ "subcallsync_result", afb_hook_flag_req_subcallsync_result },
{ "subscribe", afb_hook_flag_req_subscribe },
- { "success", afb_hook_flag_req_success },
{ "unref", afb_hook_flag_req_unref },
- { "unstore", afb_hook_flag_req_unstore },
+ { "unstore", afb_hook_flag_req_legacy_unstore },
{ "unsubscribe", afb_hook_flag_req_unsubscribe },
{ "vverbose", afb_hook_flag_req_vverbose },
};
@@ -285,8 +292,8 @@ static void hook_xreq(void *closure, const struct afb_hookid *hookid, const stru
va_start(ap, format);
emit(closure, hookid, "request", "{si ss ss ss so* ss*}", format, ap,
"index", xreq->hookindex,
- "api", xreq->request.api,
- "verb", xreq->request.verb,
+ "api", xreq->request.called_api,
+ "verb", xreq->request.called_verb,
"action", action,
"credentials", cred,
"session", session);
@@ -295,7 +302,8 @@ static void hook_xreq(void *closure, const struct afb_hookid *hookid, const stru
static void hook_xreq_begin(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
{
- hook_xreq(closure, hookid, xreq, "begin", NULL);
+ hook_xreq(closure, hookid, xreq, "begin", "{sO?}",
+ "json", afb_xreq_unhooked_json((struct afb_xreq*)xreq));
}
static void hook_xreq_end(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq)
@@ -318,17 +326,11 @@ static void hook_xreq_get(void *closure, const struct afb_hookid *hookid, const
"path", arg.path);
}
-static void hook_xreq_success(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *obj, const char *info)
+static void hook_xreq_reply(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info)
{
- hook_xreq(closure, hookid, xreq, "success", "{sO? ss?}",
+ hook_xreq(closure, hookid, xreq, "reply", "{sO? ss? ss?}",
"result", obj,
- "info", info);
-}
-
-static void hook_xreq_fail(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *status, const char *info)
-{
- hook_xreq(closure, hookid, xreq, "fail", "{ss? ss?}",
- "status", status,
+ "error", error,
"info", info);
}
@@ -364,21 +366,21 @@ static void hook_xreq_session_set_LOA(void *closure, const struct afb_hookid *ho
"result", result);
}
-static void hook_xreq_subscribe(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_eventid *eventid, int result)
+static void hook_xreq_subscribe(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_event_x2 *event, int result)
{
hook_xreq(closure, hookid, xreq, "subscribe", "{s{ss si} si}",
"event",
- "name", afb_evt_eventid_fullname(eventid),
- "id", afb_evt_eventid_id(eventid),
+ "name", afb_evt_event_x2_fullname(event),
+ "id", afb_evt_event_x2_id(event),
"result", result);
}
-static void hook_xreq_unsubscribe(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_eventid *eventid, int result)
+static void hook_xreq_unsubscribe(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_event_x2 *event, int result)
{
hook_xreq(closure, hookid, xreq, "unsubscribe", "{s{ss? si} si}",
"event",
- "name", afb_evt_eventid_fullname(eventid),
- "id", afb_evt_eventid_id(eventid),
+ "name", afb_evt_event_x2_fullname(event),
+ "id", afb_evt_event_x2_id(event),
"result", result);
}
@@ -390,11 +392,12 @@ static void hook_xreq_subcall(void *closure, const struct afb_hookid *hookid, co
"args", args);
}
-static void hook_xreq_subcall_result(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result)
+static void hook_xreq_subcall_result(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info)
{
- hook_xreq(closure, hookid, xreq, "subcall_result", "{si sO?}",
- "status", status,
- "result", result);
+ hook_xreq(closure, hookid, xreq, "subcall_result", "{sO? ss? ss?}",
+ "object", object,
+ "error", error,
+ "info", info);
}
static void hook_xreq_subcallsync(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
@@ -405,11 +408,13 @@ static void hook_xreq_subcallsync(void *closure, const struct afb_hookid *hookid
"args", args);
}
-static void hook_xreq_subcallsync_result(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result)
+static void hook_xreq_subcallsync_result(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *object, const char *error, const char *info)
{
- hook_xreq(closure, hookid, xreq, "subcallsync_result", "{si sO?}",
+ hook_xreq(closure, hookid, xreq, "subcallsync_result", "{si sO? ss? ss?}",
"status", status,
- "result", result);
+ "object", object,
+ "error", error,
+ "info", info);
}
static void hook_xreq_vverbose(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int level, const char *file, int line, const char *func, const char *fmt, va_list args)
@@ -448,21 +453,6 @@ static void hook_xreq_unstore(void *closure, const struct afb_hookid *hookid, co
hook_xreq(closure, hookid, xreq, "unstore", NULL);
}
-static void hook_xreq_subcall_req(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
-{
- hook_xreq(closure, hookid, xreq, "subcall_req", "{ss? ss? sO?}",
- "api", api,
- "verb", verb,
- "args", args);
-}
-
-static void hook_xreq_subcall_req_result(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result)
-{
- hook_xreq(closure, hookid, xreq, "subcall_req_result", "{si sO?}",
- "status", status,
- "result", result);
-}
-
static void hook_xreq_has_permission(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *permission, int result)
{
hook_xreq(closure, hookid, xreq, "has_permission", "{ss sb}",
@@ -497,15 +487,20 @@ static void hook_xreq_get_uid(void *closure, const struct afb_hookid *hookid, co
"result", result);
}
+static void hook_xreq_get_client_info(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct json_object *result)
+{
+ hook_xreq(closure, hookid, xreq, "get_client_info", "{so}",
+ "result", result);
+}
+
static struct afb_hook_xreq_itf hook_xreq_itf = {
.hook_xreq_begin = hook_xreq_begin,
.hook_xreq_end = hook_xreq_end,
.hook_xreq_json = hook_xreq_json,
.hook_xreq_get = hook_xreq_get,
- .hook_xreq_success = hook_xreq_success,
- .hook_xreq_fail = hook_xreq_fail,
- .hook_xreq_context_get = hook_xreq_context_get,
- .hook_xreq_context_set = hook_xreq_context_set,
+ .hook_xreq_reply = hook_xreq_reply,
+ .hook_xreq_legacy_context_get = hook_xreq_context_get,
+ .hook_xreq_legacy_context_set = hook_xreq_context_set,
.hook_xreq_addref = hook_xreq_addref,
.hook_xreq_unref = hook_xreq_unref,
.hook_xreq_session_close = hook_xreq_session_close,
@@ -517,85 +512,146 @@ static struct afb_hook_xreq_itf hook_xreq_itf = {
.hook_xreq_subcallsync = hook_xreq_subcallsync,
.hook_xreq_subcallsync_result = hook_xreq_subcallsync_result,
.hook_xreq_vverbose = hook_xreq_vverbose,
- .hook_xreq_store = hook_xreq_store,
- .hook_xreq_unstore = hook_xreq_unstore,
- .hook_xreq_subcall_req = hook_xreq_subcall_req,
- .hook_xreq_subcall_req_result = hook_xreq_subcall_req_result,
+ .hook_xreq_legacy_store = hook_xreq_store,
+ .hook_xreq_legacy_unstore = hook_xreq_unstore,
.hook_xreq_has_permission = hook_xreq_has_permission,
.hook_xreq_get_application_id = hook_xreq_get_application_id,
.hook_xreq_context_make = hook_xreq_context_make,
.hook_xreq_get_uid = hook_xreq_get_uid,
+ .hook_xreq_get_client_info = hook_xreq_get_client_info,
};
/*******************************************************************************/
-/***** trace the daemon interface *****/
+/***** trace the api interface *****/
/*******************************************************************************/
-static struct flag ditf_flags[] = { /* must be sorted by names */
- { "all", afb_hook_flags_ditf_all },
- { "common", afb_hook_flags_ditf_common },
- { "event_broadcast_after", afb_hook_flag_ditf_event_broadcast_after },
- { "event_broadcast_before", afb_hook_flag_ditf_event_broadcast_before },
- { "event_make", afb_hook_flag_ditf_event_make },
- { "extra", afb_hook_flags_ditf_extra },
- { "get_event_loop", afb_hook_flag_ditf_get_event_loop },
- { "get_system_bus", afb_hook_flag_ditf_get_system_bus },
- { "get_user_bus", afb_hook_flag_ditf_get_user_bus },
- { "queue_job", afb_hook_flag_ditf_queue_job },
- { "require_api", afb_hook_flag_ditf_require_api },
- { "require_api_result", afb_hook_flag_ditf_require_api_result },
- { "rootdir_get_fd", afb_hook_flag_ditf_rootdir_get_fd },
- { "rootdir_open_locale", afb_hook_flag_ditf_rootdir_open_locale },
- { "unstore_req", afb_hook_flag_ditf_unstore_req },
- { "vverbose", afb_hook_flag_ditf_vverbose },
+#if !defined(REMOVE_LEGACY_TRACE)
+static struct flag legacy_ditf_flags[] = { /* must be sorted by names */
+ { "all", afb_hook_flags_api_ditf_all },
+ { "common", afb_hook_flags_api_ditf_common },
+ { "event_broadcast_after", afb_hook_flag_api_event_broadcast },
+ { "event_broadcast_before", afb_hook_flag_api_event_broadcast },
+ { "event_make", afb_hook_flag_api_event_make },
+ { "extra", afb_hook_flags_api_ditf_extra },
+ { "get_event_loop", afb_hook_flag_api_get_event_loop },
+ { "get_system_bus", afb_hook_flag_api_get_system_bus },
+ { "get_user_bus", afb_hook_flag_api_get_user_bus },
+ { "queue_job", afb_hook_flag_api_queue_job },
+ { "require_api", afb_hook_flag_api_require_api },
+ { "require_api_result", afb_hook_flag_api_require_api },
+ { "rootdir_get_fd", afb_hook_flag_api_rootdir_get_fd },
+ { "rootdir_open_locale", afb_hook_flag_api_rootdir_open_locale },
+ { "unstore_req", afb_hook_flag_api_legacy_unstore_req },
+ { "vverbose", afb_hook_flag_api_vverbose },
};
+static struct flag legacy_svc_flags[] = { /* must be sorted by names */
+ { "all", afb_hook_flags_api_svc_all },
+ { "call", afb_hook_flag_api_call },
+ { "call_result", afb_hook_flag_api_call },
+ { "callsync", afb_hook_flag_api_callsync },
+ { "callsync_result", afb_hook_flag_api_callsync },
+ { "on_event_after", afb_hook_flag_api_on_event },
+ { "on_event_before", afb_hook_flag_api_on_event },
+ { "start_after", afb_hook_flag_api_start },
+ { "start_before", afb_hook_flag_api_start },
+};
+
+/* get the export value for flag of 'name' */
+static int get_legacy_ditf_flag(const char *name)
+{
+ return get_flag(name, legacy_ditf_flags, (int)(sizeof legacy_ditf_flags / sizeof *legacy_ditf_flags));
+}
+
/* get the export value for flag of 'name' */
-static int get_ditf_flag(const char *name)
+static int get_legacy_svc_flag(const char *name)
{
- return get_flag(name, ditf_flags, (int)(sizeof ditf_flags / sizeof *ditf_flags));
+ return get_flag(name, legacy_svc_flags, (int)(sizeof legacy_svc_flags / sizeof *legacy_svc_flags));
}
+#endif
+
+static struct flag api_flags[] = { /* must be sorted by names */
+ { "add_alias", afb_hook_flag_api_add_alias },
+ { "all", afb_hook_flags_api_all },
+ { "api_add_verb", afb_hook_flag_api_api_add_verb },
+ { "api", afb_hook_flags_api_api },
+ { "api_del_verb", afb_hook_flag_api_api_del_verb },
+ { "api_seal", afb_hook_flag_api_api_seal },
+ { "api_set_on_event", afb_hook_flag_api_api_set_on_event },
+ { "api_set_on_init", afb_hook_flag_api_api_set_on_init },
+ { "api_set_verbs", afb_hook_flag_api_api_set_verbs },
+ { "call", afb_hook_flag_api_call },
+ { "callsync", afb_hook_flag_api_callsync },
+ { "class_provide", afb_hook_flag_api_class_provide },
+ { "class_require", afb_hook_flag_api_class_require },
+ { "common", afb_hook_flags_api_common },
+ { "delete_api", afb_hook_flag_api_delete_api },
+ { "event", afb_hook_flags_api_event },
+ { "event_broadcast", afb_hook_flag_api_event_broadcast },
+ { "event_handler_add", afb_hook_flag_api_event_handler_add },
+ { "event_handler_del", afb_hook_flag_api_event_handler_del },
+ { "event_make", afb_hook_flag_api_event_make },
+ { "extra", afb_hook_flags_api_extra },
+ { "get_event_loop", afb_hook_flag_api_get_event_loop },
+ { "get_system_bus", afb_hook_flag_api_get_system_bus },
+ { "get_user_bus", afb_hook_flag_api_get_user_bus },
+ { "legacy_unstore_req", afb_hook_flag_api_legacy_unstore_req },
+ { "new_api", afb_hook_flag_api_new_api },
+ { "on_event", afb_hook_flag_api_on_event },
+ { "on_event_handler", afb_hook_flag_api_on_event_handler },
+ { "queue_job", afb_hook_flag_api_queue_job },
+ { "require_api", afb_hook_flag_api_require_api },
+ { "rootdir_get_fd", afb_hook_flag_api_rootdir_get_fd },
+ { "rootdir_open_locale",afb_hook_flag_api_rootdir_open_locale },
+ { "start", afb_hook_flag_api_start },
+ { "vverbose", afb_hook_flag_api_vverbose },
+};
+/* get the export value for flag of 'name' */
+static int get_api_flag(const char *name)
+{
+ return get_flag(name, api_flags, (int)(sizeof api_flags / sizeof *api_flags));
+}
-static void hook_ditf(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *action, const char *format, ...)
+static void hook_api(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *action, const char *format, ...)
{
va_list ap;
va_start(ap, format);
- emit(closure, hookid, "daemon", "{ss ss}", format, ap,
+ emit(closure, hookid, "api", "{ss ss}", format, ap,
"api", afb_export_apiname(export),
"action", action);
va_end(ap);
}
-static void hook_ditf_event_broadcast_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object)
+static void hook_api_event_broadcast_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object)
{
- hook_ditf(closure, hookid, export, "event_broadcast_before", "{ss sO*}",
+ hook_api(closure, hookid, export, "event_broadcast_before", "{ss sO?}",
"name", name, "data", object);
}
-static void hook_ditf_event_broadcast_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object, int result)
+static void hook_api_event_broadcast_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct json_object *object, int result)
{
- hook_ditf(closure, hookid, export, "event_broadcast_after", "{ss sO* si}",
+ hook_api(closure, hookid, export, "event_broadcast_after", "{ss sO? si}",
"name", name, "data", object, "result", result);
}
-static void hook_ditf_get_event_loop(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_event *result)
+static void hook_api_get_event_loop(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_event *result)
{
- hook_ditf(closure, hookid, export, "get_event_loop", NULL);
+ hook_api(closure, hookid, export, "get_event_loop", NULL);
}
-static void hook_ditf_get_user_bus(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result)
+static void hook_api_get_user_bus(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result)
{
- hook_ditf(closure, hookid, export, "get_user_bus", NULL);
+ hook_api(closure, hookid, export, "get_user_bus", NULL);
}
-static void hook_ditf_get_system_bus(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result)
+static void hook_api_get_system_bus(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct sd_bus *result)
{
- hook_ditf(closure, hookid, export, "get_system_bus", NULL);
+ hook_api(closure, hookid, export, "get_system_bus", NULL);
}
-static void hook_ditf_vverbose(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
+static void hook_api_vverbose(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
{
struct json_object *pos;
int len;
@@ -612,7 +668,7 @@ static void hook_ditf_vverbose(void *closure, const struct afb_hookid *hookid, c
if (file)
wrap_json_pack(&pos, "{ss si ss*}", "file", file, "line", line, "function", function);
- hook_ditf(closure, hookid, export, "vverbose", "{si ss* ss? so*}",
+ hook_api(closure, hookid, export, "vverbose", "{si ss* ss? so*}",
"level", level,
"type", verbosity_level_name(level),
len < 0 ? "format" : "message", len < 0 ? fmt : msg,
@@ -621,13 +677,13 @@ static void hook_ditf_vverbose(void *closure, const struct afb_hookid *hookid, c
free(msg);
}
-static void hook_ditf_event_make(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_eventid *result)
+static void hook_api_event_make(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_event_x2 *result)
{
- hook_ditf(closure, hookid, export, "event_make", "{ss ss si}",
- "name", name, "event", afb_evt_eventid_fullname(result), "id", afb_evt_eventid_id(result));
+ hook_api(closure, hookid, export, "event_make", "{ss ss si}",
+ "name", name, "event", afb_evt_event_x2_fullname(result), "id", afb_evt_event_x2_id(result));
}
-static void hook_ditf_rootdir_get_fd(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
+static void hook_api_rootdir_get_fd(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
{
char path[PATH_MAX];
@@ -636,12 +692,12 @@ static void hook_ditf_rootdir_get_fd(void *closure, const struct afb_hookid *hoo
readlink(path, path, sizeof path);
}
- hook_ditf(closure, hookid, export, "rootdir_get_fd", "{ss}",
+ hook_api(closure, hookid, export, "rootdir_get_fd", "{ss}",
result < 0 ? "path" : "error",
result < 0 ? strerror(errno) : path);
}
-static void hook_ditf_rootdir_open_locale(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *filename, int flags, const char *locale, int result)
+static void hook_api_rootdir_open_locale(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *filename, int flags, const char *locale, int result)
{
char path[PATH_MAX];
@@ -650,7 +706,7 @@ static void hook_ditf_rootdir_open_locale(void *closure, const struct afb_hookid
readlink(path, path, sizeof path);
}
- hook_ditf(closure, hookid, export, "rootdir_open_locale", "{ss si ss* ss}",
+ hook_api(closure, hookid, export, "rootdir_open_locale", "{ss si ss* ss}",
"file", filename,
"flags", flags,
"locale", locale,
@@ -658,130 +714,187 @@ static void hook_ditf_rootdir_open_locale(void *closure, const struct afb_hookid
result < 0 ? strerror(errno) : path);
}
-static void hook_ditf_queue_job(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result)
+static void hook_api_queue_job(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout, int result)
{
- hook_ditf(closure, hookid, export, "queue_job", "{ss}", "result", result);
+ hook_api(closure, hookid, export, "queue_job", "{ss}", "result", result);
}
-static void hook_ditf_unstore_req(void * closure, const struct afb_hookid *hookid, const struct afb_export *export, struct afb_stored_req *sreq)
+static void hook_api_unstore_req(void * closure, const struct afb_hookid *hookid, const struct afb_export *export, struct afb_stored_req *sreq)
{
- hook_ditf(closure, hookid, export, "unstore_req", NULL);
+ hook_api(closure, hookid, export, "unstore_req", NULL);
}
-static void hook_ditf_require_api(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized)
+static void hook_api_require_api(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized)
{
- hook_ditf(closure, hookid, export, "require_api", "{ss sb}", "name", name, "initialized", initialized);
+ hook_api(closure, hookid, export, "require_api", "{ss sb}", "name", name, "initialized", initialized);
}
-static void hook_ditf_require_api_result(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized, int result)
+static void hook_api_require_api_result(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, int initialized, int result)
{
- hook_ditf(closure, hookid, export, "require_api_result", "{ss sb si}", "name", name, "initialized", initialized, "result", result);
+ hook_api(closure, hookid, export, "require_api_result", "{ss sb si}", "name", name, "initialized", initialized, "result", result);
}
-static struct afb_hook_ditf_itf hook_ditf_itf = {
- .hook_ditf_event_broadcast_before = hook_ditf_event_broadcast_before,
- .hook_ditf_event_broadcast_after = hook_ditf_event_broadcast_after,
- .hook_ditf_get_event_loop = hook_ditf_get_event_loop,
- .hook_ditf_get_user_bus = hook_ditf_get_user_bus,
- .hook_ditf_get_system_bus = hook_ditf_get_system_bus,
- .hook_ditf_vverbose = hook_ditf_vverbose,
- .hook_ditf_event_make = hook_ditf_event_make,
- .hook_ditf_rootdir_get_fd = hook_ditf_rootdir_get_fd,
- .hook_ditf_rootdir_open_locale = hook_ditf_rootdir_open_locale,
- .hook_ditf_queue_job = hook_ditf_queue_job,
- .hook_ditf_unstore_req = hook_ditf_unstore_req,
- .hook_ditf_require_api = hook_ditf_require_api,
- .hook_ditf_require_api_result = hook_ditf_require_api_result
-};
+static void hook_api_add_alias_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *alias, int result)
+{
+ hook_api(closure, hookid, export, "add_alias", "{si ss? ss}", "status", result, "api", api, "alias", alias);
+}
-/*******************************************************************************/
-/***** trace the services *****/
-/*******************************************************************************/
+static void hook_api_start_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export)
+{
+ hook_api(closure, hookid, export, "start_before", NULL);
+}
-static struct flag svc_flags[] = { /* must be sorted by names */
- { "all", afb_hook_flags_svc_all },
- { "call", afb_hook_flag_svc_call },
- { "call_result", afb_hook_flag_svc_call_result },
- { "callsync", afb_hook_flag_svc_callsync },
- { "callsync_result", afb_hook_flag_svc_callsync_result },
- { "on_event_after", afb_hook_flag_svc_on_event_after },
- { "on_event_before", afb_hook_flag_svc_on_event_before },
- { "start_after", afb_hook_flag_svc_start_after },
- { "start_before", afb_hook_flag_svc_start_before },
-};
+static void hook_api_start_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status)
+{
+ hook_api(closure, hookid, export, "start_after", "{si}", "result", status);
+}
-/* get the export value for flag of 'name' */
-static int get_svc_flag(const char *name)
+static void hook_api_on_event_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int evtid, struct json_object *object)
{
- return get_flag(name, svc_flags, (int)(sizeof svc_flags / sizeof *svc_flags));
+ hook_api(closure, hookid, export, "on_event_before", "{ss si sO*}",
+ "event", event, "id", evtid, "data", object);
}
-static void hook_svc(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *action, const char *format, ...)
+static void hook_api_on_event_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int evtid, struct json_object *object)
{
- va_list ap;
+ hook_api(closure, hookid, export, "on_event_after", "{ss si sO?}",
+ "event", event, "id", evtid, "data", object);
+}
- va_start(ap, format);
- emit(closure, hookid, "service", "{ss ss}", format, ap,
- "api", afb_export_apiname(export),
- "action", action);
- va_end(ap);
+static void hook_api_call(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
+{
+ hook_api(closure, hookid, export, "call", "{ss ss sO?}",
+ "api", api, "verb", verb, "args", args);
}
-static void hook_svc_start_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export)
+static void hook_api_call_result(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, struct json_object *object, const char *error, const char *info)
{
- hook_svc(closure, hookid, export, "start_before", NULL);
+ hook_api(closure, hookid, export, "call_result", "{sO? ss? ss?}",
+ "object", object, "error", error, "info", info);
}
-static void hook_svc_start_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status)
+static void hook_api_callsync(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
{
- hook_svc(closure, hookid, export, "start_after", "{si}", "result", status);
+ hook_api(closure, hookid, export, "callsync", "{ss ss sO?}",
+ "api", api, "verb", verb, "args", args);
}
-static void hook_svc_on_event_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int evtid, struct json_object *object)
+static void hook_api_callsync_result(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *object, const char *error, const char *info)
{
- hook_svc(closure, hookid, export, "on_event_before", "{ss si sO*}",
- "event", event, "id", evtid, "data", object);
+ hook_api(closure, hookid, export, "callsync_result", "{si sO? ss? ss?}",
+ "status", status, "object", object, "error", error, "info", info);
}
-static void hook_svc_on_event_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *event, int evtid, struct json_object *object)
+static void hook_api_new_api_before(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *info, int noconcurrency)
{
- hook_svc(closure, hookid, export, "on_event_after", "{ss si sO*}",
- "event", event, "id", evtid, "data", object);
+ hook_api(closure, hookid, export, "new_api.before", "{ss ss? sb}",
+ "api", api, "info", info, "noconcurrency", noconcurrency);
}
-static void hook_svc_call(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
+static void hook_api_new_api_after(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *api)
{
- hook_svc(closure, hookid, export, "call", "{ss ss sO*}",
- "api", api, "verb", verb, "args", args);
+ hook_api(closure, hookid, export, "new_api.after", "{si ss}",
+ "status", result, "api", api);
}
-static void hook_svc_call_result(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result)
+static void hook_api_api_set_verbs_v2(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const struct afb_verb_v2 *verbs)
{
- hook_svc(closure, hookid, export, "call_result", "{si sO*}",
- "status", status, "result", result);
+ hook_api(closure, hookid, export, "set_verbs_v2", "{si}", "status", result);
}
-static void hook_svc_callsync(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *api, const char *verb, struct json_object *args)
+static void hook_api_api_set_verbs_v3(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const struct afb_verb_v3 *verbs)
{
- hook_svc(closure, hookid, export, "callsync", "{ss ss sO*}",
- "api", api, "verb", verb, "args", args);
+ hook_api(closure, hookid, export, "set_verbs_v3", "{si}", "status", result);
+}
+
+
+static void hook_api_api_add_verb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *verb, const char *info, int glob)
+{
+ hook_api(closure, hookid, export, "add_verb", "{si ss ss? sb}", "status", result, "verb", verb, "info", info, "glob", glob);
+}
+
+static void hook_api_api_del_verb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *verb)
+{
+ hook_api(closure, hookid, export, "del_verb", "{si ss}", "status", result, "verb", verb);
+}
+
+static void hook_api_api_set_on_event(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
+{
+ hook_api(closure, hookid, export, "set_on_event", "{si}", "status", result);
}
-static void hook_svc_callsync_result(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int status, struct json_object *result)
+static void hook_api_api_set_on_init(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
{
- hook_svc(closure, hookid, export, "callsync_result", "{si sO*}",
- "status", status, "result", result);
+ hook_api(closure, hookid, export, "set_on_init", "{si}", "status", result);
}
-static struct afb_hook_svc_itf hook_svc_itf = {
- .hook_svc_start_before = hook_svc_start_before,
- .hook_svc_start_after = hook_svc_start_after,
- .hook_svc_on_event_before = hook_svc_on_event_before,
- .hook_svc_on_event_after = hook_svc_on_event_after,
- .hook_svc_call = hook_svc_call,
- .hook_svc_call_result = hook_svc_call_result,
- .hook_svc_callsync = hook_svc_callsync,
- .hook_svc_callsync_result = hook_svc_callsync_result
+static void hook_api_api_seal(void *closure, const struct afb_hookid *hookid, const struct afb_export *export)
+{
+ hook_api(closure, hookid, export, "seal", NULL);
+}
+
+static void hook_api_event_handler_add(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *pattern)
+{
+ hook_api(closure, hookid, export, "event_handler_add", "{si ss?}", "status", result, "pattern", pattern);
+}
+
+static void hook_api_event_handler_del(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *pattern)
+{
+ hook_api(closure, hookid, export, "event_handler_del", "{si ss?}", "status", result, "pattern", pattern);
+}
+
+static void hook_api_class_provide(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *name)
+{
+ hook_api(closure, hookid, export, "class_provide", "{si ss?}", "status", result, "name", name);
+}
+
+static void hook_api_class_require(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result, const char *name)
+{
+ hook_api(closure, hookid, export, "class_require", "{si ss?}", "status", result, "name", name);
+}
+
+static void hook_api_delete_api(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
+{
+ hook_api(closure, hookid, export, "delete_api", "{si}", "status", result);
+}
+
+static struct afb_hook_api_itf hook_api_itf = {
+ .hook_api_event_broadcast_before = hook_api_event_broadcast_before,
+ .hook_api_event_broadcast_after = hook_api_event_broadcast_after,
+ .hook_api_get_event_loop = hook_api_get_event_loop,
+ .hook_api_get_user_bus = hook_api_get_user_bus,
+ .hook_api_get_system_bus = hook_api_get_system_bus,
+ .hook_api_vverbose = hook_api_vverbose,
+ .hook_api_event_make = hook_api_event_make,
+ .hook_api_rootdir_get_fd = hook_api_rootdir_get_fd,
+ .hook_api_rootdir_open_locale = hook_api_rootdir_open_locale,
+ .hook_api_queue_job = hook_api_queue_job,
+ .hook_api_legacy_unstore_req = hook_api_unstore_req,
+ .hook_api_require_api = hook_api_require_api,
+ .hook_api_require_api_result = hook_api_require_api_result,
+ .hook_api_add_alias = hook_api_add_alias_cb,
+ .hook_api_start_before = hook_api_start_before,
+ .hook_api_start_after = hook_api_start_after,
+ .hook_api_on_event_before = hook_api_on_event_before,
+ .hook_api_on_event_after = hook_api_on_event_after,
+ .hook_api_call = hook_api_call,
+ .hook_api_call_result = hook_api_call_result,
+ .hook_api_callsync = hook_api_callsync,
+ .hook_api_callsync_result = hook_api_callsync_result,
+ .hook_api_new_api_before = hook_api_new_api_before,
+ .hook_api_new_api_after = hook_api_new_api_after,
+ .hook_api_api_set_verbs_v2 = hook_api_api_set_verbs_v2,
+ .hook_api_api_set_verbs_v3 = hook_api_api_set_verbs_v3,
+ .hook_api_api_add_verb = hook_api_api_add_verb,
+ .hook_api_api_del_verb = hook_api_api_del_verb,
+ .hook_api_api_set_on_event = hook_api_api_set_on_event,
+ .hook_api_api_set_on_init = hook_api_api_set_on_init,
+ .hook_api_api_seal = hook_api_api_seal,
+ .hook_api_event_handler_add = hook_api_event_handler_add,
+ .hook_api_event_handler_del = hook_api_event_handler_del,
+ .hook_api_class_provide = hook_api_class_provide,
+ .hook_api_class_require = hook_api_class_require,
+ .hook_api_delete_api = hook_api_delete_api,
};
/*******************************************************************************/
@@ -1016,17 +1129,11 @@ abstracting[Trace_Type_Count] =
.unref = (void(*)(void*))afb_hook_unref_xreq,
.get_flag = get_xreq_flag
},
- [Trace_Type_Ditf] =
- {
- .name = "daemon",
- .unref = (void(*)(void*))afb_hook_unref_ditf,
- .get_flag = get_ditf_flag
- },
- [Trace_Type_Svc] =
+ [Trace_Type_Api] =
{
- .name = "service",
- .unref = (void(*)(void*))afb_hook_unref_svc,
- .get_flag = get_svc_flag
+ .name = "api",
+ .unref = (void(*)(void*))afb_hook_unref_api,
+ .get_flag = get_api_flag
},
[Trace_Type_Evt] =
{
@@ -1046,6 +1153,20 @@ abstracting[Trace_Type_Count] =
.unref = (void(*)(void*))afb_hook_unref_global,
.get_flag = get_global_flag
},
+#if !defined(REMOVE_LEGACY_TRACE)
+ [Trace_Legacy_Type_Ditf] =
+ {
+ .name = "daemon",
+ .unref = (void(*)(void*))afb_hook_unref_api,
+ .get_flag = get_legacy_ditf_flag
+ },
+ [Trace_Legacy_Type_Svc] =
+ {
+ .name = "service",
+ .unref = (void(*)(void*))afb_hook_unref_api,
+ .get_flag = get_legacy_svc_flag
+ },
+#endif
};
/*******************************************************************************/
@@ -1242,7 +1363,7 @@ static void trace_attach_hook(struct afb_trace *trace, struct hook *hook, enum t
struct context
{
struct afb_trace *trace;
- struct afb_req req;
+ afb_req_t req;
char *errors;
};
@@ -1252,13 +1373,12 @@ struct desc
const char *name;
const char *tag;
const char *uuid;
- const char *api;
- const char *verb;
+ const char *apiname;
+ const char *verbname;
const char *pattern;
int flags[Trace_Type_Count];
};
-
static void addhook(struct desc *desc, enum trace_type type)
{
struct hook *hook;
@@ -1299,15 +1419,12 @@ static void addhook(struct desc *desc, enum trace_type type)
return;
}
}
- hook->handler = afb_hook_create_xreq(desc->api, desc->verb, session,
+ hook->handler = afb_hook_create_xreq(desc->apiname, desc->verbname, session,
desc->flags[type], &hook_xreq_itf, hook);
afb_session_unref(session);
break;
- case Trace_Type_Ditf:
- hook->handler = afb_hook_create_ditf(desc->api, desc->flags[type], &hook_ditf_itf, hook);
- break;
- case Trace_Type_Svc:
- hook->handler = afb_hook_create_svc(desc->api, desc->flags[type], &hook_svc_itf, hook);
+ case Trace_Type_Api:
+ hook->handler = afb_hook_create_api(desc->apiname, desc->flags[type], &hook_api_itf, hook);
break;
case Trace_Type_Evt:
hook->handler = afb_hook_create_evt(desc->pattern, desc->flags[type], &hook_evt_itf, hook);
@@ -1328,7 +1445,7 @@ static void addhook(struct desc *desc, enum trace_type type)
}
/* attach and activate the hook */
- afb_req_subscribe(desc->context->req, afb_evt_event_from_evtid(hook->event->evtid));
+ afb_req_subscribe(desc->context->req, afb_evt_event_x2_from_evtid(hook->event->evtid));
trace_attach_hook(trace, hook, type);
}
@@ -1336,6 +1453,11 @@ static void addhooks(struct desc *desc)
{
int i;
+#if !defined(REMOVE_LEGACY_TRACE)
+ desc->flags[Trace_Type_Api] |= desc->flags[Trace_Legacy_Type_Ditf] | desc->flags[Trace_Legacy_Type_Svc];
+ desc->flags[Trace_Legacy_Type_Ditf] = desc->flags[Trace_Legacy_Type_Svc] = 0;
+#endif
+
for (i = 0 ; i < Trace_Type_Count ; i++) {
if (desc->flags[i])
addhook(desc, i);
@@ -1368,14 +1490,21 @@ static void add_xreq_flags(void *closure, struct json_object *object)
add_flags(closure, object, Trace_Type_Xreq);
}
-static void add_ditf_flags(void *closure, struct json_object *object)
+#if !defined(REMOVE_LEGACY_TRACE)
+static void legacy_add_ditf_flags(void *closure, struct json_object *object)
+{
+ add_flags(closure, object, Trace_Legacy_Type_Ditf);
+}
+
+static void legacy_add_svc_flags(void *closure, struct json_object *object)
{
- add_flags(closure, object, Trace_Type_Ditf);
+ add_flags(closure, object, Trace_Legacy_Type_Svc);
}
+#endif
-static void add_svc_flags(void *closure, struct json_object *object)
+static void add_api_flags(void *closure, struct json_object *object)
{
- add_flags(closure, object, Trace_Type_Svc);
+ add_flags(closure, object, Trace_Type_Api);
}
static void add_evt_flags(void *closure, struct json_object *object)
@@ -1398,21 +1527,30 @@ static void add(void *closure, struct json_object *object)
{
int rc;
struct desc desc;
- struct json_object *request, *event, *daemon, *service, *sub, *global, *session;
+ struct json_object *request, *event, *sub, *global, *session, *api;
+#if !defined(REMOVE_LEGACY_TRACE)
+ struct json_object *daemon, *service;
+#endif
memcpy (&desc, closure, sizeof desc);
- request = event = daemon = service = sub = global = session = NULL;
+ request = event = sub = global = session = api = NULL;
+#if !defined(REMOVE_LEGACY_TRACE)
+ daemon = service = NULL;
+#endif
- rc = wrap_json_unpack(object, "{s?s s?s s?s s?s s?s s?s s?o s?o s?o s?o s?o s?o}",
+ rc = wrap_json_unpack(object, "{s?s s?s s?s s?s s?s s?s s?o s?o s?o s?o s?o s?o s?o}",
"name", &desc.name,
"tag", &desc.tag,
- "api", &desc.api,
- "verb", &desc.verb,
+ "apiname", &desc.apiname,
+ "verbname", &desc.verbname,
"uuid", &desc.uuid,
"pattern", &desc.pattern,
+ "api", &api,
"request", &request,
+#if !defined(REMOVE_LEGACY_TRACE)
"daemon", &daemon,
"service", &service,
+#endif
"event", &event,
"session", &session,
"global", &global,
@@ -1420,11 +1558,11 @@ static void add(void *closure, struct json_object *object)
if (!rc) {
/* replace stars */
- if (desc.api && desc.api[0] == '*' && !desc.api[1])
- desc.api = NULL;
+ if (desc.apiname && desc.apiname[0] == '*' && !desc.apiname[1])
+ desc.apiname = NULL;
- if (desc.verb && desc.verb[0] == '*' && !desc.verb[1])
- desc.verb = NULL;
+ if (desc.verbname && desc.verbname[0] == '*' && !desc.verbname[1])
+ desc.verbname = NULL;
if (desc.uuid && desc.uuid[0] == '*' && !desc.uuid[1])
desc.uuid = NULL;
@@ -1433,11 +1571,16 @@ static void add(void *closure, struct json_object *object)
if (request)
wrap_json_optarray_for_all(request, add_xreq_flags, &desc);
+ if (api)
+ wrap_json_optarray_for_all(api, add_api_flags, &desc);
+
+#if !defined(REMOVE_LEGACY_TRACE)
if (daemon)
- wrap_json_optarray_for_all(daemon, add_ditf_flags, &desc);
+ wrap_json_optarray_for_all(daemon, legacy_add_ditf_flags, &desc);
if (service)
- wrap_json_optarray_for_all(service, add_svc_flags, &desc);
+ wrap_json_optarray_for_all(service, legacy_add_svc_flags, &desc);
+#endif
if (event)
wrap_json_optarray_for_all(event, add_evt_flags, &desc);
@@ -1562,7 +1705,7 @@ void afb_trace_unref(struct afb_trace *trace)
}
/* add traces */
-int afb_trace_add(struct afb_req req, struct json_object *args, struct afb_trace *trace)
+int afb_trace_add(afb_req_t req, struct json_object *args, struct afb_trace *trace)
{
struct context context;
struct desc desc;
@@ -1587,7 +1730,7 @@ int afb_trace_add(struct afb_req req, struct json_object *args, struct afb_trace
}
/* drop traces */
-extern int afb_trace_drop(struct afb_req req, struct json_object *args, struct afb_trace *trace)
+extern int afb_trace_drop(afb_req_t req, struct json_object *args, struct afb_trace *trace)
{
int rc;
struct context context;
diff --git a/src/afb-trace.h b/src/afb-trace.h
index 5056fb25..0371546f 100644
--- a/src/afb-trace.h
+++ b/src/afb-trace.h
@@ -25,7 +25,7 @@ extern struct afb_trace *afb_trace_create(const char *api, struct afb_session *b
extern void afb_trace_addref(struct afb_trace *trace);
extern void afb_trace_unref(struct afb_trace *trace);
-extern int afb_trace_add(struct afb_req req, struct json_object *args, struct afb_trace *trace);
-extern int afb_trace_drop(struct afb_req req, struct json_object *args, struct afb_trace *trace);
+extern int afb_trace_add(afb_req_t req, struct json_object *args, struct afb_trace *trace);
+extern int afb_trace_drop(afb_req_t req, struct json_object *args, struct afb_trace *trace);
diff --git a/src/afb-ws-json1.c b/src/afb-ws-json1.c
index 315bee8e..95167b5f 100644
--- a/src/afb-ws-json1.c
+++ b/src/afb-ws-json1.c
@@ -49,7 +49,7 @@ static void aws_on_event(struct afb_ws_json1 *ws, const char *event, int eventid
/* predeclaration of wsreq callbacks */
static void wsreq_destroy(struct afb_xreq *xreq);
-static void wsreq_reply(struct afb_xreq *xreq, int status, json_object *obj);
+static void wsreq_reply(struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info);
/* declaration of websocket structure */
struct afb_ws_json1
@@ -194,8 +194,8 @@ static void aws_on_call(struct afb_ws_json1 *ws, const char *api, const char *ve
afb_wsj1_msg_addref(msg);
wsreq->msgj1 = msg;
wsreq->xreq.cred = afb_cred_addref(ws->cred);
- wsreq->xreq.request.api = api;
- wsreq->xreq.request.verb = verb;
+ wsreq->xreq.request.called_api = api;
+ wsreq->xreq.request.called_verb = verb;
wsreq->xreq.json = afb_wsj1_msg_object_j(wsreq->msgj1);
wsreq->aws = afb_ws_json1_addref(ws);
wsreq->xreq.listener = wsreq->aws->listener;
@@ -228,13 +228,17 @@ static void wsreq_destroy(struct afb_xreq *xreq)
free(wsreq);
}
-static void wsreq_reply(struct afb_xreq *xreq, int status, json_object *obj)
+static void wsreq_reply(struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info)
{
struct afb_wsreq *wsreq = CONTAINER_OF_XREQ(struct afb_wsreq, xreq);
int rc;
+ struct json_object *reply;
- rc = (status < 0 ? afb_wsj1_reply_error_j : afb_wsj1_reply_ok_j)(
- wsreq->msgj1, obj, afb_context_sent_token(&wsreq->xreq.context));
+ /* create the reply */
+ reply = afb_msg_json_reply(object, error, info, &xreq->context);
+
+ rc = (error ? afb_wsj1_reply_error_j : afb_wsj1_reply_ok_j)(
+ wsreq->msgj1, reply, afb_context_sent_token(&wsreq->xreq.context));
if (rc)
ERROR("Can't send reply: %m");
}
diff --git a/src/afb-xreq.c b/src/afb-xreq.c
index 582e9b72..8f246b3c 100644
--- a/src/afb-xreq.c
+++ b/src/afb-xreq.c
@@ -21,22 +21,26 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <stdarg.h>
#include <json-c/json.h>
+
#include <afb/afb-binding-v1.h>
#include <afb/afb-binding-v2.h>
-#include <afb/afb-request.h>
+#include <afb/afb-binding-v3.h>
+#include <afb/afb-req-x2.h>
+#include "afb-api.h"
+#include "afb-apiset.h"
+#include "afb-auth.h"
+#include "afb-calls.h"
#include "afb-context.h"
-#include "afb-xreq.h"
#include "afb-evt.h"
-#include "afb-msg-json.h"
#include "afb-cred.h"
#include "afb-hook.h"
-#include "afb-api.h"
-#include "afb-api-dyn.h"
-#include "afb-apiset.h"
-#include "afb-auth.h"
+#include "afb-msg-json.h"
+#include "afb-xreq.h"
+
#include "jobs.h"
#include "verbose.h"
@@ -45,7 +49,7 @@
static void xreq_finalize(struct afb_xreq *xreq)
{
if (!xreq->replied)
- afb_xreq_fail(xreq, "error", "no reply");
+ afb_xreq_reply(xreq, NULL, "error", "no reply");
if (xreq->hookflags)
afb_hook_xreq_end(xreq);
if (xreq->caller)
@@ -66,274 +70,22 @@ inline void afb_xreq_unhooked_unref(struct afb_xreq *xreq)
/******************************************************************************/
-struct subcall
-{
- struct afb_xreq xreq;
-
- void (*completion)(struct subcall*, int, struct json_object*);
-
- union {
- struct {
- struct jobloop *jobloop;
- struct json_object *result;
- int status;
- };
- struct {
- union {
- void (*callback)(void*, int, struct json_object*);
- void (*callback_req)(void*, int, struct json_object*, struct afb_req);
- void (*callback_request)(void*, int, struct json_object*, struct afb_request*);
- };
- void *closure;
- };
- };
-};
-
-static int subcall_subscribe_cb(struct afb_xreq *xreq, struct afb_eventid *eventid)
-{
- struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq);
-
- return afb_xreq_subscribe(subcall->xreq.caller, eventid);
-}
-
-static int subcall_unsubscribe_cb(struct afb_xreq *xreq, struct afb_eventid *eventid)
-{
- struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq);
-
- return afb_xreq_unsubscribe(subcall->xreq.caller, eventid);
-}
-
-static void subcall_reply_cb(struct afb_xreq *xreq, int status, struct json_object *result)
-{
- struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq);
-
- subcall->completion(subcall, status, result);
- json_object_put(result);
- afb_xreq_unhooked_unref(&subcall->xreq);
-}
-
-static void subcall_destroy_cb(struct afb_xreq *xreq)
-{
- struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq);
-
- json_object_put(subcall->xreq.json);
- afb_cred_unref(subcall->xreq.cred);
- free(subcall);
-}
-
-const struct afb_xreq_query_itf afb_xreq_subcall_itf = {
- .reply = subcall_reply_cb,
- .unref = subcall_destroy_cb,
- .subscribe = subcall_subscribe_cb,
- .unsubscribe = subcall_unsubscribe_cb
-};
-
-static struct subcall *subcall_alloc(
- struct afb_xreq *caller,
- const char *api,
- const char *verb,
- struct json_object *args
-)
-{
- struct subcall *subcall;
- size_t lenapi, lenverb;
- char *copy;
-
- lenapi = 1 + strlen(api);
- lenverb = 1 + strlen(verb);
- subcall = malloc(lenapi + lenverb + sizeof *subcall);
- if (!subcall)
- ERROR("out of memory");
- else {
- copy = (char*)&subcall[1];
- memcpy(copy, api, lenapi);
- api = copy;
- copy = &copy[lenapi];
- memcpy(copy, verb, lenverb);
- verb = copy;
-
- afb_xreq_init(&subcall->xreq, &afb_xreq_subcall_itf);
- afb_context_subinit(&subcall->xreq.context, &caller->context);
- subcall->xreq.cred = afb_cred_addref(caller->cred);
- subcall->xreq.json = args;
- subcall->xreq.request.api = api;
- subcall->xreq.request.verb = verb;
- subcall->xreq.caller = caller;
- afb_xreq_unhooked_addref(caller);
- }
- return subcall;
-}
-
-
-static void subcall_on_reply(struct subcall *subcall, int status, struct json_object *result)
-{
- subcall->callback(subcall->closure, status, result);
-}
-
-static void subcall_req_on_reply(struct subcall *subcall, int status, struct json_object *result)
-{
- subcall->callback_req(subcall->closure, status, result, xreq_to_req(subcall->xreq.caller));
-}
-
-static void subcall_request_on_reply(struct subcall *subcall, int status, struct json_object *result)
-{
- subcall->callback_request(subcall->closure, status, result, xreq_to_request(subcall->xreq.caller));
-}
-
-static void subcall_hooked_on_reply(struct subcall *subcall, int status, struct json_object *result)
-{
- afb_hook_xreq_subcall_result(subcall->xreq.caller, status, result);
- subcall_on_reply(subcall, status, result);
-}
-
-static void subcall_req_hooked_on_reply(struct subcall *subcall, int status, struct json_object *result)
-{
- afb_hook_xreq_subcall_req_result(subcall->xreq.caller, status, result);
- subcall_req_on_reply(subcall, status, result);
-}
-
-static void subcall_request_hooked_on_reply(struct subcall *subcall, int status, struct json_object *result)
-{
- afb_hook_xreq_subcall_result(subcall->xreq.caller, status, result);
- subcall_request_on_reply(subcall, status, result);
-}
-
-static void subcall_reply_direct_cb(void *closure, int status, struct json_object *result)
+struct json_object *afb_xreq_unhooked_json(struct afb_xreq *xreq)
{
- struct afb_xreq *xreq = closure;
-
- if (xreq->replied) {
- ERROR("subcall replied more than one time!!");
- json_object_put(result);
- } else {
- xreq->replied = 1;
- subcall_reply_cb(xreq, status, result);
- }
-}
-
-static void subcall_process(struct subcall *subcall, void (*completion)(struct subcall*, int, struct json_object*))
-{
- subcall->completion = completion;
- if (subcall->xreq.caller->queryitf->subcall) {
- subcall->xreq.caller->queryitf->subcall(
- subcall->xreq.caller, subcall->xreq.request.api, subcall->xreq.request.verb,
- subcall->xreq.json, subcall_reply_direct_cb, &subcall->xreq);
- } else {
- afb_xreq_unhooked_addref(&subcall->xreq);
- afb_xreq_process(&subcall->xreq, subcall->xreq.caller->apiset);
- }
-}
-
-static void subcall(struct subcall *subcall, void (*callback)(void*, int, struct json_object*), void *cb_closure)
-{
- subcall->callback = callback;
- subcall->closure = cb_closure;
- subcall_process(subcall, subcall_on_reply);
-}
-
-static void subcall_req(struct subcall *subcall, void (*callback)(void*, int, struct json_object*, struct afb_req), void *cb_closure)
-{
- subcall->callback_req = callback;
- subcall->closure = cb_closure;
- subcall_process(subcall, subcall_req_on_reply);
-}
-
-static void subcall_request(struct subcall *subcall, void (*callback)(void*, int, struct json_object*, struct afb_request*), void *cb_closure)
-{
- subcall->callback_request = callback;
- subcall->closure = cb_closure;
- subcall_process(subcall, subcall_request_on_reply);
-}
-
-static void subcall_hooked(struct subcall *subcall, void (*callback)(void*, int, struct json_object*), void *cb_closure)
-{
- subcall->callback = callback;
- subcall->closure = cb_closure;
- subcall_process(subcall, subcall_hooked_on_reply);
-}
-
-static void subcall_req_hooked(struct subcall *subcall, void (*callback)(void*, int, struct json_object*, struct afb_req), void *cb_closure)
-{
- subcall->callback_req = callback;
- subcall->closure = cb_closure;
- subcall_process(subcall, subcall_req_hooked_on_reply);
-}
-
-static void subcall_request_hooked(struct subcall *subcall, void (*callback)(void*, int, struct json_object*, struct afb_request*), void *cb_closure)
-{
- subcall->callback_request = callback;
- subcall->closure = cb_closure;
- subcall_process(subcall, subcall_request_hooked_on_reply);
-}
-
-static void subcall_sync_leave(struct subcall *subcall)
-{
- struct jobloop *jobloop = __atomic_exchange_n(&subcall->jobloop, NULL, __ATOMIC_RELAXED);
- if (jobloop)
- jobs_leave(jobloop);
-}
-
-static void subcall_sync_reply(struct subcall *subcall, int status, struct json_object *result)
-{
- subcall->status = status;
- subcall->result = json_object_get(result);
- subcall_sync_leave(subcall);
-}
-
-static void subcall_sync_enter(int signum, void *closure, struct jobloop *jobloop)
-{
- struct subcall *subcall = closure;
-
- if (!signum) {
- subcall->jobloop = jobloop;
- subcall->result = NULL;
- subcall->status = 0;
- subcall_process(subcall, subcall_sync_reply);
- } else {
- subcall->status = -1;
- subcall_sync_leave(subcall);
- }
-}
-
-static int subcallsync(struct subcall *subcall, struct json_object **result)
-{
- int rc;
-
- afb_xreq_unhooked_addref(&subcall->xreq);
- rc = jobs_enter(NULL, 0, subcall_sync_enter, subcall);
- *result = subcall->result;
- if (rc < 0 || subcall->status < 0) {
- *result = *result ?: afb_msg_json_internal_error();
- rc = -1;
- }
- afb_xreq_unhooked_unref(&subcall->xreq);
- return rc;
-}
-
-/******************************************************************************/
-
-static void vinfo(void *first, void *second, const char *fmt, va_list args, void (*fun)(void*,void*,const char*))
-{
- char *info;
- if (fmt == NULL || vasprintf(&info, fmt, args) < 0)
- info = NULL;
- fun(first, second, info);
- free(info);
-}
-
-/******************************************************************************/
-
-static struct json_object *xreq_json_cb(struct afb_request *closure)
-{
- struct afb_xreq *xreq = xreq_from_request(closure);
if (!xreq->json && xreq->queryitf->json)
xreq->json = xreq->queryitf->json(xreq);
return xreq->json;
}
-static struct afb_arg xreq_get_cb(struct afb_request *closure, const char *name)
+static struct json_object *xreq_json_cb(struct afb_req_x2 *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_xreq_unhooked_json(xreq);
+}
+
+static struct afb_arg xreq_get_cb(struct afb_req_x2 *closure, const char *name)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
struct afb_arg arg;
struct json_object *object, *value;
@@ -353,409 +105,388 @@ static struct afb_arg xreq_get_cb(struct afb_request *closure, const char *name)
return arg;
}
-static void xreq_success_cb(struct afb_request *closure, struct json_object *obj, const char *info)
+static void xreq_reply_cb(struct afb_req_x2 *closure, struct json_object *obj, const char *error, const char *info)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
if (xreq->replied) {
ERROR("reply called more than one time!!");
json_object_put(obj);
} else {
xreq->replied = 1;
- if (xreq->queryitf->success)
- xreq->queryitf->success(xreq, obj, info);
- else
- xreq->queryitf->reply(xreq, 0, afb_msg_json_reply_ok(info, obj, &xreq->context, NULL));
+ xreq->queryitf->reply(xreq, obj, error, info);
}
}
-static void xreq_fail_cb(struct afb_request *closure, const char *status, const char *info)
+static void xreq_vreply_cb(struct afb_req_x2 *closure, struct json_object *obj, const char *error, const char *fmt, va_list args)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ char *info;
+ if (fmt == NULL || vasprintf(&info, fmt, args) < 0)
+ info = NULL;
+ xreq_reply_cb(closure, obj, error, info);
+ free(info);
+}
- if (xreq->replied) {
- ERROR("reply called more than one time!!");
- } else {
- xreq->replied = 1;
- if (xreq->queryitf->fail)
- xreq->queryitf->fail(xreq, status, info);
- else
- xreq->queryitf->reply(xreq, -1, afb_msg_json_reply_error(status, info, &xreq->context, NULL));
- }
+static void xreq_legacy_success_cb(struct afb_req_x2 *closure, struct json_object *obj, const char *info)
+{
+ xreq_reply_cb(closure, obj, NULL, info);
}
-static void xreq_vsuccess_cb(struct afb_request *closure, struct json_object *obj, const char *fmt, va_list args)
+static void xreq_legacy_fail_cb(struct afb_req_x2 *closure, const char *status, const char *info)
{
- vinfo(closure, obj, fmt, args, (void*)xreq_success_cb);
+ xreq_reply_cb(closure, NULL, status, info);
}
-static void xreq_vfail_cb(struct afb_request *closure, const char *status, const char *fmt, va_list args)
+static void xreq_legacy_vsuccess_cb(struct afb_req_x2 *closure, struct json_object *obj, const char *fmt, va_list args)
{
- vinfo(closure, (void*)status, fmt, args, (void*)xreq_fail_cb);
+ xreq_vreply_cb(closure, obj, NULL, fmt, args);
}
-static void *xreq_context_get_cb(struct afb_request *closure)
+static void xreq_legacy_vfail_cb(struct afb_req_x2 *closure, const char *status, const char *fmt, va_list args)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ xreq_vreply_cb(closure, NULL, status, fmt, args);
+}
+
+static void *xreq_legacy_context_get_cb(struct afb_req_x2 *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
return afb_context_get(&xreq->context);
}
-static void xreq_context_set_cb(struct afb_request *closure, void *value, void (*free_value)(void*))
+static void xreq_legacy_context_set_cb(struct afb_req_x2 *closure, void *value, void (*free_value)(void*))
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
afb_context_set(&xreq->context, value, free_value);
}
-static struct afb_request *xreq_addref_cb(struct afb_request *closure)
+static struct afb_req_x2 *xreq_addref_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
afb_xreq_unhooked_addref(xreq);
return closure;
}
-static void xreq_unref_cb(struct afb_request *closure)
+static void xreq_unref_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
afb_xreq_unhooked_unref(xreq);
}
-static void xreq_session_close_cb(struct afb_request *closure)
+static void xreq_session_close_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
afb_context_close(&xreq->context);
}
-static int xreq_session_set_LOA_cb(struct afb_request *closure, unsigned level)
+static int xreq_session_set_LOA_cb(struct afb_req_x2 *closure, unsigned level)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
return afb_context_change_loa(&xreq->context, level);
}
-static int xreq_subscribe_eventid_cb(struct afb_request *closure, struct afb_eventid *eventid);
-static int xreq_subscribe_cb(struct afb_request *closure, struct afb_event event)
+static int xreq_subscribe_event_x2_cb(struct afb_req_x2 *closure, struct afb_event_x2 *event)
{
- return xreq_subscribe_eventid_cb(closure, afb_event_to_eventid(event));
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_xreq_subscribe(xreq, event);
}
-static int xreq_subscribe_eventid_cb(struct afb_request *closure, struct afb_eventid *eventid)
+static int xreq_legacy_subscribe_event_x1_cb(struct afb_req_x2 *closure, struct afb_event_x1 event)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- return afb_xreq_subscribe(xreq, eventid);
+ return xreq_subscribe_event_x2_cb(closure, afb_event_x1_to_event_x2(event));
}
-int afb_xreq_subscribe(struct afb_xreq *xreq, struct afb_eventid *eventid)
+int afb_xreq_subscribe(struct afb_xreq *xreq, struct afb_event_x2 *event)
{
if (xreq->listener)
- return afb_evt_eventid_add_watch(xreq->listener, eventid);
+ return afb_evt_event_x2_add_watch(xreq->listener, event);
if (xreq->queryitf->subscribe)
- return xreq->queryitf->subscribe(xreq, eventid);
+ return xreq->queryitf->subscribe(xreq, event);
ERROR("no event listener, subscription impossible");
errno = EINVAL;
return -1;
}
-static int xreq_unsubscribe_eventid_cb(struct afb_request *closure, struct afb_eventid *eventid);
-static int xreq_unsubscribe_cb(struct afb_request *closure, struct afb_event event)
+static int xreq_unsubscribe_event_x2_cb(struct afb_req_x2 *closure, struct afb_event_x2 *event)
{
- return xreq_unsubscribe_eventid_cb(closure, afb_event_to_eventid(event));
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_xreq_unsubscribe(xreq, event);
}
-static int xreq_unsubscribe_eventid_cb(struct afb_request *closure, struct afb_eventid *eventid)
+static int xreq_legacy_unsubscribe_event_x1_cb(struct afb_req_x2 *closure, struct afb_event_x1 event)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- return afb_xreq_unsubscribe(xreq, eventid);
+ return xreq_unsubscribe_event_x2_cb(closure, afb_event_x1_to_event_x2(event));
}
-int afb_xreq_unsubscribe(struct afb_xreq *xreq, struct afb_eventid *eventid)
+int afb_xreq_unsubscribe(struct afb_xreq *xreq, struct afb_event_x2 *event)
{
if (xreq->listener)
- return afb_evt_eventid_remove_watch(xreq->listener, eventid);
+ return afb_evt_event_x2_remove_watch(xreq->listener, event);
if (xreq->queryitf->unsubscribe)
- return xreq->queryitf->unsubscribe(xreq, eventid);
+ return xreq->queryitf->unsubscribe(xreq, event);
ERROR("no event listener, unsubscription impossible");
errno = EINVAL;
return -1;
}
-static void xreq_subcall_cb(struct afb_request *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure)
+static void xreq_legacy_subcall_cb(struct afb_req_x2 *req, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- struct subcall *sc;
-
- sc = subcall_alloc(xreq, api, verb, args);
- if (sc == NULL) {
- if (callback)
- callback(cb_closure, 1, afb_msg_json_internal_error());
- json_object_put(args);
- } else {
- subcall(sc, callback, cb_closure);
- }
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ return afb_calls_legacy_subcall_v1(xreq, api, verb, args, callback, closure);
}
-static void xreq_subcall_req_cb(struct afb_request *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_req), void *cb_closure)
+static void xreq_legacy_subcall_req_cb(struct afb_req_x2 *req, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_req_x1), void *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- struct subcall *sc;
-
- sc = subcall_alloc(xreq, api, verb, args);
- if (sc == NULL) {
- if (callback)
- callback(cb_closure, 1, afb_msg_json_internal_error(), xreq_to_req(xreq));
- json_object_put(args);
- } else {
- subcall_req(sc, callback, cb_closure);
- }
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ return afb_calls_legacy_subcall_v2(xreq, api, verb, args, callback, closure);
}
-static void xreq_subcall_request_cb(struct afb_request *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_request*), void *cb_closure)
+static void xreq_legacy_subcall_request_cb(struct afb_req_x2 *req, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_req_x2*), void *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- struct subcall *sc;
-
- sc = subcall_alloc(xreq, api, verb, args);
- if (sc == NULL) {
- if (callback)
- callback(cb_closure, 1, afb_msg_json_internal_error(), xreq_to_request(xreq));
- json_object_put(args);
- } else {
- subcall_request(sc, callback, cb_closure);
- }
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ return afb_calls_legacy_subcall_v3(xreq, api, verb, args, callback, closure);
}
-static int xreq_subcallsync_cb(struct afb_request *closure, const char *api, const char *verb, struct json_object *args, struct json_object **result)
+static int xreq_legacy_subcallsync_cb(struct afb_req_x2 *req, const char *api, const char *verb, struct json_object *args, struct json_object **result)
{
- int rc;
- struct subcall *sc;
- struct afb_xreq *xreq = xreq_from_request(closure);
- struct json_object *resu;
-
- sc = subcall_alloc(xreq, api, verb, args);
- if (!sc) {
- rc = -1;
- resu = afb_msg_json_internal_error();
- json_object_put(args);
- } else {
- rc = subcallsync(sc, &resu);
- }
- if (result)
- *result = resu;
- else
- json_object_put(resu);
- return rc;
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ return afb_calls_legacy_subcall_sync(xreq, api, verb, args, result);
}
-static void xreq_vverbose_cb(struct afb_request *closure, int level, const char *file, int line, const char *func, const char *fmt, va_list args)
+static void xreq_vverbose_cb(struct afb_req_x2 *closure, int level, const char *file, int line, const char *func, const char *fmt, va_list args)
{
char *p;
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
if (!fmt || vasprintf(&p, fmt, args) < 0)
vverbose(level, file, line, func, fmt, args);
else {
- verbose(level, file, line, func, "[REQ/API %s] %s", xreq->request.api, p);
+ verbose(level, file, line, func, "[REQ/API %s] %s", xreq->request.called_api, p);
free(p);
}
}
-static struct afb_stored_req *xreq_store_cb(struct afb_request *closure)
+static struct afb_stored_req *xreq_legacy_store_cb(struct afb_req_x2 *closure)
{
xreq_addref_cb(closure);
return (struct afb_stored_req*)closure;
}
-static int xreq_has_permission_cb(struct afb_request *closure, const char *permission)
+static int xreq_has_permission_cb(struct afb_req_x2 *closure, const char *permission)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
return afb_auth_has_permission(xreq, permission);
}
-static char *xreq_get_application_id_cb(struct afb_request *closure)
+static char *xreq_get_application_id_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
return xreq->cred && xreq->cred->id ? strdup(xreq->cred->id) : NULL;
}
-static void *xreq_context_make_cb(struct afb_request *closure, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure)
+static void *xreq_context_make_cb(struct afb_req_x2 *closure, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
return afb_context_make(&xreq->context, replace, create_value, free_value, create_closure);
}
-static int xreq_get_uid_cb(struct afb_request *closure)
+static int xreq_get_uid_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
return xreq->cred && xreq->cred->id ? (int)xreq->cred->uid : -1;
}
+static struct json_object *xreq_get_client_info_cb(struct afb_req_x2 *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ struct json_object *r = json_object_new_object();
+ if (xreq->cred && xreq->cred->id) {
+ json_object_object_add(r, "uid", json_object_new_int(xreq->cred->uid));
+ json_object_object_add(r, "gid", json_object_new_int(xreq->cred->gid));
+ json_object_object_add(r, "pid", json_object_new_int(xreq->cred->pid));
+ json_object_object_add(r, "user", json_object_new_string(xreq->cred->user));
+ json_object_object_add(r, "label", json_object_new_string(xreq->cred->label));
+ json_object_object_add(r, "id", json_object_new_string(xreq->cred->id));
+ }
+ if (xreq->context.session) {
+ json_object_object_add(r, "uuid", json_object_new_string(afb_context_uuid(&xreq->context)));
+ json_object_object_add(r, "LOA", json_object_new_int(afb_context_get_loa(&xreq->context)));
+ }
+ return r;
+}
+
+static void xreq_subcall_cb(
+ struct afb_req_x2 *req,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void (*callback)(void *closure, struct json_object *object, const char *error, const char * info, struct afb_req_x2 *req),
+ void *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ afb_calls_subcall(xreq, api, verb, args, flags, callback, closure);
+}
+
+static int xreq_subcallsync_cb(
+ struct afb_req_x2 *req,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ struct json_object **object,
+ char **error,
+ char **info)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ return afb_calls_subcall_sync(xreq, api, verb, args, flags, object, error, info);
+}
+
/******************************************************************************/
-static struct json_object *xreq_hooked_json_cb(struct afb_request *closure)
+static struct json_object *xreq_hooked_json_cb(struct afb_req_x2 *closure)
{
struct json_object *r = xreq_json_cb(closure);
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
return afb_hook_xreq_json(xreq, r);
}
-static struct afb_arg xreq_hooked_get_cb(struct afb_request *closure, const char *name)
+static struct afb_arg xreq_hooked_get_cb(struct afb_req_x2 *closure, const char *name)
{
struct afb_arg r = xreq_get_cb(closure, name);
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
return afb_hook_xreq_get(xreq, name, r);
}
-static void xreq_hooked_success_cb(struct afb_request *closure, struct json_object *obj, const char *info)
+static void xreq_hooked_reply_cb(struct afb_req_x2 *closure, struct json_object *obj, const char *error, const char *info)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ afb_hook_xreq_reply(xreq, obj, error, info);
+ xreq_reply_cb(closure, obj, error, info);
+}
+
+static void xreq_hooked_vreply_cb(struct afb_req_x2 *closure, struct json_object *obj, const char *error, const char *fmt, va_list args)
+{
+ char *info;
+ if (fmt == NULL || vasprintf(&info, fmt, args) < 0)
+ info = NULL;
+ xreq_hooked_reply_cb(closure, obj, error, info);
+ free(info);
+}
+
+static void xreq_hooked_legacy_success_cb(struct afb_req_x2 *closure, struct json_object *obj, const char *info)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- afb_hook_xreq_success(xreq, obj, info);
- xreq_success_cb(closure, obj, info);
+ xreq_hooked_reply_cb(closure, obj, NULL, info);
}
-static void xreq_hooked_fail_cb(struct afb_request *closure, const char *status, const char *info)
+static void xreq_hooked_legacy_fail_cb(struct afb_req_x2 *closure, const char *status, const char *info)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- afb_hook_xreq_fail(xreq, status, info);
- xreq_fail_cb(closure, status, info);
+ xreq_hooked_reply_cb(closure, NULL, status, info);
}
-static void xreq_hooked_vsuccess_cb(struct afb_request *closure, struct json_object *obj, const char *fmt, va_list args)
+static void xreq_hooked_legacy_vsuccess_cb(struct afb_req_x2 *closure, struct json_object *obj, const char *fmt, va_list args)
{
- vinfo(closure, obj, fmt, args, (void*)xreq_hooked_success_cb);
+ xreq_hooked_vreply_cb(closure, obj, NULL, fmt, args);
}
-static void xreq_hooked_vfail_cb(struct afb_request *closure, const char *status, const char *fmt, va_list args)
+static void xreq_hooked_legacy_vfail_cb(struct afb_req_x2 *closure, const char *status, const char *fmt, va_list args)
{
- vinfo(closure, (void*)status, fmt, args, (void*)xreq_hooked_fail_cb);
+ xreq_hooked_vreply_cb(closure, NULL, status, fmt, args);
}
-static void *xreq_hooked_context_get_cb(struct afb_request *closure)
+static void *xreq_hooked_legacy_context_get_cb(struct afb_req_x2 *closure)
{
- void *r = xreq_context_get_cb(closure);
- struct afb_xreq *xreq = xreq_from_request(closure);
- return afb_hook_xreq_context_get(xreq, r);
+ void *r = xreq_legacy_context_get_cb(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_hook_xreq_legacy_context_get(xreq, r);
}
-static void xreq_hooked_context_set_cb(struct afb_request *closure, void *value, void (*free_value)(void*))
+static void xreq_hooked_legacy_context_set_cb(struct afb_req_x2 *closure, void *value, void (*free_value)(void*))
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- afb_hook_xreq_context_set(xreq, value, free_value);
- xreq_context_set_cb(closure, value, free_value);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ afb_hook_xreq_legacy_context_set(xreq, value, free_value);
+ xreq_legacy_context_set_cb(closure, value, free_value);
}
-static struct afb_request *xreq_hooked_addref_cb(struct afb_request *closure)
+static struct afb_req_x2 *xreq_hooked_addref_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
afb_hook_xreq_addref(xreq);
return xreq_addref_cb(closure);
}
-static void xreq_hooked_unref_cb(struct afb_request *closure)
+static void xreq_hooked_unref_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
afb_hook_xreq_unref(xreq);
xreq_unref_cb(closure);
}
-static void xreq_hooked_session_close_cb(struct afb_request *closure)
+static void xreq_hooked_session_close_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
afb_hook_xreq_session_close(xreq);
xreq_session_close_cb(closure);
}
-static int xreq_hooked_session_set_LOA_cb(struct afb_request *closure, unsigned level)
+static int xreq_hooked_session_set_LOA_cb(struct afb_req_x2 *closure, unsigned level)
{
int r = xreq_session_set_LOA_cb(closure, level);
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
return afb_hook_xreq_session_set_LOA(xreq, level, r);
}
-static int xreq_hooked_subscribe_eventid_cb(struct afb_request *closure, struct afb_eventid *eventid);
-static int xreq_hooked_subscribe_cb(struct afb_request *closure, struct afb_event event)
+static int xreq_hooked_subscribe_event_x2_cb(struct afb_req_x2 *closure, struct afb_event_x2 *event)
{
- return xreq_hooked_subscribe_eventid_cb(closure, afb_event_to_eventid(event));
+ int r = xreq_subscribe_event_x2_cb(closure, event);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_hook_xreq_subscribe(xreq, event, r);
}
-static int xreq_hooked_subscribe_eventid_cb(struct afb_request *closure, struct afb_eventid *eventid)
+static int xreq_hooked_legacy_subscribe_event_x1_cb(struct afb_req_x2 *closure, struct afb_event_x1 event)
{
- int r = xreq_subscribe_eventid_cb(closure, eventid);
- struct afb_xreq *xreq = xreq_from_request(closure);
- return afb_hook_xreq_subscribe(xreq, eventid, r);
+ return xreq_hooked_subscribe_event_x2_cb(closure, afb_event_x1_to_event_x2(event));
}
-static int xreq_hooked_unsubscribe_eventid_cb(struct afb_request *closure, struct afb_eventid *eventid);
-static int xreq_hooked_unsubscribe_cb(struct afb_request *closure, struct afb_event event)
+static int xreq_hooked_unsubscribe_event_x2_cb(struct afb_req_x2 *closure, struct afb_event_x2 *event)
{
- return xreq_hooked_unsubscribe_eventid_cb(closure, afb_event_to_eventid(event));
+ int r = xreq_unsubscribe_event_x2_cb(closure, event);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_hook_xreq_unsubscribe(xreq, event, r);
}
-static int xreq_hooked_unsubscribe_eventid_cb(struct afb_request *closure, struct afb_eventid *eventid)
+static int xreq_hooked_legacy_unsubscribe_event_x1_cb(struct afb_req_x2 *closure, struct afb_event_x1 event)
{
- int r = xreq_unsubscribe_eventid_cb(closure, eventid);
- struct afb_xreq *xreq = xreq_from_request(closure);
- return afb_hook_xreq_unsubscribe(xreq, eventid, r);
+ return xreq_hooked_unsubscribe_event_x2_cb(closure, afb_event_x1_to_event_x2(event));
}
-static void xreq_hooked_subcall_cb(struct afb_request *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure)
+static void xreq_hooked_legacy_subcall_cb(struct afb_req_x2 *req, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- struct subcall *sc;
-
- afb_hook_xreq_subcall(xreq, api, verb, args);
- sc = subcall_alloc(xreq, api, verb, args);
- if (sc == NULL) {
- if (callback)
- callback(cb_closure, 1, afb_msg_json_internal_error());
- json_object_put(args);
- } else {
- subcall_hooked(sc, callback, cb_closure);
- }
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ afb_calls_legacy_hooked_subcall_v1(xreq, api, verb, args, callback, closure);
}
-static void xreq_hooked_subcall_req_cb(struct afb_request *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_req), void *cb_closure)
+static void xreq_hooked_legacy_subcall_req_cb(struct afb_req_x2 *req, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_req_x1), void *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- struct subcall *sc;
-
- afb_hook_xreq_subcall_req(xreq, api, verb, args);
- sc = subcall_alloc(xreq, api, verb, args);
- if (sc == NULL) {
- if (callback)
- callback(cb_closure, 1, afb_msg_json_internal_error(), xreq_to_req(xreq));
- json_object_put(args);
- } else {
- subcall_req_hooked(sc, callback, cb_closure);
- }
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ afb_calls_legacy_hooked_subcall_v2(xreq, api, verb, args, callback, closure);
}
-static void xreq_hooked_subcall_request_cb(struct afb_request *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_request *), void *cb_closure)
+static void xreq_hooked_legacy_subcall_request_cb(struct afb_req_x2 *req, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_req_x2 *), void *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- struct subcall *sc;
-
- afb_hook_xreq_subcall(xreq, api, verb, args);
- sc = subcall_alloc(xreq, api, verb, args);
- if (sc == NULL) {
- if (callback)
- callback(cb_closure, 1, afb_msg_json_internal_error(), xreq_to_request(xreq));
- json_object_put(args);
- } else {
- subcall_request_hooked(sc, callback, cb_closure);
- }
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ afb_calls_legacy_hooked_subcall_v3(xreq, api, verb, args, callback, closure);
}
-static int xreq_hooked_subcallsync_cb(struct afb_request *closure, const char *api, const char *verb, struct json_object *args, struct json_object **result)
+static int xreq_hooked_legacy_subcallsync_cb(struct afb_req_x2 *req, const char *api, const char *verb, struct json_object *args, struct json_object **result)
{
- int r;
- struct afb_xreq *xreq = xreq_from_request(closure);
- afb_hook_xreq_subcallsync(xreq, api, verb, args);
- r = xreq_subcallsync_cb(closure, api, verb, args, result);
- return afb_hook_xreq_subcallsync_result(xreq, r, *result);
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ return afb_calls_legacy_hooked_subcall_sync(xreq, api, verb, args, result);
}
-static void xreq_hooked_vverbose_cb(struct afb_request *closure, int level, const char *file, int line, const char *func, const char *fmt, va_list args)
+static void xreq_hooked_vverbose_cb(struct afb_req_x2 *closure, int level, const char *file, int line, const char *func, const char *fmt, va_list args)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
va_list ap;
va_copy(ap, args);
xreq_vverbose_cb(closure, level, file, line, func, fmt, args);
@@ -763,149 +494,178 @@ static void xreq_hooked_vverbose_cb(struct afb_request *closure, int level, cons
va_end(ap);
}
-static struct afb_stored_req *xreq_hooked_store_cb(struct afb_request *closure)
+static struct afb_stored_req *xreq_hooked_legacy_store_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
- struct afb_stored_req *r = xreq_store_cb(closure);
- afb_hook_xreq_store(xreq, r);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ struct afb_stored_req *r = xreq_legacy_store_cb(closure);
+ afb_hook_xreq_legacy_store(xreq, r);
return r;
}
-static int xreq_hooked_has_permission_cb(struct afb_request *closure, const char *permission)
+static int xreq_hooked_has_permission_cb(struct afb_req_x2 *closure, const char *permission)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
int r = xreq_has_permission_cb(closure, permission);
return afb_hook_xreq_has_permission(xreq, permission, r);
}
-static char *xreq_hooked_get_application_id_cb(struct afb_request *closure)
+static char *xreq_hooked_get_application_id_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
char *r = xreq_get_application_id_cb(closure);
return afb_hook_xreq_get_application_id(xreq, r);
}
-static void *xreq_hooked_context_make_cb(struct afb_request *closure, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure)
+static void *xreq_hooked_context_make_cb(struct afb_req_x2 *closure, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
void *result = xreq_context_make_cb(closure, replace, create_value, free_value, create_closure);
return afb_hook_xreq_context_make(xreq, replace, create_value, free_value, create_closure, result);
}
-static int xreq_hooked_get_uid_cb(struct afb_request *closure)
+static int xreq_hooked_get_uid_cb(struct afb_req_x2 *closure)
{
- struct afb_xreq *xreq = xreq_from_request(closure);
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
int r = xreq_get_uid_cb(closure);
return afb_hook_xreq_get_uid(xreq, r);
}
+static struct json_object *xreq_hooked_get_client_info_cb(struct afb_req_x2 *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ struct json_object *r = xreq_get_client_info_cb(closure);
+ return afb_hook_xreq_get_client_info(xreq, r);
+}
+
+static void xreq_hooked_subcall_cb(
+ struct afb_req_x2 *req,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void (*callback)(void *closure, struct json_object *object, const char *error, const char * info, struct afb_req_x2 *req),
+ void *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ afb_calls_hooked_subcall(xreq, api, verb, args, flags, callback, closure);
+}
+
+static int xreq_hooked_subcallsync_cb(
+ struct afb_req_x2 *req,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ struct json_object **object,
+ char **error,
+ char **info)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(req);
+ return afb_calls_hooked_subcall_sync(xreq, api, verb, args, flags, object, error, info);
+}
+
/******************************************************************************/
-const struct afb_request_itf xreq_itf = {
+const struct afb_req_x2_itf xreq_itf = {
.json = xreq_json_cb,
.get = xreq_get_cb,
- .success = xreq_success_cb,
- .fail = xreq_fail_cb,
- .vsuccess = xreq_vsuccess_cb,
- .vfail = xreq_vfail_cb,
- .context_get = xreq_context_get_cb,
- .context_set = xreq_context_set_cb,
+ .legacy_success = xreq_legacy_success_cb,
+ .legacy_fail = xreq_legacy_fail_cb,
+ .legacy_vsuccess = xreq_legacy_vsuccess_cb,
+ .legacy_vfail = xreq_legacy_vfail_cb,
+ .legacy_context_get = xreq_legacy_context_get_cb,
+ .legacy_context_set = xreq_legacy_context_set_cb,
.addref = xreq_addref_cb,
.unref = xreq_unref_cb,
.session_close = xreq_session_close_cb,
.session_set_LOA = xreq_session_set_LOA_cb,
- .subscribe = xreq_subscribe_cb,
- .unsubscribe = xreq_unsubscribe_cb,
- .subcall = xreq_subcall_cb,
- .subcallsync = xreq_subcallsync_cb,
+ .legacy_subscribe_event_x1 = xreq_legacy_subscribe_event_x1_cb,
+ .legacy_unsubscribe_event_x1 = xreq_legacy_unsubscribe_event_x1_cb,
+ .legacy_subcall = xreq_legacy_subcall_cb,
+ .legacy_subcallsync = xreq_legacy_subcallsync_cb,
.vverbose = xreq_vverbose_cb,
- .store = xreq_store_cb,
- .subcall_req = xreq_subcall_req_cb,
+ .legacy_store_req = xreq_legacy_store_cb,
+ .legacy_subcall_req = xreq_legacy_subcall_req_cb,
.has_permission = xreq_has_permission_cb,
.get_application_id = xreq_get_application_id_cb,
.context_make = xreq_context_make_cb,
- .subscribe_eventid = xreq_subscribe_eventid_cb,
- .unsubscribe_eventid = xreq_unsubscribe_eventid_cb,
- .subcall_request = xreq_subcall_request_cb,
+ .subscribe_event_x2 = xreq_subscribe_event_x2_cb,
+ .unsubscribe_event_x2 = xreq_unsubscribe_event_x2_cb,
+ .legacy_subcall_request = xreq_legacy_subcall_request_cb,
.get_uid = xreq_get_uid_cb,
+ .reply = xreq_reply_cb,
+ .vreply = xreq_vreply_cb,
+ .get_client_info = xreq_get_client_info_cb,
+ .subcall = xreq_subcall_cb,
+ .subcallsync = xreq_subcallsync_cb,
};
-const struct afb_request_itf xreq_hooked_itf = {
+const struct afb_req_x2_itf xreq_hooked_itf = {
.json = xreq_hooked_json_cb,
.get = xreq_hooked_get_cb,
- .success = xreq_hooked_success_cb,
- .fail = xreq_hooked_fail_cb,
- .vsuccess = xreq_hooked_vsuccess_cb,
- .vfail = xreq_hooked_vfail_cb,
- .context_get = xreq_hooked_context_get_cb,
- .context_set = xreq_hooked_context_set_cb,
+ .legacy_success = xreq_hooked_legacy_success_cb,
+ .legacy_fail = xreq_hooked_legacy_fail_cb,
+ .legacy_vsuccess = xreq_hooked_legacy_vsuccess_cb,
+ .legacy_vfail = xreq_hooked_legacy_vfail_cb,
+ .legacy_context_get = xreq_hooked_legacy_context_get_cb,
+ .legacy_context_set = xreq_hooked_legacy_context_set_cb,
.addref = xreq_hooked_addref_cb,
.unref = xreq_hooked_unref_cb,
.session_close = xreq_hooked_session_close_cb,
.session_set_LOA = xreq_hooked_session_set_LOA_cb,
- .subscribe = xreq_hooked_subscribe_cb,
- .unsubscribe = xreq_hooked_unsubscribe_cb,
- .subcall = xreq_hooked_subcall_cb,
- .subcallsync = xreq_hooked_subcallsync_cb,
+ .legacy_subscribe_event_x1 = xreq_hooked_legacy_subscribe_event_x1_cb,
+ .legacy_unsubscribe_event_x1 = xreq_hooked_legacy_unsubscribe_event_x1_cb,
+ .legacy_subcall = xreq_hooked_legacy_subcall_cb,
+ .legacy_subcallsync = xreq_hooked_legacy_subcallsync_cb,
.vverbose = xreq_hooked_vverbose_cb,
- .store = xreq_hooked_store_cb,
- .subcall_req = xreq_hooked_subcall_req_cb,
+ .legacy_store_req = xreq_hooked_legacy_store_cb,
+ .legacy_subcall_req = xreq_hooked_legacy_subcall_req_cb,
.has_permission = xreq_hooked_has_permission_cb,
.get_application_id = xreq_hooked_get_application_id_cb,
.context_make = xreq_hooked_context_make_cb,
- .subscribe_eventid = xreq_hooked_subscribe_eventid_cb,
- .unsubscribe_eventid = xreq_hooked_unsubscribe_eventid_cb,
- .subcall_request = xreq_hooked_subcall_request_cb,
+ .subscribe_event_x2 = xreq_hooked_subscribe_event_x2_cb,
+ .unsubscribe_event_x2 = xreq_hooked_unsubscribe_event_x2_cb,
+ .legacy_subcall_request = xreq_hooked_legacy_subcall_request_cb,
.get_uid = xreq_hooked_get_uid_cb,
+ .reply = xreq_hooked_reply_cb,
+ .vreply = xreq_hooked_vreply_cb,
+ .get_client_info = xreq_hooked_get_client_info_cb,
+ .subcall = xreq_hooked_subcall_cb,
+ .subcallsync = xreq_hooked_subcallsync_cb,
};
/******************************************************************************/
-struct afb_req afb_xreq_unstore(struct afb_stored_req *sreq)
+struct afb_req_x1 afb_xreq_unstore(struct afb_stored_req *sreq)
{
struct afb_xreq *xreq = (struct afb_xreq *)sreq;
if (xreq->hookflags)
- afb_hook_xreq_unstore(xreq);
- return xreq_to_req(xreq);
+ afb_hook_xreq_legacy_unstore(xreq);
+ return xreq_to_req_x1(xreq);
}
struct json_object *afb_xreq_json(struct afb_xreq *xreq)
{
- return afb_request_json(xreq_to_request(xreq));
+ return afb_req_x2_json(xreq_to_req_x2(xreq));
}
-void afb_xreq_success(struct afb_xreq *xreq, struct json_object *obj, const char *info)
+void afb_xreq_reply(struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info)
{
- afb_request_success(xreq_to_request(xreq), obj, info);
+ afb_req_x2_reply(xreq_to_req_x2(xreq), obj, error, info);
}
-void afb_xreq_success_f(struct afb_xreq *xreq, struct json_object *obj, const char *info, ...)
+void afb_xreq_reply_f(struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info, ...)
{
va_list args;
va_start(args, info);
- afb_request_success_v(xreq_to_request(xreq), obj, info, args);
+ afb_req_x2_reply_v(xreq_to_req_x2(xreq), obj, error, info, args);
va_end(args);
}
-void afb_xreq_fail(struct afb_xreq *xreq, const char *status, const char *info)
-{
- afb_request_fail(xreq_to_request(xreq), status, info);
-}
-
-void afb_xreq_fail_f(struct afb_xreq *xreq, const char *status, const char *info, ...)
-{
- va_list args;
-
- va_start(args, info);
- afb_request_fail_v(xreq_to_request(xreq), status, info, args);
- va_end(args);
-
-}
-
const char *afb_xreq_raw(struct afb_xreq *xreq, size_t *size)
{
- struct json_object *obj = xreq_json_cb(xreq_to_request(xreq));
+ struct json_object *obj = xreq_json_cb(xreq_to_req_x2(xreq));
const char *result = json_object_to_json_string(obj);
if (size != NULL)
*size = strlen(result);
@@ -914,69 +674,79 @@ const char *afb_xreq_raw(struct afb_xreq *xreq, size_t *size)
void afb_xreq_addref(struct afb_xreq *xreq)
{
- afb_request_addref(xreq_to_request(xreq));
+ afb_req_x2_addref(xreq_to_req_x2(xreq));
}
void afb_xreq_unref(struct afb_xreq *xreq)
{
- afb_request_unref(xreq_to_request(xreq));
+ afb_req_x2_unref(xreq_to_req_x2(xreq));
+}
+
+void afb_xreq_unhooked_legacy_subcall(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_req_x2 *), void *cb_closure)
+{
+ xreq_legacy_subcall_request_cb(xreq_to_req_x2(xreq), api, verb, args, callback, cb_closure);
+}
+
+void afb_xreq_legacy_subcall(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_req_x2 *), void *cb_closure)
+{
+ afb_req_x2_subcall_legacy(xreq_to_req_x2(xreq), api, verb, args, callback, cb_closure);
}
-void afb_xreq_unhooked_subcall(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_request *), void *cb_closure)
+void afb_xreq_unhooked_subcall(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, int flags, void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_req_x2 *), void *closure)
{
- xreq_subcall_request_cb(xreq_to_request(xreq), api, verb, args, callback, cb_closure);
+ xreq_subcall_cb(xreq_to_req_x2(xreq), api, verb, args, flags, callback, closure);
}
-void afb_xreq_subcall(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_request *), void *cb_closure)
+void afb_xreq_subcall(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, int flags, void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_req_x2 *), void *closure)
{
- afb_request_subcall(xreq_to_request(xreq), api, verb, args, callback, cb_closure);
+ afb_req_x2_subcall(xreq_to_req_x2(xreq), api, verb, args, flags, callback, closure);
}
-int afb_xreq_unhooked_subcall_sync(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, struct json_object **result)
+int afb_xreq_unhooked_legacy_subcall_sync(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, struct json_object **result)
{
- return xreq_subcallsync_cb(xreq_to_request(xreq), api, verb, args, result);
+ return xreq_legacy_subcallsync_cb(xreq_to_req_x2(xreq), api, verb, args, result);
}
-int afb_xreq_subcall_sync(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, struct json_object **result)
+int afb_xreq_legacy_subcall_sync(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, struct json_object **result)
{
- return afb_request_subcall_sync(xreq_to_request(xreq), api, verb, args, result);
+ return afb_req_x2_subcall_sync_legacy(xreq_to_req_x2(xreq), api, verb, args, result);
}
static int xreq_session_check_apply_v1(struct afb_xreq *xreq, int sessionflags)
{
int loa;
- if ((sessionflags & (AFB_SESSION_CLOSE_V1|AFB_SESSION_RENEW_V1|AFB_SESSION_CHECK_V1|AFB_SESSION_LOA_EQ_V1)) != 0) {
+ if ((sessionflags & (AFB_SESSION_CLOSE_X1|AFB_SESSION_RENEW_X1|AFB_SESSION_CHECK_X1|AFB_SESSION_LOA_EQ_X1)) != 0) {
if (!afb_context_check(&xreq->context)) {
afb_context_close(&xreq->context);
- afb_xreq_fail_f(xreq, "denied", "invalid token's identity");
+ afb_xreq_reply_f(xreq, NULL, "denied", "invalid token's identity");
errno = EINVAL;
return -1;
}
}
- if ((sessionflags & AFB_SESSION_LOA_GE_V1) != 0) {
- loa = (sessionflags >> AFB_SESSION_LOA_SHIFT_V1) & AFB_SESSION_LOA_MASK_V1;
+ if ((sessionflags & AFB_SESSION_LOA_GE_X1) != 0) {
+ loa = (sessionflags >> AFB_SESSION_LOA_SHIFT_X1) & AFB_SESSION_LOA_MASK_X1;
if (!afb_context_check_loa(&xreq->context, loa)) {
- afb_xreq_fail_f(xreq, "denied", "invalid LOA");
+ afb_xreq_reply_f(xreq, NULL, "denied", "invalid LOA");
errno = EPERM;
return -1;
}
}
- if ((sessionflags & AFB_SESSION_LOA_LE_V1) != 0) {
- loa = (sessionflags >> AFB_SESSION_LOA_SHIFT_V1) & AFB_SESSION_LOA_MASK_V1;
+ if ((sessionflags & AFB_SESSION_LOA_LE_X1) != 0) {
+ loa = (sessionflags >> AFB_SESSION_LOA_SHIFT_X1) & AFB_SESSION_LOA_MASK_X1;
if (afb_context_check_loa(&xreq->context, loa + 1)) {
- afb_xreq_fail_f(xreq, "denied", "invalid LOA");
+ afb_xreq_reply_f(xreq, NULL, "denied", "invalid LOA");
errno = EPERM;
return -1;
}
}
- if ((sessionflags & AFB_SESSION_RENEW_V1) != 0) {
+ if ((sessionflags & AFB_SESSION_RENEW_X1) != 0) {
afb_context_refresh(&xreq->context);
}
- if ((sessionflags & AFB_SESSION_CLOSE_V1) != 0) {
+ if ((sessionflags & AFB_SESSION_CLOSE_X1) != 0) {
afb_context_change_loa(&xreq->context, 0);
afb_context_close(&xreq->context);
}
@@ -991,29 +761,29 @@ static int xreq_session_check_apply_v2(struct afb_xreq *xreq, uint32_t sessionfl
if (sessionflags != 0) {
if (!afb_context_check(&xreq->context)) {
afb_context_close(&xreq->context);
- afb_xreq_fail_f(xreq, "denied", "invalid token's identity");
+ afb_xreq_reply_f(xreq, NULL, "denied", "invalid token's identity");
errno = EINVAL;
return -1;
}
}
- loa = (int)(sessionflags & AFB_SESSION_LOA_MASK_V2);
+ loa = (int)(sessionflags & AFB_SESSION_LOA_MASK_X2);
if (loa && !afb_context_check_loa(&xreq->context, loa)) {
- afb_xreq_fail_f(xreq, "denied", "invalid LOA");
+ afb_xreq_reply_f(xreq, NULL, "denied", "invalid LOA");
errno = EPERM;
return -1;
}
if (auth && !afb_auth_check(xreq, auth)) {
- afb_xreq_fail_f(xreq, "denied", "authorisation refused");
+ afb_xreq_reply_f(xreq, NULL, "denied", "authorisation refused");
errno = EPERM;
return -1;
}
- if ((sessionflags & AFB_SESSION_REFRESH_V2) != 0) {
+ if ((sessionflags & AFB_SESSION_REFRESH_X2) != 0) {
afb_context_refresh(&xreq->context);
}
- if ((sessionflags & AFB_SESSION_CLOSE_V2) != 0) {
+ if ((sessionflags & AFB_SESSION_CLOSE_X2) != 0) {
afb_context_close(&xreq->context);
}
@@ -1023,55 +793,55 @@ static int xreq_session_check_apply_v2(struct afb_xreq *xreq, uint32_t sessionfl
void afb_xreq_call_verb_v1(struct afb_xreq *xreq, const struct afb_verb_desc_v1 *verb)
{
if (!verb)
- afb_xreq_fail_unknown_verb(xreq);
+ afb_xreq_reply_unknown_verb(xreq);
else
if (!xreq_session_check_apply_v1(xreq, verb->session))
- verb->callback(xreq_to_req(xreq));
+ verb->callback(xreq_to_req_x1(xreq));
}
void afb_xreq_call_verb_v2(struct afb_xreq *xreq, const struct afb_verb_v2 *verb)
{
if (!verb)
- afb_xreq_fail_unknown_verb(xreq);
+ afb_xreq_reply_unknown_verb(xreq);
else
if (!xreq_session_check_apply_v2(xreq, verb->session, verb->auth))
- verb->callback(xreq_to_req(xreq));
+ verb->callback(xreq_to_req_x1(xreq));
}
-void afb_xreq_call_verb_vdyn(struct afb_xreq *xreq, const struct afb_api_dyn_verb *verb)
+void afb_xreq_call_verb_v3(struct afb_xreq *xreq, const struct afb_verb_v3 *verb)
{
if (!verb)
- afb_xreq_fail_unknown_verb(xreq);
+ afb_xreq_reply_unknown_verb(xreq);
else
if (xreq_session_check_apply_v2(xreq, verb->session, verb->auth) >= 0)
- verb->callback(xreq_to_request(xreq));
+ verb->callback(xreq_to_req_x2(xreq));
}
void afb_xreq_init(struct afb_xreq *xreq, const struct afb_xreq_query_itf *queryitf)
{
memset(xreq, 0, sizeof *xreq);
- xreq->request.itf = &xreq_hooked_itf; /* hook by default */
+ xreq->request.itf = &xreq_itf; /* no hook by default */
xreq->refcount = 1;
xreq->queryitf = queryitf;
}
-void afb_xreq_fail_unknown_api(struct afb_xreq *xreq)
+void afb_xreq_reply_unknown_api(struct afb_xreq *xreq)
{
- afb_xreq_fail_f(xreq, "unknown-api", "api %s not found (for verb %s)", xreq->request.api, xreq->request.verb);
+ afb_xreq_reply_f(xreq, NULL, "unknown-api", "api %s not found (for verb %s)", xreq->request.called_api, xreq->request.called_verb);
}
-void afb_xreq_fail_unknown_verb(struct afb_xreq *xreq)
+void afb_xreq_reply_unknown_verb(struct afb_xreq *xreq)
{
- afb_xreq_fail_f(xreq, "unknown-verb", "verb %s unknown within api %s", xreq->request.verb, xreq->request.api);
+ afb_xreq_reply_f(xreq, NULL, "unknown-verb", "verb %s unknown within api %s", xreq->request.called_verb, xreq->request.called_api);
}
static void init_hooking(struct afb_xreq *xreq)
{
afb_hook_init_xreq(xreq);
- if (xreq->hookflags)
+ if (xreq->hookflags) {
+ xreq->request.itf = &xreq_hooked_itf; /* unhook the interface */
afb_hook_xreq_begin(xreq);
- else
- xreq->request.itf = &xreq_itf; /* unhook the interface */
+ }
}
/**
@@ -1080,16 +850,16 @@ static void init_hooking(struct afb_xreq *xreq)
static void process_async(int signum, void *arg)
{
struct afb_xreq *xreq = arg;
- const struct afb_api *api;
+ const struct afb_api_item *api;
if (signum != 0) {
/* emit the error (assumes that hooking is initialised) */
- afb_xreq_fail_f(xreq, "aborted", "signal %s(%d) caught", strsignal(signum), signum);
+ afb_xreq_reply_f(xreq, NULL, "aborted", "signal %s(%d) caught", strsignal(signum), signum);
} else {
/* init hooking */
init_hooking(xreq);
- /* invoke api call method to process the reqiest */
- api = (const struct afb_api*)xreq->context.api_key;
+ /* invoke api call method to process the request */
+ api = (const struct afb_api_item*)xreq->context.api_key;
api->itf->call(api->closure, xreq);
}
/* release the request */
@@ -1111,7 +881,7 @@ static void early_failure(struct afb_xreq *xreq, const char *status, const char
/* send error */
va_start(args, info);
- afb_request_fail_v(xreq_to_request(xreq), status, info, args);
+ afb_req_x2_reply_v(xreq_to_req_x2(xreq), NULL, status, info, args);
va_end(args);
}
@@ -1121,17 +891,17 @@ static void early_failure(struct afb_xreq *xreq, const char *status, const char
*/
void afb_xreq_process(struct afb_xreq *xreq, struct afb_apiset *apiset)
{
- const struct afb_api *api;
+ const struct afb_api_item *api;
struct afb_xreq *caller;
/* lookup at the api */
xreq->apiset = apiset;
- api = afb_apiset_lookup_started(apiset, xreq->request.api, 1);
+ api = afb_apiset_lookup_started(apiset, xreq->request.called_api, 1);
if (!api) {
if (errno == ENOENT)
- early_failure(xreq, "unknown-api", "api %s not found (for verb %s)", xreq->request.api, xreq->request.verb);
+ early_failure(xreq, "unknown-api", "api %s not found (for verb %s)", xreq->request.called_api, xreq->request.called_verb);
else
- early_failure(xreq, "bad-api-state", "api %s not started correctly: %m", xreq->request.api);
+ early_failure(xreq, "bad-api-state", "api %s not started correctly: %m", xreq->request.called_api);
goto end;
}
xreq->context.api_key = api;
@@ -1140,10 +910,10 @@ void afb_xreq_process(struct afb_xreq *xreq, struct afb_apiset *apiset)
if (api->group) {
caller = xreq->caller;
while (caller) {
- if (((const struct afb_api *)caller->context.api_key)->group == api->group) {
+ if (((const struct afb_api_item*)caller->context.api_key)->group == api->group) {
/* noconcurrency lock detected */
- ERROR("self-lock detected in call stack for API %s", xreq->request.api);
- early_failure(xreq, "self-locked", "recursive self lock, API %s", xreq->request.api);
+ ERROR("self-lock detected in call stack for API %s", xreq->request.called_api);
+ early_failure(xreq, "self-locked", "recursive self lock, API %s", xreq->request.called_api);
goto end;
}
caller = caller->caller;
@@ -1162,3 +932,8 @@ end:
afb_xreq_unhooked_unref(xreq);
}
+const char *xreq_on_behalf_cred_export(struct afb_xreq *xreq)
+{
+ return xreq->caller ? afb_cred_export(xreq->cred) : NULL;
+}
+
diff --git a/src/afb-xreq.h b/src/afb-xreq.h
index ae1419fb..5c748d6f 100644
--- a/src/afb-xreq.h
+++ b/src/afb-xreq.h
@@ -17,8 +17,9 @@
#pragma once
-#include <afb/afb-request-itf.h>
-#include <afb/afb-req-itf.h>
+#include <stdarg.h>
+#include <afb/afb-req-x1-itf.h>
+#include <afb/afb-req-x2-itf.h>
#include "afb-context.h"
struct json_object;
@@ -26,29 +27,20 @@ struct afb_evt_listener;
struct afb_xreq;
struct afb_cred;
struct afb_apiset;
-struct afb_api_dyn_verb;
-struct afb_eventid;
+struct afb_event_x2;
struct afb_verb_desc_v1;
struct afb_verb_v2;
-struct afb_req;
+struct afb_verb_v3;
+struct afb_req_x1;
struct afb_stored_req;
struct afb_xreq_query_itf {
struct json_object *(*json)(struct afb_xreq *xreq);
struct afb_arg (*get)(struct afb_xreq *xreq, const char *name);
- void (*success)(struct afb_xreq *xreq, struct json_object *obj, const char *info);
- void (*fail)(struct afb_xreq *xreq, const char *status, const char *info);
- void (*reply)(struct afb_xreq *xreq, int status, struct json_object *obj);
+ void (*reply)(struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info);
void (*unref)(struct afb_xreq *xreq);
- int (*subscribe)(struct afb_xreq *xreq, struct afb_eventid *eventid);
- int (*unsubscribe)(struct afb_xreq *xreq, struct afb_eventid *eventid);
- void (*subcall)(
- struct afb_xreq *xreq,
- const char *api,
- const char *verb,
- struct json_object *args,
- void (*callback)(void*, int, struct json_object*),
- void *cb_closure);
+ int (*subscribe)(struct afb_xreq *xreq, struct afb_event_x2 *event);
+ int (*unsubscribe)(struct afb_xreq *xreq, struct afb_event_x2 *event);
};
/**
@@ -56,7 +48,7 @@ struct afb_xreq_query_itf {
*/
struct afb_xreq
{
- struct afb_request request; /**< exported request */
+ struct afb_req_x2 request; /**< exported request */
struct afb_context context; /**< context of the request */
struct afb_apiset *apiset; /**< apiset of the xreq */
struct json_object *json; /**< the json object (or NULL) */
@@ -90,49 +82,65 @@ struct afb_xreq
#define CONTAINER_OF_XREQ(type,x) CONTAINER_OF(type,xreq,x)
/* req wrappers for xreq */
-extern struct afb_req afb_xreq_unstore(struct afb_stored_req *sreq);
+extern struct afb_req_x1 afb_xreq_unstore(struct afb_stored_req *sreq);
extern void afb_xreq_addref(struct afb_xreq *xreq);
extern void afb_xreq_unref(struct afb_xreq *xreq);
extern void afb_xreq_unhooked_addref(struct afb_xreq *xreq);
extern void afb_xreq_unhooked_unref(struct afb_xreq *xreq);
+extern struct json_object *afb_xreq_unhooked_json(struct afb_xreq *xreq);
extern struct json_object *afb_xreq_json(struct afb_xreq *xreq);
-extern void afb_xreq_success(struct afb_xreq *xreq, struct json_object *obj, const char *info);
-extern void afb_xreq_success_f(struct afb_xreq *xreq, struct json_object *obj, const char *info, ...);
+extern void afb_xreq_reply(struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info);
+extern void afb_xreq_reply_f(struct afb_xreq *xreq, struct json_object *obj, const char *error, const char *info, ...);
-extern void afb_xreq_fail(struct afb_xreq *xreq, const char *status, const char *info);
-extern void afb_xreq_fail_f(struct afb_xreq *xreq, const char *status, const char *info, ...);
-extern void afb_xreq_fail_unknown_api(struct afb_xreq *xreq);
-extern void afb_xreq_fail_unknown_verb(struct afb_xreq *xreq);
+extern void afb_xreq_reply_unknown_api(struct afb_xreq *xreq);
+extern void afb_xreq_reply_unknown_verb(struct afb_xreq *xreq);
extern const char *afb_xreq_raw(struct afb_xreq *xreq, size_t *size);
-extern int afb_xreq_subscribe(struct afb_xreq *xreq, struct afb_eventid *eventid);
-extern int afb_xreq_unsubscribe(struct afb_xreq *xreq, struct afb_eventid *eventid);
+extern int afb_xreq_subscribe(struct afb_xreq *xreq, struct afb_event_x2 *event);
+extern int afb_xreq_unsubscribe(struct afb_xreq *xreq, struct afb_event_x2 *event);
-extern void afb_xreq_subcall(
+extern void afb_xreq_legacy_subcall(
struct afb_xreq *xreq,
const char *api,
const char *verb,
struct json_object *args,
- void (*callback)(void*, int, struct json_object*, struct afb_request *),
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x2 *),
void *cb_closure);
-extern void afb_xreq_unhooked_subcall(
+extern void afb_xreq_unhooked_legacy_subcall(
struct afb_xreq *xreq,
const char *api,
const char *verb,
struct json_object *args,
- void (*callback)(void*, int, struct json_object*, struct afb_request *),
+ void (*callback)(void*, int, struct json_object*, struct afb_req_x2 *),
void *cb_closure);
-extern int afb_xreq_unhooked_subcall_sync(
+extern void afb_xreq_subcall(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_req_x2 *),
+ void *closure);
+extern void afb_xreq_unhooked_subcall(
+ struct afb_xreq *xreq,
+ const char *api,
+ const char *verb,
+ struct json_object *args,
+ int flags,
+ void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_req_x2 *),
+ void *closure);
+
+extern int afb_xreq_unhooked_legacy_subcall_sync(
struct afb_xreq *xreq,
const char *api,
const char *verb,
struct json_object *args,
struct json_object **result);
-extern int afb_xreq_subcall_sync(
+extern int afb_xreq_legacy_subcall_sync(
struct afb_xreq *xreq,
const char *api,
const char *verb,
@@ -146,23 +154,24 @@ extern void afb_xreq_process(struct afb_xreq *xreq, struct afb_apiset *apiset);
extern void afb_xreq_call_verb_v1(struct afb_xreq *xreq, const struct afb_verb_desc_v1 *verb);
extern void afb_xreq_call_verb_v2(struct afb_xreq *xreq, const struct afb_verb_v2 *verb);
-extern void afb_xreq_call_verb_vdyn(struct afb_xreq *xreq, const struct afb_api_dyn_verb *verb);
+extern void afb_xreq_call_verb_v3(struct afb_xreq *xreq, const struct afb_verb_v3 *verb);
+
+extern const char *xreq_on_behalf_cred_export(struct afb_xreq *xreq);
/******************************************************************************/
-static inline struct afb_req xreq_to_req(struct afb_xreq *xreq)
+static inline struct afb_req_x1 xreq_to_req_x1(struct afb_xreq *xreq)
{
- return (struct afb_req){ .itf = xreq->request.itf, .closure = &xreq->request };
+ return (struct afb_req_x1){ .itf = xreq->request.itf, .closure = &xreq->request };
}
-static inline struct afb_request *xreq_to_request(struct afb_xreq *xreq)
+static inline struct afb_req_x2 *xreq_to_req_x2(struct afb_xreq *xreq)
{
return &xreq->request;
}
-static inline struct afb_xreq *xreq_from_request(struct afb_request *request)
+static inline struct afb_xreq *xreq_from_req_x2(struct afb_req_x2 *req)
{
- return CONTAINER_OF(struct afb_xreq, request, request);
+ return CONTAINER_OF(struct afb_xreq, request, req);
}
-
diff --git a/src/afs-config.c b/src/afs-config.c
index 78fee7dc..70a6d475 100644
--- a/src/afs-config.c
+++ b/src/afs-config.c
@@ -263,11 +263,11 @@ static void parse_arguments(int argc, char **argv, struct afs_config *config)
while ((optc = getopt_long(argc, argv, shortopts, gnuOptions, NULL)) != EOF) {
switch (optc) {
case SET_VERBOSE:
- verbosity++;
+ verbose_inc();
break;
case SET_QUIET:
- verbosity--;
+ verbose_dec();
break;
case SET_TCP_PORT:
@@ -441,7 +441,7 @@ struct afs_config *afs_config_parse_arguments(int argc, char **argv)
parse_environment(result);
parse_arguments(argc, argv, result);
fulfill_config(result);
- if (verbosity >= 3)
+ if (verbose_wants(Log_Level_Info))
afs_config_dump(result);
return result;
}
diff --git a/src/afs-supervision.h b/src/afs-supervision.h
index 2c76f249..25d1b4b1 100644
--- a/src/afs-supervision.h
+++ b/src/afs-supervision.h
@@ -45,5 +45,5 @@ struct afs_supervision_initiator
char extra[27]; /**< zero terminated extra computed here to be 64-37 */
};
-#define AFS_SUPERVISION_APINAME "$"
+#define AFS_SUPERVISION_APINAME "."
#define AFS_SUPERVISOR_APINAME "supervisor"
diff --git a/src/afs-supervisor.c b/src/afs-supervisor.c
index 285d82cb..6bd1fc62 100644
--- a/src/afs-supervisor.c
+++ b/src/afs-supervisor.c
@@ -28,13 +28,15 @@
#include <sys/un.h>
#include <json-c/json.h>
-#include <afb/afb-binding-v2.h>
+
+#define AFB_BINDING_VERSION 3
+#include <afb/afb-binding.h>
#include "afb-cred.h"
#include "afb-stub-ws.h"
#include "afb-api.h"
#include "afb-xreq.h"
-#include "afb-api-so-v2.h"
+#include "afb-api-v3.h"
#include "afb-apiset.h"
#include "afb-fdev.h"
@@ -76,6 +78,10 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/* list of supervised daemons */
static struct supervised *superviseds;
+/* events */
+static afb_event_t event_add_pid;
+static afb_event_t event_del_pid;
+
/*************************************************************************************/
@@ -155,7 +161,7 @@ static int send_initiator(int fd, const char *command)
}
/*
- * checks whether the incomming supervised represented by its creds
+ * checks whether the incoming supervised represented by its creds
* is to be accepted or not.
* return 1 if yes or 0 otherwise.
*/
@@ -171,11 +177,15 @@ static void on_supervised_hangup(struct afb_stub_ws *stub)
ps = &superviseds;
while ((s = *ps) && s->stub != stub)
ps = &s->next;
- if (s) {
+ if (s)
*ps = s->next;
- afb_stub_ws_unref(stub);
- }
pthread_mutex_unlock(&mutex);
+ afb_stub_ws_unref(stub);
+ if (s) {
+ afb_event_push(event_del_pid, json_object_new_int((int)s->cred->pid));
+ afb_cred_unref(s->cred);
+ free(s);
+ }
}
/*
@@ -246,8 +256,10 @@ static void accept_supervision_link(int sock)
rc = send_initiator(fd, NULL);
if (!rc) {
rc = make_supervised(fd, cred);
- if (!rc)
+ if (!rc) {
+ afb_event_push(event_add_pid, json_object_new_int((int)cred->pid));
return;
+ }
}
}
afb_cred_unref(cred);
@@ -290,9 +302,27 @@ int afs_supervisor_discover()
/*************************************************************************************/
-static struct afb_binding_data_v2 datav2;
+static void f_subscribe(afb_req_t req)
+{
+ struct json_object *args = afb_req_json(req);
+ int revoke, ok;
+
+ revoke = json_object_is_type(args, json_type_boolean)
+ && !json_object_get_boolean(args);
-static void f_list(struct afb_req req)
+ ok = 1;
+ if (!revoke) {
+ ok = !afb_req_subscribe(req, event_add_pid)
+ && !afb_req_subscribe(req, event_del_pid);
+ }
+ if (revoke || !ok) {
+ afb_req_unsubscribe(req, event_add_pid);
+ afb_req_unsubscribe(req, event_del_pid);
+ }
+ afb_req_reply(req, NULL, ok ? NULL : "error", NULL);
+}
+
+static void f_list(afb_req_t req)
{
char pid[50];
struct json_object *resu, *item;
@@ -317,82 +347,82 @@ static void f_list(struct afb_req req)
afb_req_success(req, resu, NULL);
}
-static void f_discover(struct afb_req req)
+static void f_discover(afb_req_t req)
{
afs_supervisor_discover();
afb_req_success(req, NULL, NULL);
}
-static void propagate(struct afb_req req, const char *verb)
+static void propagate(afb_req_t req, const char *verb)
{
struct afb_xreq *xreq;
struct json_object *args, *item;
struct supervised *s;
- struct afb_api api;
+ struct afb_api_item api;
int p;
- xreq = xreq_from_request(req.closure);
+ xreq = xreq_from_req_x2(req);
args = afb_xreq_json(xreq);
if (!json_object_object_get_ex(args, "pid", &item)) {
- afb_xreq_fail(xreq, "no-pid", NULL);
+ afb_xreq_reply(xreq, NULL, "no-pid", NULL);
return;
}
errno = 0;
p = json_object_get_int(item);
if (!p && errno) {
- afb_xreq_fail(xreq, "bad-pid", NULL);
+ afb_xreq_reply(xreq, NULL, "bad-pid", NULL);
return;
}
s = supervised_of_pid((pid_t)p);
if (!s) {
- afb_req_fail(req, "unknown-pid", NULL);
+ afb_req_reply(req, NULL, "unknown-pid", NULL);
return;
}
json_object_object_del(args, "pid");
if (verb)
- xreq->request.verb = verb;
+ xreq->request.called_verb = verb;
api = afb_stub_ws_client_api(s->stub);
api.itf->call(api.closure, xreq);
}
-static void f_do(struct afb_req req)
+static void f_do(afb_req_t req)
{
propagate(req, NULL);
}
-static void f_config(struct afb_req req)
+static void f_config(afb_req_t req)
{
propagate(req, NULL);
}
-static void f_trace(struct afb_req req)
+static void f_trace(afb_req_t req)
{
propagate(req, NULL);
}
-static void f_sessions(struct afb_req req)
+static void f_sessions(afb_req_t req)
{
propagate(req, "slist");
}
-static void f_session_close(struct afb_req req)
+static void f_session_close(afb_req_t req)
{
propagate(req, "sclose");
}
-static void f_exit(struct afb_req req)
+static void f_exit(afb_req_t req)
{
propagate(req, NULL);
afb_req_success(req, NULL, NULL);
}
-static void f_debug_wait(struct afb_req req)
+static void f_debug_wait(afb_req_t req)
{
propagate(req, "wait");
afb_req_success(req, NULL, NULL);
}
-static void f_debug_break(struct afb_req req)
+static void f_debug_break(afb_req_t req)
{
propagate(req, "break");
afb_req_success(req, NULL, NULL);
@@ -403,10 +433,22 @@ static void f_debug_break(struct afb_req req)
/**
* initialize the supervisor
*/
-static int init_supervisor()
+static int init_supervisor(afb_api_t api)
{
int rc, fd;
+ event_add_pid = afb_api_make_event(api, "add-pid");
+ if (!afb_event_is_valid(event_add_pid)) {
+ ERROR("Can't create added event");
+ return -1;
+ }
+
+ event_del_pid = afb_api_make_event(api, "del-pid");
+ if (!afb_event_is_valid(event_del_pid)) {
+ ERROR("Can't create deleted event");
+ return -1;
+ }
+
/* create an empty set for superviseds */
empty_apiset = afb_apiset_create(supervision_apiname, 0);
if (!empty_apiset) {
@@ -448,93 +490,102 @@ static const struct afb_auth _afb_auths_v2_supervisor[] = {
}
};
-static const struct afb_verb_v2 _afb_verbs_v2_supervisor[] = {
+static const struct afb_verb_v3 _afb_verbs_supervisor[] = {
+ {
+ .verb = "subscribe",
+ .callback = f_subscribe,
+ .auth = &_afb_auths_v2_supervisor[0],
+ .info = NULL,
+ .session = AFB_SESSION_CHECK_X2
+ },
{
.verb = "list",
.callback = f_list,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{
.verb = "config",
.callback = f_config,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{
.verb = "do",
.callback = f_do,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{
.verb = "trace",
.callback = f_trace,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{
.verb = "sessions",
.callback = f_sessions,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{
.verb = "session-close",
.callback = f_session_close,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{
.verb = "exit",
.callback = f_exit,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{
.verb = "debug-wait",
.callback = f_debug_wait,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{
.verb = "debug-break",
.callback = f_debug_break,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{
.verb = "discover",
.callback = f_discover,
.auth = &_afb_auths_v2_supervisor[0],
.info = NULL,
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK_X2
},
{ .verb = NULL }
};
-static const struct afb_binding_v2 _afb_binding_v2_supervisor = {
+static const struct afb_binding_v3 _afb_binding_supervisor = {
.api = supervisor_apiname,
.specification = NULL,
.info = NULL,
- .verbs = _afb_verbs_v2_supervisor,
+ .verbs = _afb_verbs_supervisor,
.preinit = NULL,
.init = init_supervisor,
.onevent = NULL,
.noconcurrency = 0
};
-int afs_supervisor_add(struct afb_apiset *apiset)
+int afs_supervisor_add(
+ struct afb_apiset *declare_set,
+ struct afb_apiset * call_set)
{
- return afb_api_so_v2_add_binding(&_afb_binding_v2_supervisor, NULL, apiset, &datav2);
+ return -!afb_api_v3_from_binding(&_afb_binding_supervisor, declare_set, call_set);
}
diff --git a/src/afs-supervisor.h b/src/afs-supervisor.h
index aeae6c72..08768ae7 100644
--- a/src/afs-supervisor.h
+++ b/src/afs-supervisor.h
@@ -19,5 +19,6 @@
extern int afs_supervisor_discover();
-extern int afs_supervisor_add(struct afb_apiset *apiset);
-
+extern int afs_supervisor_add(
+ struct afb_apiset *declare_set,
+ struct afb_apiset * call_set);
diff --git a/src/devtools/genskel.c b/src/devtools/genskel.c
index a0a78815..55dd3c15 100644
--- a/src/devtools/genskel.c
+++ b/src/devtools/genskel.c
@@ -62,6 +62,7 @@ struct path
/**
* root of the JSON being parsed
*/
+int version = 3;
struct json_object *root = NULL;
struct json_object *d_perms = NULL;
struct json_object *a_perms = NULL;
@@ -78,8 +79,8 @@ int noconc = -1;
int cpp = 0;
/**
- * Search for a reference of type "#/a/b/c" int the
- * parsed JSON object
+ * Search for a reference of type "#/a/b/c" in the
+ * parsed JSON object (root)
*/
struct json_object *search(const char *path)
{
@@ -170,6 +171,7 @@ struct json_object *expand_$ref(struct path path)
return path.object;
}
+/* create c name by replacing non alpha numeric characters with underscores */
char *cify(const char *str)
{
char *r = strdup(str);
@@ -182,6 +184,7 @@ char *cify(const char *str)
return r;
}
+/* format the specification as a C string */
char *make_info(const char *text, int split)
{
const char *a, *b;
@@ -260,11 +263,13 @@ char *make_info(const char *text, int split)
return desc;
}
+/* make the description of the object */
char *make_desc(struct json_object *o)
{
- return make_info(json_object_to_json_string_ext(root, 0), 1);
+ return make_info(json_object_to_json_string_ext(o, 0), 1);
}
+/* get the permission odescription if set */
struct json_object *permissions_of_verb(struct json_object *obj)
{
struct json_object *x, *y;
@@ -279,6 +284,7 @@ struct json_object *permissions_of_verb(struct json_object *obj)
return NULL;
}
+/* output the array of permissions */
void print_perms()
{
int i, n;
@@ -286,7 +292,7 @@ void print_perms()
n = a_perms ? json_object_array_length(a_perms) : 0;
if (n) {
- printf("static const struct afb_auth _afb_auths_v2_%s[] = {\n" , capi);
+ printf("static const struct afb_auth _afb_auths_%s[] = {\n" , capi);
i = 0;
while (i < n) {
printf(fmtstr, json_object_get_string(json_object_array_get_idx(a_perms, i)));
@@ -296,6 +302,10 @@ void print_perms()
}
}
+/*
+ * search in the global object 'd_perm' the computed representation
+ * of the permission described either by 'obj' or 'desc'
+ */
struct json_object *new_perm(struct json_object *obj, const char *desc)
{
const char *tag;
@@ -304,12 +314,15 @@ struct json_object *new_perm(struct json_object *obj, const char *desc)
tag = obj ? json_object_to_json_string_ext(obj, 0) : desc;
if (!json_object_object_get_ex(d_perms, tag, &y)) {
+
+ /* creates the d_perms dico and the a_perms array */
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));
+ /* creates the reference in the structure */
+ asprintf(&b, "&_afb_auths_%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);
@@ -323,6 +336,7 @@ struct json_object *decl_perm(struct json_object *obj);
enum optype { And, Or };
+/* recursive declare and/or permissions */
struct json_object *decl_perm_a(enum optype op, struct json_object *obj)
{
int i, n;
@@ -354,16 +368,22 @@ struct json_object *decl_perm_a(enum optype op, struct json_object *obj)
return x;
}
+/* declare the permission for obj */
struct json_object *decl_perm(struct json_object *obj)
{
char *a;
+ const char *fmt;
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, cpp ? "afb::auth_permission(\"%s\")" : ".type = afb_auth_Permission, .text = \"%s\"", json_object_get_string(x));
+ if (cpp)
+ fmt = "afb::auth_permission(\"%s\")";
+ else
+ fmt = ".type = afb_auth_Permission, .text = \"%s\"";
+ asprintf(&a, fmt, json_object_get_string(x));
y = new_perm(obj, a);
free(a);
}
@@ -375,7 +395,11 @@ struct json_object *decl_perm(struct json_object *obj)
}
else if (json_object_object_get_ex(obj, "not", &x)) {
x = decl_perm(x);
- asprintf(&a, cpp ? "afb::auth_not(%s)" : ".type = afb_auth_Not, .first = %s", json_object_get_string(x));
+ if (cpp)
+ fmt = "afb::auth_not(%s)";
+ else
+ fmt = ".type = afb_auth_Not, .first = %s";
+ asprintf(&a, fmt, json_object_get_string(x));
y = new_perm(obj, a);
free(a);
}
@@ -477,7 +501,7 @@ void print_session(struct json_object *p)
s = p ? get_session(p) : 0;
c = 1;
if (s & SESSION_CHECK) {
- printf("%s", "|AFB_SESSION_CHECK_V2" + c);
+ printf("%s", "|AFB_SESSION_CHECK" + c);
c = 0;
}
if (s & SESSION_LOA_3 & ~SESSION_LOA_2)
@@ -489,19 +513,19 @@ void print_session(struct json_object *p)
else
l = 0;
if (l) {
- printf("%s%d_V2", "|AFB_SESSION_LOA_" + c, l);
+ printf("%s%d", "|AFB_SESSION_LOA_" + c, l);
c = 0;
}
if (s & SESSION_CLOSE) {
- printf("%s", "|AFB_SESSION_CLOSE_V2" + c);
+ printf("%s", "|AFB_SESSION_CLOSE" + c);
c = 0;
}
if (s & SESSION_RENEW) {
- printf("%s", "|AFB_SESSION_REFRESH_V2" + c);
+ printf("%s", "|AFB_SESSION_REFRESH" + c);
c = 0;
}
if (c)
- printf("AFB_SESSION_NONE_V2");
+ printf("AFB_SESSION_NONE");
}
void print_verb(const char *name)
@@ -513,7 +537,7 @@ void print_declare_verb(const char *name, struct json_object *obj)
{
printf("%s void ", scope);
print_verb(name);
- printf("(struct afb_req req);\n");
+ printf("(afb_req req);\n");
}
void print_struct_verb(const char *name, struct json_object *obj)
@@ -542,6 +566,12 @@ void print_struct_verb(const char *name, struct json_object *obj)
, info ? make_info(info, 0) : "NULL"
);
print_session(p);
+ if (version == 3)
+ printf(
+ ",\n"
+ " .vcbdata = NULL,\n"
+ " .glob = 0"
+ );
printf(
"\n"
" },\n"
@@ -646,7 +676,7 @@ void process(char *filename)
/* get the API name */
printf(
"\n"
- "static const char _afb_description_v2_%s[] =\n"
+ "static const char _afb_description_%s[] =\n"
"%s"
";\n"
"\n"
@@ -657,8 +687,8 @@ void process(char *filename)
enum_verbs(print_declare_verb);
printf(
"\n"
- "static const struct afb_verb_v2 _afb_verbs_v2_%s[] = {\n"
- , capi
+ "static const struct afb_verb_v%d _afb_verbs_%s[] = {\n"
+ , version, capi
);
enum_verbs(print_struct_verb);
printf(
@@ -667,25 +697,36 @@ void process(char *filename)
" .callback = NULL,\n"
" .auth = NULL,\n"
" .info = NULL,\n"
- " .session = 0\n"
+ " .session = 0"
+ );
+ if (version == 3)
+ printf(
+ ",\n"
+ " .vcbdata = NULL,\n"
+ " .glob = 0"
+ );
+ printf(
+ "\n"
" }\n"
"};\n"
);
printf(
"\n"
- "%sconst struct afb_binding_v2 %s%s = {\n"
+ "%sconst struct afb_binding_v%d %s%s = {\n"
" .api = \"%s\",\n"
- " .specification = _afb_description_v2_%s,\n"
+ " .specification = _afb_description_%s,\n"
" .info = %s,\n"
- " .verbs = _afb_verbs_v2_%s,\n"
+ " .verbs = _afb_verbs_%s,\n"
" .preinit = %s,\n"
" .init = %s,\n"
" .onevent = %s,\n"
+ "%s"
" .noconcurrency = %d\n"
"};\n"
"\n"
, priv ? "static " : ""
- , priv ? "_afb_binding_v2_" : "afbBindingV2"
+ , version
+ , priv ? "_afb_binding_" : version==3 ? "afbBindingV3" : "afbBindingV2"
, priv ? capi : ""
, api
, capi
@@ -694,6 +735,7 @@ void process(char *filename)
, preinit ?: "NULL"
, init ?: "NULL"
, onevent ?: "NULL"
+ , version==3 ? " .userdata = NULL,\n" : ""
, !!noconc
);
@@ -705,11 +747,25 @@ void process(char *filename)
/** process the list of files or stdin if none */
int main(int ac, char **av)
{
+ int r, w;
av++;
- if (*av && !(strcmp(*av, "-x") && strcmp(*av, "--cpp"))) {
- cpp = 1;
- av++;
+
+ r = w = 0;
+ while (av[r]) {
+ if (!(strcmp(av[r], "-x") && strcmp(av[r], "--cpp"))) {
+ cpp = 1;
+ r++;
+ } else if (!strcmp(av[r], "-2")) {
+ version = 2;
+ r++;
+ } else if (!strcmp(av[r], "-3")) {
+ version = 3;
+ r++;
+ } else {
+ av[w++] = av[r++];
+ }
}
+ av[w] = NULL;
if (!*av)
process("-");
else {
@@ -718,7 +774,3 @@ int main(int ac, char **av)
return 0;
}
-
-
-
-
diff --git a/src/devtools/monitor-api.json b/src/devtools/monitor-api.json
index 3c8867cd..ca4a9b37 100644
--- a/src/devtools/monitor-api.json
+++ b/src/devtools/monitor-api.json
@@ -172,11 +172,11 @@
"end",
"event",
"extra",
- "fail",
"get",
"json",
"life",
"ref",
+ "reply",
"result",
"session",
"session_close",
@@ -190,7 +190,6 @@
"subcallsync",
"subcallsync_result",
"subscribe",
- "success",
"unref",
"unstore",
"unsubscribe",
@@ -306,8 +305,8 @@
"paths": {
"/get": {
"description": "Get monitoring data.",
+ "x-permissions": { "session": "check" },
"get": {
- "x-permissions": { "session": "check" },
"parameters": [
{
"in": "query",
@@ -338,8 +337,8 @@
},
"/set": {
"description": "Set monitoring actions.",
+ "x-permissions": { "session": "check" },
"get": {
- "x-permissions": { "session": "check" },
"parameters": [
{
"in": "query",
@@ -364,8 +363,8 @@
},
"/trace": {
"description": "Set monitoring actions.",
+ "x-permissions": { "session": "check" },
"get": {
- "x-permissions": { "session": "check" },
"parameters": [
{
"in": "query",
@@ -396,8 +395,8 @@
},
"/session": {
"description": "describes the session.",
+ "x-permissions": { "session": "check" },
"get": {
- "x-permissions": { "session": "check" },
"parameters": [
{
"in": "query",
diff --git a/src/jobs-fake.c b/src/jobs-fake.c
index d3444e32..d3cd19e1 100644
--- a/src/jobs-fake.c
+++ b/src/jobs-fake.c
@@ -71,7 +71,7 @@ static int add_job(const void *group, int timeout, void (*callback)(int signum,
else
first = j;
last = j;
- pthread_mutex_unlock(&mutex);
+ pthread_mutex_unlock(&mutex);
return 0;
}
@@ -83,7 +83,7 @@ static void *thrrun(void *arg)
j = first;
if (j)
first = j->next;
- pthread_mutex_unlock(&mutex);
+ pthread_mutex_unlock(&mutex);
if (j) {
j->callback(0, j->closure);
free(j);
diff --git a/src/jobs.c b/src/jobs.c
index 5980305a..26fc0157 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -716,7 +716,7 @@ static int on_evloop_efd(sd_event_source *s, int fd, uint32_t revents, void *use
struct evloop *evloop = userdata;
read(evloop->efd, &x, sizeof x);
pthread_mutex_lock(&mutex);
- pthread_cond_broadcast(&evloop->cond);
+ pthread_cond_broadcast(&evloop->cond);
pthread_mutex_unlock(&mutex);
return 1;
}
diff --git a/src/afb-client-demo.c b/src/main-afb-client-demo.c
index 011de2b5..4e865879 100644
--- a/src/afb-client-demo.c
+++ b/src/main-afb-client-demo.c
@@ -41,15 +41,13 @@ static void on_wsj1_call(void *closure, const char *api, const char *verb, struc
static void on_wsj1_event(void *closure, const char *event, struct afb_wsj1_msg *msg);
static void on_pws_hangup(void *closure);
-static void on_pws_reply_success(void *closure, void *request, struct json_object *result, const char *info);
-static void on_pws_reply_fail(void *closure, void *request, const char *status, const char *info);
+static void on_pws_reply(void *closure, void *request, struct json_object *result, const char *error, const char *info);
static void on_pws_event_create(void *closure, const char *event_name, int event_id);
static void on_pws_event_remove(void *closure, const char *event_name, int event_id);
static void on_pws_event_subscribe(void *closure, void *request, const char *event_name, int event_id);
static void on_pws_event_unsubscribe(void *closure, void *request, const char *event_name, int event_id);
static void on_pws_event_push(void *closure, const char *event_name, int event_id, struct json_object *data);
static void on_pws_event_broadcast(void *closure, const char *event_name, struct json_object *data);
-static void on_pws_subcall(void *closure, struct afb_proto_ws_subcall *subcall, void *request, const char *api, const char *verb, struct json_object *args);
static int io_event_callback(sd_event_source *src, int fd, uint32_t revents, void *closure);
@@ -65,15 +63,13 @@ static struct afb_wsj1_itf wsj1_itf = {
/* the callback interface for pws */
static struct afb_proto_ws_client_itf pws_itf = {
- .on_reply_success = on_pws_reply_success,
- .on_reply_fail = on_pws_reply_fail,
+ .on_reply = on_pws_reply,
.on_event_create = on_pws_event_create,
.on_event_remove = on_pws_event_remove,
.on_event_subscribe = on_pws_event_subscribe,
.on_event_unsubscribe = on_pws_event_unsubscribe,
.on_event_push = on_pws_event_push,
.on_event_broadcast = on_pws_event_broadcast,
- .on_subcall = on_pws_subcall,
};
/* global variables */
@@ -96,18 +92,18 @@ static void usage(int status, char *arg0)
name = name ? name + 1 : arg0;
fprintf(status ? stderr : stdout, "usage: %s [-H [-r]] [-b] [-e] uri [api verb [data]]\n", name);
fprintf(status ? stderr : stdout, " %s -d [-H [-r]] [-b] [-e] uri [verb [data]]\n", name);
- fprintf(status ? stderr : stdout, "\n" \
- "allowed options\n" \
- " --break, -b Break connection just after event/call has been emitted.\n" \
- " --direct, -d Direct api\n" \
- " --echo, -e Echo inputs\n" \
- " --help, -h Display this help\n" \
- " --human, -H Display human readable JSON\n" \
- " --raw, -r Raw output (default)\n" \
- "Example:\n" \
- " %s --human 'localhost:1234/api?token=HELLO&uuid=magic' hello ping\n"
- "\n", name
- );
+ fprintf(status ? stderr : stdout, "\n"
+ "allowed options\n"
+ " --break, -b Break connection just after event/call has been emitted.\n"
+ " --direct, -d Direct api\n"
+ " --echo, -e Echo inputs\n"
+ " --help, -h Display this help\n"
+ " --human, -H Display human readable JSON\n"
+ " --raw, -r Raw output (default)\n"
+ "Example:\n"
+ " %s --human 'localhost:1234/api?token=HELLO&uuid=magic' hello ping\n"
+ "\n", name
+ );
exit(status);
}
@@ -233,7 +229,7 @@ static void on_wsj1_call(void *closure, const char *api, const char *verb, struc
{
int rc;
if (raw)
- printf("%s", afb_wsj1_msg_object_s(msg));
+ printf("%s\n", afb_wsj1_msg_object_s(msg));
if (human)
printf("ON-CALL %s/%s:\n%s\n", api, verb,
json_object_to_json_string_ext(afb_wsj1_msg_object_j(msg),
@@ -248,7 +244,7 @@ static void on_wsj1_call(void *closure, const char *api, const char *verb, struc
static void on_wsj1_event(void *closure, const char *event, struct afb_wsj1_msg *msg)
{
if (raw)
- printf("%s", afb_wsj1_msg_object_s(msg));
+ printf("%s\n", afb_wsj1_msg_object_s(msg));
if (human)
printf("ON-EVENT %s:\n%s\n", event,
json_object_to_json_string_ext(afb_wsj1_msg_object_j(msg),
@@ -260,7 +256,7 @@ static void on_wsj1_event(void *closure, const char *event, struct afb_wsj1_msg
static void on_wsj1_reply(void *closure, struct afb_wsj1_msg *msg)
{
if (raw)
- printf("%s", afb_wsj1_msg_object_s(msg));
+ printf("%s\n", afb_wsj1_msg_object_s(msg));
if (human)
printf("ON-REPLY %s: %s\n%s\n", (char*)closure,
afb_wsj1_msg_is_reply_ok(msg) ? "OK" : "ERROR",
@@ -393,20 +389,25 @@ static int io_event_callback(sd_event_source *src, int fd, uint32_t revents, voi
return 1;
}
-static void on_pws_reply_success(void *closure, void *request, struct json_object *result, const char *info)
+static void on_pws_reply(void *closure, void *request, struct json_object *result, const char *error, const char *info)
{
- if (raw)
- printf("%s", json_object_to_json_string(result));
+ error = error ?: "success";
+ if (raw) {
+ /* TODO: transitionnal: fake the structured response */
+ struct json_object *x = json_object_new_object(), *y = json_object_new_object();
+ json_object_object_add(x, "jtype", json_object_new_string("afb-reply"));
+ json_object_object_add(x, "request", y);
+ json_object_object_add(y, "status", json_object_new_string(error));
+ if (info)
+ json_object_object_add(y, "info", json_object_new_string(info));
+ if (result)
+ json_object_object_add(x, "response", json_object_get(result));
+
+ printf("%s\n", json_object_to_json_string(x));
+ json_object_put(x);
+ }
if (human)
- printf("ON-REPLY-SUCCESS %s: %s\n%s\n", (char*)request, info?:"", json_object_to_json_string_ext(result, JSON_C_TO_STRING_PRETTY));
- fflush(stdout);
- free(request);
- dec_callcount();
-}
-
-static void on_pws_reply_fail(void *closure, void *request, const char *status, const char *info)
-{
- printf("ON-REPLY-FAIL %s: %s [%s]\n", (char*)request, status?:"?", info?:"");
+ printf("ON-REPLY %s: %s %s\n%s\n", (char*)request, error, info ?: "", json_object_to_json_string_ext(result, JSON_C_TO_STRING_PRETTY));
fflush(stdout);
free(request);
dec_callcount();
@@ -439,7 +440,7 @@ static void on_pws_event_unsubscribe(void *closure, void *request, const char *e
static void on_pws_event_push(void *closure, const char *event_name, int event_id, struct json_object *data)
{
if (raw)
- printf("%s", json_object_to_json_string(data));
+ printf("ON-EVENT-PUSH: [%d:%s]\n%s\n", event_id, event_name, json_object_to_json_string_ext(data, 0));
if (human)
printf("ON-EVENT-PUSH: [%d:%s]\n%s\n", event_id, event_name, json_object_to_json_string_ext(data, JSON_C_TO_STRING_PRETTY));
fflush(stdout);
@@ -448,22 +449,12 @@ static void on_pws_event_push(void *closure, const char *event_name, int event_i
static void on_pws_event_broadcast(void *closure, const char *event_name, struct json_object *data)
{
if (raw)
- printf("%s", json_object_to_json_string(data));
+ printf("ON-EVENT-BROADCAST: [%s]\n%s\n", event_name, json_object_to_json_string_ext(data, 0));
if (human)
printf("ON-EVENT-BROADCAST: [%s]\n%s\n", event_name, json_object_to_json_string_ext(data, JSON_C_TO_STRING_PRETTY));
fflush(stdout);
}
-static void on_pws_subcall(void *closure, struct afb_proto_ws_subcall *subcall, void *request, const char *api, const char *verb, struct json_object *args)
-{
- if (raw)
- printf("%s", json_object_to_json_string(args));
- if (human)
- printf("ON-SUBCALL %s: %s/%s\n%s\n", (char*)request, api, verb, json_object_to_json_string_ext(args, JSON_C_TO_STRING_PRETTY));
- afb_proto_ws_subcall_reply(subcall, 1, NULL);
- fflush(stdout);
-}
-
/* makes a call */
static void pws_call(const char *verb, const char *object)
{
@@ -488,7 +479,7 @@ static void pws_call(const char *verb, const char *object)
if (!o)
o = json_object_new_string(object);
}
- rc = afb_proto_ws_client_call(pws, verb, o, sessionid, key);
+ rc = afb_proto_ws_client_call(pws, verb, o, sessionid, key, NULL);
json_object_put(o);
if (rc < 0) {
fprintf(stderr, "calling %s(%s) failed: %m\n", verb, object?:"");
diff --git a/src/main.c b/src/main-afb-daemon.c
index 8c243f73..8b1a2b23 100644
--- a/src/main.c
+++ b/src/main-afb-daemon.c
@@ -39,6 +39,7 @@
#include "afb-config.h"
#include "afb-hswitch.h"
#include "afb-apiset.h"
+#include "afb-autoset.h"
#include "afb-api-so.h"
#if defined(WITH_DBUS_TRANSPARENCY)
# include "afb-api-dbus.h"
@@ -90,12 +91,13 @@ static struct afb_config_list *run_for_list(struct afb_config_list *list,
static int run_start(void *closure, char *value)
{
- int (*starter) (const char *value, struct afb_apiset *apiset) = closure;
- return starter(value, main_apiset) >= 0;
+ int (*starter) (const char *value, struct afb_apiset *declare_set, struct afb_apiset *call_set) = closure;
+ return starter(value, main_apiset, main_apiset) >= 0;
}
static void apiset_start_list(struct afb_config_list *list,
- int (*starter) (const char *value, struct afb_apiset *apiset), const char *message)
+ int (*starter) (const char *value, struct afb_apiset *declare_set, struct afb_apiset *call_set),
+ const char *message)
{
list = run_for_list(list, run_start, starter);
if (list) {
@@ -263,17 +265,17 @@ static struct afb_hsrv *start_http_server()
return NULL;
}
- if (!afb_hsrv_set_cache_timeout(hsrv, main_config->cacheTimeout)
+ if (!afb_hsrv_set_cache_timeout(hsrv, main_config->cache_timeout)
|| !init_http_server(hsrv)) {
ERROR("initialisation of httpd failed");
afb_hsrv_put(hsrv);
return NULL;
}
- NOTICE("Waiting port=%d rootdir=%s", main_config->httpdPort, main_config->rootdir);
- NOTICE("Browser URL= http://localhost:%d", main_config->httpdPort);
+ NOTICE("Waiting port=%d rootdir=%s", main_config->http_port, main_config->rootdir);
+ NOTICE("Browser URL= http://localhost:%d", main_config->http_port);
- rc = afb_hsrv_start(hsrv, (uint16_t) main_config->httpdPort, 15);
+ rc = afb_hsrv_start(hsrv, (uint16_t) main_config->http_port, 15);
if (!rc) {
ERROR("starting of httpd failed");
afb_hsrv_put(hsrv);
@@ -419,8 +421,8 @@ static int execute_command()
return 0;
/* compute the string for port */
- if (main_config->httpdPort)
- rc = snprintf(port, sizeof port, "%d", main_config->httpdPort);
+ if (main_config->http_port)
+ rc = snprintf(port, sizeof port, "%d", main_config->http_port);
else
rc = snprintf(port, sizeof port, "%cp", SUBST_CHAR);
if (rc < 0 || rc >= (int)(sizeof port)) {
@@ -455,14 +457,16 @@ struct startup_req
struct afb_session *session;
};
-static void startup_call_reply(struct afb_xreq *xreq, int status, struct json_object *obj)
+static void startup_call_reply(struct afb_xreq *xreq, struct json_object *object, const char *error, const char *info)
{
struct startup_req *sreq = CONTAINER_OF_XREQ(struct startup_req, xreq);
- if (status >= 0)
- NOTICE("startup call %s returned %s", sreq->current->value, json_object_get_string(obj));
- else {
- ERROR("startup call %s ERROR! %s", sreq->current->value, json_object_get_string(obj));
+ info = info ?: "";
+ if (!error) {
+ NOTICE("startup call %s returned %s (%s)", sreq->current->value, json_object_get_string(object), info);
+ json_object_put(object);
+ } else {
+ ERROR("startup call %s ERROR! %s (%s)", sreq->current->value, error, info);
exit(1);
}
}
@@ -506,8 +510,8 @@ static void startup_call_current(struct startup_req *sreq)
sreq->xreq.context.validated = 1;
sreq->api = strndup(api, verb - api);
sreq->verb = strndup(verb + 1, json - verb - 1);
- sreq->xreq.request.api = sreq->api;
- sreq->xreq.request.verb = sreq->verb;
+ sreq->xreq.request.called_api = sreq->api;
+ sreq->xreq.request.called_verb = sreq->verb;
sreq->xreq.json = json_tokener_parse(json + 1);
if (sreq->api && sreq->verb && sreq->xreq.json) {
afb_xreq_process(&sreq->xreq, main_apiset);
@@ -560,16 +564,16 @@ static void start(int signum, void *arg)
}
/* configure the daemon */
- if (afb_session_init(main_config->nbSessionMax, main_config->cntxTimeout, main_config->token)) {
+ if (afb_session_init(main_config->max_session_count, main_config->session_timeout, main_config->token)) {
ERROR("initialisation of session manager failed");
goto error;
}
- main_apiset = afb_apiset_create("main", main_config->apiTimeout);
+ main_apiset = afb_apiset_create("main", main_config->api_timeout);
if (!main_apiset) {
ERROR("can't create main api set");
goto error;
}
- if (afb_monitor_init() < 0) {
+ if (afb_monitor_init(main_apiset, main_apiset) < 0) {
ERROR("failed to setup monitor");
goto error;
}
@@ -581,10 +585,8 @@ static void start(int signum, void *arg)
/* install hooks */
if (main_config->tracereq)
afb_hook_create_xreq(NULL, NULL, NULL, main_config->tracereq, NULL, NULL);
- if (main_config->traceditf)
- afb_hook_create_ditf(NULL, main_config->traceditf, NULL, NULL);
- if (main_config->tracesvc)
- afb_hook_create_svc(NULL, main_config->tracesvc, NULL, NULL);
+ if (main_config->traceapi)
+ afb_hook_create_api(NULL, main_config->traceapi, NULL, NULL);
if (main_config->traceevt)
afb_hook_create_evt(NULL, main_config->traceevt, NULL, NULL);
if (main_config->traceses)
@@ -599,6 +601,8 @@ static void start(int signum, void *arg)
apiset_start_list(main_config->ws_clients, afb_api_ws_add_client_weak, "the afb-websocket client");
apiset_start_list(main_config->ldpaths, afb_api_so_add_pathset_fails, "the binding path set");
apiset_start_list(main_config->weak_ldpaths, afb_api_so_add_pathset_nofails, "the weak binding path set");
+ apiset_start_list(main_config->auto_ws, afb_autoset_add_ws, "the automatic afb-websocket path set");
+ apiset_start_list(main_config->auto_link, afb_autoset_add_so, "the automatic link binding path set");
#if defined(WITH_DBUS_TRANSPARENCY)
apiset_start_list(main_config->dbus_servers, afb_api_dbus_add_server, "the afb-dbus service");
@@ -617,13 +621,13 @@ static void start(int signum, void *arg)
/* start the HTTP server */
afb_debug("start-http");
- if (!main_config->noHttpd) {
- if (main_config->httpdPort <= 0) {
+ if (!main_config->no_httpd) {
+ if (main_config->http_port <= 0) {
ERROR("no port is defined");
goto error;
}
- if (!afb_hreq_init_cookie(main_config->httpdPort, main_config->rootapi, main_config->cntxTimeout)) {
+ if (!afb_hreq_init_cookie(main_config->http_port, main_config->rootapi, main_config->session_timeout)) {
ERROR("initialisation of HTTP cookies failed");
goto error;
}
diff --git a/src/afs-main.c b/src/main-afs-supervisor.c
index 88e4757f..14f1c3b0 100644
--- a/src/afs-main.c
+++ b/src/main-afs-supervisor.c
@@ -144,7 +144,7 @@ static void start(int signum, void *arg)
}
/* init the main apiset */
- rc = afs_supervisor_add(main_apiset);
+ rc = afs_supervisor_add(main_apiset, main_apiset);
if (rc < 0) {
ERROR("Can't create supervision's apiset: %m");
goto error;
@@ -152,7 +152,7 @@ static void start(int signum, void *arg)
/* export the service if required */
if (main_config->ws_server) {
- rc = afb_api_ws_add_server(main_config->ws_server, main_apiset);
+ rc = afb_api_ws_add_server(main_config->ws_server, main_apiset, main_apiset);
if (rc < 0) {
ERROR("Can't export (ws-server) api %s: %m", main_config->ws_server);
goto error;
diff --git a/src/monitor-api.inc b/src/monitor-api.inc
index cbc1187f..e4dc2c92 100644
--- a/src/monitor-api.inc
+++ b/src/monitor-api.inc
@@ -1,5 +1,5 @@
-static const char _afb_description_v2_monitor[] =
+static const char _afb_description_monitor[] =
"{\"openapi\":\"3.0.0\",\"info\":{\"description\":\"monitoring of binding"
"s and internals\",\"title\":\"monitor\",\"version\":\"1.0\",\"x-binding-"
"c-generator\":{\"api\":\"monitor\",\"version\":2,\"prefix\":\"f_\",\"pos"
@@ -118,57 +118,68 @@ static const char _afb_description_v2_monitor[] =
"}}}}}}}}}"
;
-static void f_get(struct afb_req req);
-static void f_set(struct afb_req req);
-static void f_trace(struct afb_req req);
-static void f_session(struct afb_req req);
+static void f_get(afb_req_t req);
+static void f_set(afb_req_t req);
+static void f_trace(afb_req_t req);
+static void f_session(afb_req_t req);
-static const struct afb_verb_v2 _afb_verbs_v2_monitor[] = {
+static const struct afb_verb_v3 _afb_verbs_monitor[] = {
{
.verb = "get",
.callback = f_get,
.auth = NULL,
.info = "Get monitoring data.",
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK,
+ .vcbdata = NULL,
+ .glob = 0
},
{
.verb = "set",
.callback = f_set,
.auth = NULL,
.info = "Set monitoring actions.",
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK,
+ .vcbdata = NULL,
+ .glob = 0
},
{
.verb = "trace",
.callback = f_trace,
.auth = NULL,
.info = "Set monitoring actions.",
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK,
+ .vcbdata = NULL,
+ .glob = 0
},
{
.verb = "session",
.callback = f_session,
.auth = NULL,
.info = "describes the session.",
- .session = AFB_SESSION_CHECK_V2
+ .session = AFB_SESSION_CHECK,
+ .vcbdata = NULL,
+ .glob = 0
},
{
.verb = NULL,
.callback = NULL,
.auth = NULL,
.info = NULL,
- .session = 0
+ .session = 0,
+ .vcbdata = NULL,
+ .glob = 0
}
};
-static const struct afb_binding_v2 _afb_binding_v2_monitor = {
+static const struct afb_binding_v3 _afb_binding_monitor = {
.api = "monitor",
- .specification = _afb_description_v2_monitor,
+ .specification = _afb_description_monitor,
.info = "monitoring of bindings and internals",
- .verbs = _afb_verbs_v2_monitor,
+ .verbs = _afb_verbs_monitor,
.preinit = NULL,
.init = NULL,
.onevent = NULL,
+ .userdata = NULL,
.noconcurrency = 0
};
diff --git a/src/pearson.c b/src/pearson.c
new file mode 100644
index 00000000..a39c8952
--- /dev/null
+++ b/src/pearson.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 "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.
+ */
+
+#include <stdint.h>
+
+/*
+ * Returns a tiny hash value for the 'text'.
+ *
+ * Tiny hash function inspired from pearson
+ */
+uint8_t pearson4(const char *text)
+{
+ static uint8_t T[16] = {
+ 4, 1, 6, 0, 9, 14, 11, 5,
+ 2, 3, 12, 15, 10, 7, 8, 13
+ };
+ uint8_t r, c;
+
+ for (r = 0; (c = (uint8_t)*text) ; text++) {
+ r = T[r ^ (15 & c)];
+ r = T[r ^ (c >> 4)];
+ }
+ return r; // % HEADCOUNT;
+}
+
diff --git a/src/pearson.h b/src/pearson.h
new file mode 100644
index 00000000..2daa6546
--- /dev/null
+++ b/src/pearson.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 "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.
+ */
+
+#pragma once
+
+extern uint8_t pearson4(const char *text);
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index f63f27ae..f0349a68 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -22,6 +22,8 @@ if(check_FOUND)
INCLUDE_DIRECTORIES(${INCLUDE_DIRS} ${check_INCLUDE_DIRS})
SET(link_libraries ${link_libraries} ${check_LDFLAGS})
add_subdirectory(session)
+ add_subdirectory(apiset)
+ add_subdirectory(apiv3)
else(check_FOUND)
MESSAGE(WARNING "check not found! no test!")
endif(check_FOUND)
diff --git a/src/tests/apiset/CMakeLists.txt b/src/tests/apiset/CMakeLists.txt
new file mode 100644
index 00000000..180c80b8
--- /dev/null
+++ b/src/tests/apiset/CMakeLists.txt
@@ -0,0 +1,23 @@
+###########################################################################
+# Copyright (C) 2018 "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.
+###########################################################################
+
+add_executable(test-apiset test-apiset.c)
+target_include_directories(test-apiset PRIVATE ../..)
+target_link_libraries(test-apiset afb-lib ${link_libraries})
+add_test(NAME apiset COMMAND test-apiset)
+
diff --git a/src/tests/apiset/test-apiset.c b/src/tests/apiset/test-apiset.c
new file mode 100644
index 00000000..bdc84137
--- /dev/null
+++ b/src/tests/apiset/test-apiset.c
@@ -0,0 +1,579 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+
+#include <check.h>
+#if !defined(ck_assert_ptr_null)
+# define ck_assert_ptr_null(X) ck_assert_ptr_eq(X, NULL)
+# define ck_assert_ptr_nonnull(X) ck_assert_ptr_ne(X, NULL)
+#endif
+
+#include "afb-api.h"
+#include "afb-apiset.h"
+
+const char *names[] = {
+ "Sadie",
+ "Milford",
+ "Yvette",
+ "Carma",
+ "Cory",
+ "Clarence",
+ "Jeffery",
+ "Molly",
+ "Sheba",
+ "Tasha",
+ "Corey",
+ "Gerry",
+ NULL
+};
+
+const char *aliases[] = {
+ "Rich", "Molly",
+ "Alicia", "Carma",
+ "Drema", "YVETTE",
+ "Pablo", "Sheba",
+ "Wendell", "Sadie",
+ "Cathrine", "CarMa",
+ "Allen", "Corey",
+ "Tori", "Drema",
+ NULL
+};
+
+const char *extras[] = {
+ "Meta",
+ "Delia",
+ "Pearlie",
+ "Hank",
+ "Vena",
+ "Terrance",
+ "Gloria",
+ "Tobi",
+ "Mack",
+ "Rosalee",
+ NULL
+};
+
+struct afb_api_itf api_itf_null = {
+ .call = NULL,
+ .service_start = NULL,
+ .update_hooks = NULL,
+ .get_logmask = NULL,
+ .set_logmask = NULL,
+ .describe = NULL,
+ .unref = NULL
+};
+
+
+/*********************************************************************/
+/* check the initialisation */
+START_TEST (check_initialisation)
+{
+ const char name[] = "name";
+ const char noname[] = "";
+ int to = 3600;
+ int noto = -1;
+ struct afb_apiset *a, *b;
+
+ a = afb_apiset_create(NULL, noto);
+ ck_assert_ptr_nonnull(a);
+ ck_assert_str_eq(noname, afb_apiset_name(a));
+ ck_assert_int_eq(noto, afb_apiset_timeout_get(a));
+ afb_apiset_timeout_set(a, to);
+ ck_assert_int_eq(to, afb_apiset_timeout_get(a));
+ b = afb_apiset_addref(a);
+ ck_assert_ptr_eq(a, b);
+ afb_apiset_unref(b);
+ afb_apiset_unref(a);
+
+ a = afb_apiset_create(name, to);
+ ck_assert_ptr_nonnull(a);
+ ck_assert_str_eq(name, afb_apiset_name(a));
+ ck_assert_int_eq(to, afb_apiset_timeout_get(a));
+ afb_apiset_timeout_set(a, noto);
+ ck_assert_int_eq(noto, afb_apiset_timeout_get(a));
+ b = afb_apiset_addref(a);
+ ck_assert_ptr_eq(a, b);
+ afb_apiset_unref(b);
+ afb_apiset_unref(a);
+}
+END_TEST
+
+/*********************************************************************/
+/* check that NULL is a valid value for addref/unref */
+START_TEST (check_sanity)
+{
+ struct afb_apiset *a;
+
+ a = afb_apiset_addref(NULL);
+ ck_assert_ptr_null(a);
+ afb_apiset_unref(NULL);
+ ck_assert(1);
+}
+END_TEST
+
+/*********************************************************************/
+/* check creation and retrieval of apis */
+
+START_TEST (check_creation)
+{
+ int i, j, nn, na;
+ struct afb_apiset *a;
+ struct afb_api_item sa;
+ const char *x, *y, **set;
+ const struct afb_api_item *pa;
+
+ /* create a apiset */
+ a = afb_apiset_create(NULL, 0);
+ ck_assert_ptr_nonnull(a);
+
+ /* add apis */
+ for (i = 0 ; names[i] != NULL ; i++) {
+ sa.itf = &api_itf_null;
+ sa.closure = (void*)names[i];
+ sa.group = names[i];
+ ck_assert_int_eq(0, afb_apiset_add(a, names[i], sa));
+ pa = afb_apiset_lookup(a, names[i], 1);
+ ck_assert_ptr_nonnull(pa);
+ ck_assert_ptr_eq(sa.itf, pa->itf);
+ ck_assert_ptr_eq(sa.closure, pa->closure);
+ ck_assert_ptr_eq(sa.group, pa->group);
+ ck_assert_int_eq(0, afb_apiset_is_alias(a, names[i]));
+ ck_assert_str_eq(names[i], afb_apiset_unalias(a, names[i]));
+ ck_assert_int_eq(-1, afb_apiset_add(a, names[i], sa));
+ ck_assert_int_eq(errno, EEXIST);
+ }
+ nn = i;
+
+ /* add aliases */
+ for (i = 0 ; aliases[i] != NULL ; i += 2) {
+ ck_assert_int_eq(-1, afb_apiset_add_alias(a, extras[0], aliases[i]));
+ ck_assert_int_eq(errno, ENOENT);
+ ck_assert_int_eq(0, afb_apiset_add_alias(a, aliases[i + 1], aliases[i]));
+ ck_assert_ptr_nonnull(afb_apiset_lookup(a, aliases[i], 1));
+ ck_assert_int_eq(1, afb_apiset_is_alias(a, aliases[i]));
+ x = afb_apiset_unalias(a, aliases[i]);
+ y = afb_apiset_unalias(a, aliases[i + 1]);
+ ck_assert_int_eq(0, strcasecmp(x, y));
+ ck_assert_int_eq(-1, afb_apiset_add_alias(a, aliases[i + 1], aliases[i]));
+ ck_assert_int_eq(errno, EEXIST);
+ }
+ na = i / 2;
+
+ /* check extras */
+ for (i = 0 ; extras[i] != NULL ; i++) {
+ pa = afb_apiset_lookup(a, extras[i], 1);
+ ck_assert_ptr_null(pa);
+ ck_assert_int_eq(errno, ENOENT);
+ }
+
+ /* get the names */
+ set = afb_apiset_get_names(a, 0, 1);
+ ck_assert_ptr_nonnull(set);
+ for (i = 0 ; set[i] != NULL ; i++) {
+ ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[i], 0));
+ ck_assert_int_eq(0, afb_apiset_is_alias(a, set[i]));
+ if (i)
+ ck_assert_int_gt(0, strcasecmp(set[i-1], set[i]));
+ }
+ ck_assert_int_eq(i, nn);
+ free(set);
+ set = afb_apiset_get_names(a, 0, 2);
+ ck_assert_ptr_nonnull(set);
+ for (i = 0 ; set[i] != NULL ; i++) {
+ ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[i], 0));
+ ck_assert_int_eq(1, afb_apiset_is_alias(a, set[i]));
+ if (i)
+ ck_assert_int_gt(0, strcasecmp(set[i-1], set[i]));
+ }
+ ck_assert_int_eq(i, na);
+ free(set);
+ set = afb_apiset_get_names(a, 0, 3);
+ ck_assert_ptr_nonnull(set);
+ for (i = 0 ; set[i] != NULL ; i++) {
+ ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[i], 0));
+ if (i)
+ ck_assert_int_gt(0, strcasecmp(set[i-1], set[i]));
+ }
+ ck_assert_int_eq(i, nn + na);
+
+ /* removes the apis to check deletion */
+ for (i = 0 ; i < nn + na ; i++) {
+ if (!set[i])
+ continue;
+
+ /* should be present */
+ ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[i], 0));
+
+ /* deleting a non aliased api removes the aliases! */
+ if (!afb_apiset_is_alias(a, set[i])) {
+ for (j = i + 1 ; j < nn + na ; j++) {
+ if (!set[j])
+ continue;
+ ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[j], 0));
+ if (afb_apiset_is_alias(a, set[j])
+ && afb_apiset_lookup(a, set[i], 0) == afb_apiset_lookup(a, set[j], 0)) {
+ ck_assert(set[j][0] > 0);
+ ((char*)set[j])[0] = (char)-set[j][0];
+ }
+ }
+ }
+
+ /* delete now */
+ ck_assert_int_eq(0, afb_apiset_del(a, set[i]));
+ ck_assert_ptr_null(afb_apiset_lookup(a, set[i], 0));
+
+ /* check other not removed except aliases */
+ for (j = i + 1 ; j < nn + na ; j++) {
+ if (!set[j])
+ continue;
+ if (set[j][0] > 0)
+ ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[j], 0));
+ else {
+ ((char*)set[j])[0] = (char)-set[j][0];
+ ck_assert_ptr_null(afb_apiset_lookup(a, set[j], 0));
+ set[j] = NULL;
+ }
+ }
+ }
+ free(set);
+
+ afb_apiset_unref(a);
+}
+END_TEST
+
+/*********************************************************************/
+/* check onlack behaviour */
+
+int onlackcount;
+
+static void onlackcleanup(void *closure)
+{
+ int *count = closure;
+ ck_assert_ptr_eq(count, &onlackcount);
+ *count = 0;
+}
+static int onlack(void *closure, struct afb_apiset *a, const char *name)
+{
+ int *count = closure;
+ struct afb_api_item sa;
+
+ ck_assert_ptr_eq(count, &onlackcount);
+ (*count)++;
+
+ sa.itf = &api_itf_null;
+ sa.closure = (void*)name;
+ sa.group = name;
+
+ ck_assert_int_eq(0, afb_apiset_add(a, name, sa));
+ return 1;
+}
+
+START_TEST (check_onlack)
+{
+ int i;
+ struct afb_apiset *a;
+ struct afb_api_item sa;
+ const char *x, *y;
+ const struct afb_api_item *pa;
+
+ /* create a apiset */
+ a = afb_apiset_create(NULL, 0);
+ ck_assert_ptr_nonnull(a);
+
+ /* add apis */
+ for (i = 0 ; names[i] != NULL ; i++) {
+ sa.itf = &api_itf_null;
+ sa.closure = (void*)names[i];
+ sa.group = names[i];
+ ck_assert_int_eq(0, afb_apiset_add(a, names[i], sa));
+ pa = afb_apiset_lookup(a, names[i], 1);
+ ck_assert_ptr_nonnull(pa);
+ ck_assert_ptr_eq(sa.itf, pa->itf);
+ ck_assert_ptr_eq(sa.closure, pa->closure);
+ ck_assert_ptr_eq(sa.group, pa->group);
+ ck_assert_int_eq(0, afb_apiset_is_alias(a, names[i]));
+ ck_assert_str_eq(names[i], afb_apiset_unalias(a, names[i]));
+ ck_assert_int_eq(-1, afb_apiset_add(a, names[i], sa));
+ ck_assert_int_eq(errno, EEXIST);
+ }
+
+ /* add aliases */
+ for (i = 0 ; aliases[i] != NULL ; i += 2) {
+ ck_assert_int_eq(-1, afb_apiset_add_alias(a, extras[0], aliases[i]));
+ ck_assert_int_eq(errno, ENOENT);
+ ck_assert_int_eq(0, afb_apiset_add_alias(a, aliases[i + 1], aliases[i]));
+ ck_assert_ptr_nonnull(afb_apiset_lookup(a, aliases[i], 1));
+ ck_assert_int_eq(1, afb_apiset_is_alias(a, aliases[i]));
+ x = afb_apiset_unalias(a, aliases[i]);
+ y = afb_apiset_unalias(a, aliases[i + 1]);
+ ck_assert_int_eq(0, strcasecmp(x, y));
+ ck_assert_int_eq(-1, afb_apiset_add_alias(a, aliases[i + 1], aliases[i]));
+ ck_assert_int_eq(errno, EEXIST);
+ }
+
+ /* check extras */
+ for (i = 0 ; extras[i] != NULL ; i++) {
+ pa = afb_apiset_lookup(a, extras[i], 1);
+ ck_assert_ptr_null(pa);
+ ck_assert_int_eq(errno, ENOENT);
+ }
+
+ /* put the onlack feature */
+ afb_apiset_onlack_set(a, onlack, &onlackcount, onlackcleanup);
+
+ /* check extras */
+ onlackcount = 0;
+ for (i = 0 ; extras[i] != NULL ; i++) {
+ ck_assert_int_eq(onlackcount, i);
+ pa = afb_apiset_lookup(a, extras[i], 1);
+ ck_assert_int_eq(onlackcount, i + 1);
+ ck_assert_ptr_nonnull(pa);
+ ck_assert_ptr_eq(&api_itf_null, pa->itf);
+ ck_assert_ptr_eq(extras[i], pa->closure);
+ ck_assert_ptr_eq(extras[i], pa->group);
+ }
+
+ ck_assert_int_eq(onlackcount, i);
+ afb_apiset_unref(a);
+ ck_assert_int_eq(onlackcount, 0);
+}
+END_TEST
+
+/*********************************************************************/
+
+struct set_api {
+ const char *name;
+ int init;
+ int mask;
+} set_apis[] = {
+ { "Sadie", 0, 0 },
+ { "Milford", 0, 0 },
+ { "Yvette", 0, 0 },
+ { "Carma", 0, 0 },
+ { "Cory", 0, 0 },
+ { "Clarence", 0, 0 },
+ { "Jeffery", 0, 0 },
+ { "Molly", 0, 0 },
+ { "Sheba", 0, 0 },
+ { "Tasha", 0, 0 },
+ { "Corey", 0, 0 },
+ { "Gerry", 0, 0 },
+ { NULL, 0, 0 }
+};
+
+int set_count;
+struct set_api *set_last_api;
+
+void set_cb0(void *closure)
+{
+ set_last_api = closure;
+ set_count++;
+}
+
+void set_cb_setmask(void *closure, int mask)
+{
+ set_cb0(closure);
+ set_last_api->mask = mask;
+}
+
+int set_cb_getmask(void *closure)
+{
+ set_cb0(closure);
+ return set_last_api->mask;
+}
+
+int set_cb_start(void *closure, int share_session, int onneed)
+{
+ set_cb0(closure);
+ ck_assert_int_eq(0, set_last_api->init);
+ set_last_api->init = 1;
+ return 0;
+}
+
+struct afb_api_itf set_api_itf = {
+ .call = NULL,
+ .service_start = set_cb_start,
+ .update_hooks = set_cb0,
+ .get_logmask = set_cb_getmask,
+ .set_logmask = set_cb_setmask,
+ .describe = NULL,
+ .unref = set_cb0
+};
+
+START_TEST (check_settings)
+{
+ int i, nn, mask;
+ struct afb_apiset *a;
+ struct afb_api_item sa;
+
+ /* create a apiset */
+ a = afb_apiset_create(NULL, 0);
+ ck_assert_ptr_nonnull(a);
+
+ /* add apis */
+ for (i = 0 ; set_apis[i].name != NULL ; i++) {
+ sa.itf = &set_api_itf;
+ sa.closure = &set_apis[i];
+ sa.group = NULL;
+ ck_assert_int_eq(0, afb_apiset_add(a, set_apis[i].name, sa));
+ }
+ nn = i;
+
+ set_count = 0;
+ afb_apiset_start_all_services(a, 1);
+ ck_assert_int_eq(nn, set_count);
+
+ set_count = 0;
+ afb_apiset_update_hooks(a, NULL);
+ ck_assert_int_eq(nn, set_count);
+
+ for (mask = 1 ; !(mask >> 10) ; mask <<= 1) {
+ set_count = 0;
+ afb_apiset_set_logmask(a, NULL, mask);
+ ck_assert_int_eq(nn, set_count);
+ set_count = 0;
+ for (i = 0 ; set_apis[i].name != NULL ; i++) {
+ ck_assert_int_eq(mask, afb_apiset_get_logmask(a, set_apis[i].name));
+ ck_assert_ptr_eq(set_last_api, &set_apis[i]);
+ ck_assert_int_eq(i + 1, set_count);
+ }
+ }
+
+ set_count = 0;
+ afb_apiset_unref(a);
+ ck_assert_int_eq(nn, set_count);
+}
+END_TEST
+
+/*********************************************************************/
+
+struct clacl {
+ const char *name;
+ int count;
+} clacl[] = {
+ { "Sadie", 0 },
+ { "Milford", 0 },
+ { "Yvette", 0 },
+};
+
+struct clapi {
+ const char *name;
+ const char *provides;
+ const char *requires;
+ const char *apireq;
+ int init;
+ int expect;
+} clapi[] = {
+ { "Carma", "", "Sadie", "", 0, 9 },
+ { "Cory", "Milford", "", "Clarence", 0, 3 },
+ { "Clarence", "Milford", "", "Jeffery", 0, 2 },
+ { "Jeffery", "Milford", "", "", 0, 1 },
+ { "Molly", "Yvette", "", "Corey", 0, 6 },
+ { "Sheba", "Yvette", "Milford", "Molly", 0, 7 },
+ { "Tasha", "Sadie", "Yvette", "", 0, 8 },
+ { "Corey", "Sadie", "Milford", "Gerry", 0, 5 },
+ { "Gerry", "Sadie", "Milford", "", 0, 4 },
+ { NULL, NULL, NULL, NULL, 0, 0 }
+};
+
+int clorder;
+
+int clacb_start(void *closure, int share_session, int onneed)
+{
+ struct clapi *a = closure;
+ int i;
+
+ ck_assert_int_eq(0, a->init);
+
+ for (i = 0 ; clapi[i].name ; i++) {
+ if (a->requires && a->requires[0]
+ && clapi[i].provides && clapi[i].provides[0]
+ && !strcmp(a->requires, clapi[i].provides))
+ ck_assert_int_ne(0, clapi[i].init);
+ if (a->apireq && a->apireq[0]
+ && !strcmp(a->apireq, clapi[i].name))
+ ck_assert_int_ne(0, clapi[i].init);
+ }
+ a->init = ++clorder;
+ ck_assert_int_eq(a->init, a->expect);
+
+ return 0;
+}
+
+struct afb_api_itf clitf = {
+ .call = NULL,
+ .service_start = clacb_start,
+ .update_hooks = NULL,
+ .get_logmask = NULL,
+ .set_logmask = NULL,
+ .describe = NULL,
+ .unref = NULL
+};
+
+START_TEST (check_classes)
+{
+ int i;
+ struct afb_apiset *a;
+ struct afb_api_item sa;
+
+ /* create a apiset */
+ a = afb_apiset_create(NULL, 0);
+ ck_assert_ptr_nonnull(a);
+
+ /* add apis */
+ for (i = 0 ; clapi[i].name != NULL ; i++) {
+ sa.itf = &clitf;
+ sa.closure = &clapi[i];
+ sa.group = NULL;
+ ck_assert_int_eq(0, afb_apiset_add(a, clapi[i].name, sa));
+ }
+
+ /* add constraints */
+ for (i = 0 ; clapi[i].name != NULL ; i++) {
+ if (clapi[i].provides && clapi[i].provides[0])
+ ck_assert_int_eq(0, afb_apiset_provide_class(a, clapi[i].name, clapi[i].provides));
+ if (clapi[i].requires && clapi[i].requires[0])
+ ck_assert_int_eq(0, afb_apiset_require_class(a, clapi[i].name, clapi[i].requires));
+ if (clapi[i].apireq && clapi[i].apireq[0])
+ ck_assert_int_eq(0, afb_apiset_require(a, clapi[i].name, clapi[i].apireq));
+ }
+
+ /* start all */
+ ck_assert_int_eq(0, afb_apiset_start_all_services(a, 0));
+
+ afb_apiset_unref(a);
+}
+END_TEST
+
+/*********************************************************************/
+
+static Suite *suite;
+static TCase *tcase;
+
+void mksuite(const char *name) { suite = suite_create(name); }
+void addtcase(const char *name) { tcase = tcase_create(name); suite_add_tcase(suite, tcase); }
+void addtest(TFun fun) { tcase_add_test(tcase, fun); }
+int srun()
+{
+ int nerr;
+ SRunner *srunner = srunner_create(suite);
+ srunner_run_all(srunner, CK_NORMAL);
+ nerr = srunner_ntests_failed(srunner);
+ srunner_free(srunner);
+ return nerr;
+}
+
+int main(int ac, char **av)
+{
+ mksuite("apiset");
+ addtcase("apiset");
+ addtest(check_initialisation);
+ addtest(check_sanity);
+ addtest(check_creation);
+ addtest(check_onlack);
+ addtest(check_settings);
+ addtest(check_classes);
+ return !!srun();
+}
diff --git a/src/tests/apiv3/CMakeLists.txt b/src/tests/apiv3/CMakeLists.txt
new file mode 100644
index 00000000..dfc44619
--- /dev/null
+++ b/src/tests/apiv3/CMakeLists.txt
@@ -0,0 +1,24 @@
+###########################################################################
+# Copyright (C) 2018 "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.
+###########################################################################
+
+add_executable(test-apiv3 test-apiv3.c)
+target_include_directories(test-apiv3 PRIVATE ../..)
+target_link_libraries(test-apiv3 afb-lib ${link_libraries})
+add_test(NAME apiv3 COMMAND test-apiv3)
+
+
diff --git a/src/tests/apiv3/test-apiv3.c b/src/tests/apiv3/test-apiv3.c
new file mode 100644
index 00000000..dec1af97
--- /dev/null
+++ b/src/tests/apiv3/test-apiv3.c
@@ -0,0 +1,198 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+
+#include <check.h>
+
+#if !defined(ck_assert_ptr_null)
+# define ck_assert_ptr_null(X) ck_assert_ptr_eq(X, NULL)
+# define ck_assert_ptr_nonnull(X) ck_assert_ptr_ne(X, NULL)
+#endif
+
+#define AFB_BINDING_VERSION 0
+#include <afb/afb-binding.h>
+#include "afb-api.h"
+#include "afb-apiset.h"
+#include "afb-api-v3.h"
+
+struct inapis {
+ struct afb_binding_v3 desc;
+ struct afb_api_x3 *api;
+ int init;
+};
+
+struct inapis inapis[] = {
+ { .desc = {
+ .api = "ezra",
+ .provide_class = "e",
+ .require_class = "c",
+ .require_api = "armel"
+ }},
+ { .desc = {
+ .api = "clara",
+ .provide_class = "c",
+ .require_class = "a"
+ }},
+ { .desc = {
+ .api = "amelie",
+ .provide_class = "a",
+ .require_api = "albert armel"
+ }},
+ { .desc = {
+ .api = "chloe",
+ .provide_class = "c a"
+ }},
+ { .desc = {
+ .api = "albert",
+ .provide_class = "a"
+ }},
+ { .desc = {
+ .api = "armel",
+ .provide_class = "a",
+ .require_api = "albert"
+ }},
+ { .desc = { .api = NULL }}
+};
+
+int last_in_init;
+
+int in_init(struct afb_api_x3 *api)
+{
+ struct inapis *desc = api->userdata;
+
+ ck_assert_str_eq(api->apiname, desc->desc.api);
+ ck_assert_int_eq(desc->init, 0);
+
+ desc->init = ++last_in_init;
+ printf("init %d of %s\n", desc->init, api->apiname);
+ return 0;
+}
+
+int in_preinit(void *closure, struct afb_api_x3 *api)
+{
+ int rc;
+ struct inapis *desc = closure;
+
+ printf("default preinit of %s\n", api->apiname);
+
+ ck_assert_ptr_nonnull(api);
+ ck_assert_ptr_nonnull(desc);
+ ck_assert_ptr_nonnull(api->apiname);
+ ck_assert_ptr_null(api->userdata);
+ ck_assert_str_eq(api->apiname, desc->desc.api);
+ ck_assert_ptr_null(desc->api);
+ ck_assert_int_eq(desc->init, 0);
+
+ rc = afb_api_v3_set_binding_fields(&desc->desc, api);
+ ck_assert_int_eq(rc, 0);
+
+ api->userdata = desc;
+ desc->api = api;
+
+ if (desc->desc.preinit)
+ desc->desc.preinit(api);
+
+ if (!desc->desc.init) {
+ rc = afb_api_x3_on_init(api, in_init);
+ ck_assert_int_eq(rc, 0);
+ }
+
+ return 0;
+}
+
+int out_init(struct afb_api_x3 *api)
+{
+ return 0;
+}
+
+struct afb_apiset *apiset;
+char out_apiname[] = "out";
+struct afb_api_v3 *out_v3;
+struct afb_api_x3 *out_api;
+
+int out_preinit(void *closure, struct afb_api_x3 *api)
+{
+ int i;
+ int rc;
+ struct afb_api_x3 *napi;
+
+ ck_assert_ptr_nonnull(api);
+ ck_assert_ptr_eq(closure, out_apiname);
+ ck_assert_ptr_null(api->userdata);
+ ck_assert_str_eq(api->apiname, out_apiname);
+ out_api = api;
+
+ for (i = 0 ; inapis[i].desc.api ; i++) {
+ ck_assert_ptr_null(inapis[i].api);
+ napi = afb_api_x3_new_api(
+ api,
+ inapis[i].desc.api,
+ NULL,
+ 0,
+ in_preinit,
+ &inapis[i]);
+ ck_assert_ptr_nonnull(napi);
+ ck_assert_ptr_nonnull(inapis[i].api);
+ ck_assert_ptr_eq(inapis[i].api, napi);
+ }
+
+ rc = afb_api_x3_on_init(api, out_init);
+ ck_assert_int_eq(rc, 0);
+
+ return 0;
+}
+
+START_TEST (test)
+{
+ int rc;
+
+ apiset = afb_apiset_create("test-apiv3", 1);
+ ck_assert_ptr_nonnull(apiset);
+
+ out_v3 = afb_api_v3_create(
+ apiset,
+ apiset,
+ out_apiname,
+ NULL,
+ 0,
+ out_preinit,
+ out_apiname,
+ 0
+ );
+ ck_assert_ptr_nonnull(out_v3);
+ ck_assert_ptr_nonnull(out_api);
+
+ /* start all services */
+ rc = afb_apiset_start_all_services(apiset, 1);
+ ck_assert_int_eq(rc, 0);
+}
+END_TEST
+
+
+/*********************************************************************/
+
+static Suite *suite;
+static TCase *tcase;
+
+void mksuite(const char *name) { suite = suite_create(name); }
+void addtcase(const char *name) { tcase = tcase_create(name); suite_add_tcase(suite, tcase); }
+void addtest(TFun fun) { tcase_add_test(tcase, fun); }
+int srun()
+{
+ int nerr;
+ SRunner *srunner = srunner_create(suite);
+ srunner_run_all(srunner, CK_NORMAL);
+ nerr = srunner_ntests_failed(srunner);
+ srunner_free(srunner);
+ return nerr;
+}
+
+int main(int ac, char **av)
+{
+ mksuite("apiv3");
+ addtcase("apiv3");
+ addtest(test);
+ return !!srun();
+}
diff --git a/src/tests/session/test-session.c b/src/tests/session/test-session.c
index 58e57536..637b0a16 100644
--- a/src/tests/session/test-session.c
+++ b/src/tests/session/test-session.c
@@ -55,7 +55,7 @@ START_TEST (check_creation)
ck_assert(afb_session_uuid(s) != NULL);
ck_assert(afb_session_token(s) != NULL);
ck_assert(!afb_session_is_closed(s));
-
+
/* token is the initial one */
ck_assert_str_eq(afb_session_token(s), GOOD_UUID);
ck_assert(afb_session_check_token(s, GOOD_UUID));
diff --git a/src/verbose.c b/src/verbose.c
index 3e266a18..5fd1940c 100644
--- a/src/verbose.c
+++ b/src/verbose.c
@@ -21,14 +21,44 @@
#include "verbose.h"
-#if !defined(DEFAULT_VERBOSITY)
-# define DEFAULT_VERBOSITY Verbosity_Level_Warning
+#define MASKOF(x) (1 << (x))
+
+#if !defined(DEFAULT_LOGLEVEL)
+# define DEFAULT_LOGLEVEL Log_Level_Warning
+#endif
+
+#if !defined(DEFAULT_LOGMASK)
+# define DEFAULT_LOGMASK (MASKOF((DEFAULT_LOGLEVEL) + 1) - 1)
+#endif
+
+#if !defined(MINIMAL_LOGLEVEL)
+# define MINIMAL_LOGLEVEL Log_Level_Error
#endif
-int verbosity = 1;
+#if !defined(MINIMAL_LOGMASK)
+# define MINIMAL_LOGMASK (MASKOF((MINIMAL_LOGLEVEL) + 1) - 1)
+#endif
+
+static const char *names[] = {
+ "emergency",
+ "alert",
+ "critical",
+ "error",
+ "warning",
+ "notice",
+ "info",
+ "debug"
+};
+
+static const char asort[] = { 1, 2, 7, 0, 3, 6, 5, 4 };
+
+int logmask = DEFAULT_LOGMASK | MINIMAL_LOGMASK;
+
void (*verbose_observer)(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args);
-#define CROP_LOGLEVEL(x) ((x) < Log_Level_Emergency ? Log_Level_Emergency : (x) > Log_Level_Debug ? Log_Level_Debug : (x))
+#define CROP_LOGLEVEL(x) \
+ ((x) < Log_Level_Emergency ? Log_Level_Emergency \
+ : (x) > Log_Level_Debug ? Log_Level_Debug : (x))
#if defined(VERBOSE_WITH_SYSLOG)
@@ -41,7 +71,7 @@ static void _vverbose_(int loglevel, const char *file, int line, const char *fun
if (file == NULL || vasprintf(&p, fmt, args) < 0)
vsyslog(loglevel, fmt, args);
else {
- syslog(CROP_LOGLEVEL(loglevel), "%s [%s:%d, function]", p, file, line, function);
+ syslog(CROP_LOGLEVEL(loglevel), "%s [%s:%d, %s]", p, file, line, function?:"?");
free(p);
}
}
@@ -115,14 +145,18 @@ static void _vverbose_(int loglevel, const char *file, int line, const char *fun
int saverr, n, rc;
struct iovec iov[20];
+ /* save errno */
saverr = errno;
+ /* check if tty (2) or not (1) */
if (!tty)
tty = 1 + isatty(STDERR_FILENO);
+ /* prefix */
iov[0].iov_base = (void*)prefixes[CROP_LOGLEVEL(loglevel)] + (tty - 1 ? 4 : 0);
iov[0].iov_len = strlen(iov[0].iov_base);
+ /* " " */
iov[1].iov_base = (void*)&chars[2];
iov[1].iov_len = 2;
@@ -134,31 +168,40 @@ static void _vverbose_(int loglevel, const char *file, int line, const char *fun
if (rc < 0)
rc = 0;
else if ((size_t)rc > sizeof buffer) {
+ /* if too long, ellipsis the end with ... */
rc = (int)sizeof buffer;
buffer[rc - 1] = buffer[rc - 2] = buffer[rc - 3] = '.';
}
iov[n++].iov_len = (size_t)rc;
}
if (file && (!fmt || tty == 1 || loglevel <= Log_Level_Warning)) {
+ /* "[" (!fmt) or " [" (fmt) */
iov[n].iov_base = (void*)&chars[3 + !fmt];
iov[n++].iov_len = 2 - !fmt;
+ /* file */
iov[n].iov_base = (void*)file;
iov[n++].iov_len = strlen(file);
+ /* ":" */
iov[n].iov_base = (void*)&chars[2];
iov[n++].iov_len = 1;
if (line) {
+ /* line number */
iov[n].iov_base = lino;
iov[n++].iov_len = snprintf(lino, sizeof lino, "%d", line);
} else {
+ /* "?" */
iov[n].iov_base = (void*)&chars[1];
iov[n++].iov_len = 1;
}
+ /* "," */
iov[n].iov_base = (void*)&chars[5];
iov[n++].iov_len = 1;
if (function) {
+ /* function name */
iov[n].iov_base = (void*)function;
iov[n++].iov_len = strlen(function);
} else {
+ /* "?" */
iov[n].iov_base = (void*)&chars[1];
iov[n++].iov_len = 1;
}
@@ -166,16 +209,20 @@ static void _vverbose_(int loglevel, const char *file, int line, const char *fun
iov[n++].iov_len = 1;
}
if (n == 2) {
+ /* "?" */
iov[n].iov_base = (void*)&chars[1];
iov[n++].iov_len = 1;
}
+ /* "\n" */
iov[n].iov_base = (void*)&chars[0];
iov[n++].iov_len = 1;
+ /* emit the message */
pthread_mutex_lock(&mutex);
writev(STDERR_FILENO, iov, n);
pthread_mutex_unlock(&mutex);
+ /* restore errno */
errno = saverr;
}
@@ -187,15 +234,6 @@ void verbose_set_name(const char *name, int authority)
#endif
-void verbose(int loglevel, const char *file, int line, const char *function, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vverbose(loglevel, file, line, function, fmt, ap);
- va_end(ap);
-}
-
void vverbose(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args)
{
void (*observer)(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args) = verbose_observer;
@@ -211,3 +249,89 @@ void vverbose(int loglevel, const char *file, int line, const char *function, co
}
}
+void verbose(int loglevel, const char *file, int line, const char *function, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vverbose(loglevel, file, line, function, fmt, ap);
+ va_end(ap);
+}
+
+void set_logmask(int lvl)
+{
+ logmask = lvl | MINIMAL_LOGMASK;
+}
+
+void verbose_add(int level)
+{
+ set_logmask(logmask | MASKOF(level));
+}
+
+void verbose_sub(int level)
+{
+ set_logmask(logmask & ~MASKOF(level));
+}
+
+void verbose_clear()
+{
+ set_logmask(0);
+}
+
+void verbose_dec()
+{
+ verbosity_set(verbosity_get() - 1);
+}
+
+void verbose_inc()
+{
+ verbosity_set(verbosity_get() + 1);
+}
+
+int verbosity_to_mask(int verbo)
+{
+ int x = verbo + Log_Level_Error;
+ int l = CROP_LOGLEVEL(x);
+ return (1 << (l + 1)) - 1;
+}
+
+int verbosity_from_mask(int mask)
+{
+ int v = 0;
+ while (mask > verbosity_to_mask(v))
+ v++;
+ return v;
+}
+
+void verbosity_set(int verbo)
+{
+ set_logmask(verbosity_to_mask(verbo));
+}
+
+int verbosity_get()
+{
+ return verbosity_from_mask(logmask);
+}
+
+int verbose_level_of_name(const char *name)
+{
+ int c, i, r, l = 0, u = sizeof names / sizeof * names;
+ while (l < u) {
+ i = (l + u) >> 1;
+ r = (int)asort[i];
+ c = strcasecmp(names[r], name);
+ if (!c)
+ return r;
+ if (c < 0)
+ l = i + 1;
+ else
+ u = i;
+ }
+ return -1;
+}
+
+const char *verbose_name_of_level(int level)
+{
+ return level == CROP_LOGLEVEL(level) ? names[level] : NULL;
+}
+
diff --git a/src/verbose.h b/src/verbose.h
index 5cbe2aa6..bd36f97e 100644
--- a/src/verbose.h
+++ b/src/verbose.h
@@ -32,7 +32,6 @@
3 : ERROR, WARNING, NOTICE, INFO
greater than 3 : ERROR, WARNING, NOTICE, INFO, DEBUG
-*/
extern int verbosity;
enum verbosity_levels
@@ -43,6 +42,7 @@ enum verbosity_levels
Verbosity_Level_Info = 3,
Verbosity_Level_Debug = 4
};
+*/
extern void verbose_set_name(const char *name, int authority);
@@ -58,7 +58,7 @@ extern void verbose_set_name(const char *name, int authority);
KERN_DEBUG 7 Debug-level messages
*/
-enum log_levels
+enum
{
Log_Level_Emergency = 0,
Log_Level_Alert = 1,
@@ -70,27 +70,53 @@ enum log_levels
Log_Level_Debug = 7
};
+extern int logmask;
+
extern void verbose(int loglevel, const char *file, int line, const char *function, const char *fmt, ...) __attribute__((format(printf, 5, 6)));
extern void vverbose(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args);
#if defined(VERBOSE_NO_DATA)
-# define __VERBOSE__(lvl,...) do{if((lvl)<=Log_Level_Error) verbose(lvl, __FILE__, __LINE__, __func__, __VA_ARGS__)\
- else verbose(lvl, __FILE__, __LINE__, __func__, NULL);}while(0)
+# define __VERBOSE__(lvl,...) do{if((lvl)<=Log_Level_Error) verbose(lvl, __FILE__, __LINE__, NULL, __VA_ARGS__)\
+ else verbose(lvl, __FILE__, __LINE__, NULL, NULL);}while(0)
#elif defined(VERBOSE_NO_DETAILS)
# define __VERBOSE__(lvl,...) verbose(lvl, NULL, 0, NULL, __VA_ARGS__)
#else
# define __VERBOSE__(lvl,...) verbose(lvl, __FILE__, __LINE__, __func__, __VA_ARGS__)
#endif
-# define _VERBOSE_(vlvl,llvl,...) do{ if (verbosity >= vlvl) __VERBOSE__(llvl, __VA_ARGS__); } while(0)
+#define _LOGMASK_(lvl) ((lvl) < 0 ? -1 : (1 << (lvl)))
+#define _WANTLOG_(lvl) (logmask & _LOGMASK_(lvl))
+#define _VERBOSE_(lvl,...) do{ if (_WANTLOG_(lvl)) __VERBOSE__((lvl), __VA_ARGS__); } while(0)
-# define ERROR(...) _VERBOSE_(Verbosity_Level_Error, Log_Level_Error, __VA_ARGS__)
-# define WARNING(...) _VERBOSE_(Verbosity_Level_Warning, Log_Level_Warning, __VA_ARGS__)
-# define NOTICE(...) _VERBOSE_(Verbosity_Level_Notice, Log_Level_Notice, __VA_ARGS__)
-# define INFO(...) _VERBOSE_(Verbosity_Level_Info, Log_Level_Info, __VA_ARGS__)
-# define DEBUG(...) _VERBOSE_(Verbosity_Level_Debug, Log_Level_Debug, __VA_ARGS__)
+#define EMERGENCY(...) _VERBOSE_(Log_Level_Emergency, __VA_ARGS__)
+#define ALERT(...) _VERBOSE_(Log_Level_Alert, __VA_ARGS__)
+#define CRITICAL(...) _VERBOSE_(Log_Level_Critical, __VA_ARGS__)
+#define ERROR(...) _VERBOSE_(Log_Level_Error, __VA_ARGS__)
+#define WARNING(...) _VERBOSE_(Log_Level_Warning, __VA_ARGS__)
+#define NOTICE(...) _VERBOSE_(Log_Level_Notice, __VA_ARGS__)
+#define INFO(...) _VERBOSE_(Log_Level_Info, __VA_ARGS__)
+#define DEBUG(...) _VERBOSE_(Log_Level_Debug, __VA_ARGS__)
-# define LOGUSER(app) verbose_set_name(app,0)
-# define LOGAUTH(app) verbose_set_name(app,1)
+#define LOGUSER(app) verbose_set_name(app,0)
+#define LOGAUTH(app) verbose_set_name(app,1)
extern void (*verbose_observer)(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args);
+
+static inline int verbose_wants(int lvl) { return _WANTLOG_(lvl); }
+
+extern void verbose_dec();
+extern void verbose_inc();
+extern void verbose_clear();
+extern void verbose_add(int level);
+extern void verbose_sub(int level);
+
+extern int verbose_level_of_name(const char *name);
+extern const char *verbose_name_of_level(int level);
+
+#define _DEVERBOSITY_(vlvl) ((vlvl) + Log_Level_Error)
+#define _VERBOSITY_(llvl) ((llvl) - Log_Level_Error)
+extern int verbosity_get();
+extern void verbosity_set(int verbo);
+extern int verbosity_from_mask(int mask);
+extern int verbosity_to_mask(int verbo);
+
diff --git a/src/wrap-json.c b/src/wrap-json.c
index b139e7ad..e757c369 100644
--- a/src/wrap-json.c
+++ b/src/wrap-json.c
@@ -17,6 +17,7 @@
*/
#include <string.h>
+#include <limits.h>
#include "wrap-json.h"
@@ -528,7 +529,7 @@ static int vunpack(struct json_object *object, const char *desc, va_list args, i
int64_t *pI = NULL;
size_t *pz = NULL;
uint8_t **py = NULL;
- struct { struct json_object *parent; const char *acc; size_t index; size_t count; char type; } stack[STACKCOUNT], *top;
+ struct { struct json_object *parent; const char *acc; int index; int count; char type; } stack[STACKCOUNT], *top;
struct json_object *obj;
struct json_object **po;
@@ -702,7 +703,7 @@ static int vunpack(struct json_object *object, const char *desc, va_list args, i
if (!ignore) {
if (!json_object_is_type(obj, json_type_array))
goto missfit;
- top->count = json_object_array_length(obj);
+ top->count = (int)json_object_array_length(obj);
}
xacc[0] = ']';
acc = unpack_accept_arr;
@@ -752,7 +753,7 @@ static int vunpack(struct json_object *object, const char *desc, va_list args, i
if (key && key >= unpack_accept_any) {
if (top->index >= top->count)
goto out_of_range;
- obj = json_object_array_get_idx(top->parent, (int)top->index++);
+ obj = json_object_array_get_idx(top->parent, top->index++);
}
}
break;
@@ -863,10 +864,10 @@ static void object_for_all(struct json_object *object, void (*callback)(void*,st
static void array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
{
- size_t n = json_object_array_length(object);
- size_t i = 0;
+ int n = (int)json_object_array_length(object);
+ int i = 0;
while(i < n)
- callback(closure, json_object_array_get_idx(object, (int)i++));
+ callback(closure, json_object_array_get_idx(object, i++));
}
void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
@@ -906,16 +907,362 @@ void wrap_json_for_all(struct json_object *object, void (*callback)(void*,struct
else if (!json_object_is_type(object, json_type_array))
callback(closure, object, NULL);
else {
- size_t n = json_object_array_length(object);
- size_t i = 0;
+ int n = (int)json_object_array_length(object);
+ int i = 0;
while(i < n)
- callback(closure, json_object_array_get_idx(object, (int)i++), NULL);
+ callback(closure, json_object_array_get_idx(object, i++), NULL);
}
}
+/**
+ * Clones the 'object' for the depth 'subdepth'. The object 'object' is
+ * duplicated and all its fields are cloned with the depth 'subdepth'.
+ *
+ * @param object the object to clone. MUST be an **object**.
+ * @param subdepth the depth to use when cloning the fields of the object.
+ *
+ * @return the cloned object.
+ */
+static struct json_object *clone_object(struct json_object *object, int subdepth)
+{
+ struct json_object *r = json_object_new_object();
+ struct json_object_iterator it = json_object_iter_begin(object);
+ struct json_object_iterator end = json_object_iter_end(object);
+ while (!json_object_iter_equal(&it, &end)) {
+ json_object_object_add(r,
+ json_object_iter_peek_name(&it),
+ wrap_json_clone_depth(json_object_iter_peek_value(&it), subdepth));
+ json_object_iter_next(&it);
+ }
+ return r;
+}
+
+/**
+ * Clones the 'array' for the depth 'subdepth'. The array 'array' is
+ * duplicated and all its fields are cloned with the depth 'subdepth'.
+ *
+ * @param array the array to clone. MUST be an **array**.
+ * @param subdepth the depth to use when cloning the items of the array.
+ *
+ * @return the cloned array.
+ */
+static struct json_object *clone_array(struct json_object *array, int subdepth)
+{
+ int n = json_object_array_length(array);
+ struct json_object *r = json_object_new_array();
+ while (n) {
+ n--;
+ json_object_array_put_idx(r, n,
+ wrap_json_clone_depth(json_object_array_get_idx(array, n), subdepth));
+ }
+ return r;
+}
+
+/**
+ * Clones any json 'item' for the depth 'depth'. The item is duplicated
+ * and if 'depth' is not zero, its contents is recursively cloned with
+ * the depth 'depth' - 1.
+ *
+ * Be aware that this implementation doesn't copies the primitive json
+ * items (numbers, nulls, booleans, strings) but instead increments their
+ * use count. This can cause issues with newer versions of libjson-c that
+ * now unfortunately allows to change their values.
+ *
+ * @param item the item to clone. Can be of any kind.
+ * @param depth the depth to use when cloning composites: object or arrays.
+ *
+ * @return the cloned array.
+ *
+ * @see wrap_json_clone
+ * @see wrap_json_clone_deep
+ */
+struct json_object *wrap_json_clone_depth(struct json_object *item, int depth)
+{
+ if (depth) {
+ switch (json_object_get_type(item)) {
+ case json_type_object:
+ return clone_object(item, depth - 1);
+ case json_type_array:
+ return clone_array(item, depth - 1);
+ default:
+ break;
+ }
+ }
+ return json_object_get(item);
+}
+
+/**
+ * Clones the 'object': returns a copy of it. But doen't clones
+ * the content. Synonym of wrap_json_clone_depth(object, 1).
+ *
+ * @param object the object to clone
+ *
+ * @return a copy of the object.
+ *
+ * @see wrap_json_clone_depth
+ * @see wrap_json_clone_deep
+ */
+struct json_object *wrap_json_clone(struct json_object *object)
+{
+ return wrap_json_clone_depth(object, 1);
+}
+
+/**
+ * Clones the 'object': returns a copy of it. Also clones all
+ * the content recursively. Synonym of wrap_json_clone_depth(object, INT_MAX).
+ *
+ * @param object the object to clone
+ *
+ * @return a copy of the object.
+ *
+ * @see wrap_json_clone_depth
+ * @see wrap_json_clone
+ */
+struct json_object *wrap_json_clone_deep(struct json_object *object)
+{
+ return wrap_json_clone_depth(object, INT_MAX);
+}
+
+/**
+ * Adds the items of the object 'added' to the object 'dest'.
+ *
+ * @param dest the object to complete this object is modified
+ * @added the object containing fields to add
+ *
+ * @return the destination object 'dest'
+ *
+ * @example wrap_json_object_add({"a":"a"},{"X":"X"}) -> {"a":"a","X":"X"}
+ */
+struct json_object *wrap_json_object_add(struct json_object *dest, struct json_object *added)
+{
+ struct json_object_iterator it, end;
+ if (json_object_is_type(dest, json_type_object) && json_object_is_type(added, json_type_object)) {
+ it = json_object_iter_begin(added);
+ end = json_object_iter_end(added);
+ while (!json_object_iter_equal(&it, &end)) {
+ json_object_object_add(dest,
+ json_object_iter_peek_name(&it),
+ json_object_get(json_object_iter_peek_value(&it)));
+ json_object_iter_next(&it);
+ }
+ }
+ return dest;
+}
+
+/**
+ * Sort the 'array' and returns it. Sorting is done accordingly to the
+ * order given by the function 'wrap_json_cmp'. If the paramater isn't
+ * an array, nothing is done and the parameter is returned unchanged.
+ *
+ * @param array the array to sort
+ *
+ * @returns the array sorted
+ */
+struct json_object *wrap_json_sort(struct json_object *array)
+{
+ if (json_object_is_type(array, json_type_array))
+ json_object_array_sort(array, (int(*)(const void*, const void*))wrap_json_cmp);
+
+ return array;
+}
+
+/**
+ * Returns a json array of the sorted keys of 'object' or null if 'object' has no keys.
+ *
+ * @param object the object whose keys are to be returned
+ *
+ * @return either NULL is 'object' isn't an object or a sorted array of the key's strings.
+ */
+struct json_object *wrap_json_keys(struct json_object *object)
+{
+ struct json_object *r;
+ struct json_object_iterator it, end;
+ if (!json_object_is_type(object, json_type_object))
+ r = NULL;
+ else {
+ r = json_object_new_array();
+ it = json_object_iter_begin(object);
+ end = json_object_iter_end(object);
+ while (!json_object_iter_equal(&it, &end)) {
+ json_object_array_add(r, json_object_new_string(json_object_iter_peek_name(&it)));
+ json_object_iter_next(&it);
+ }
+ wrap_json_sort(r);
+ }
+ return r;
+}
+
+/**
+ * Internal comparison of 'x' with 'y'
+ *
+ * @param x first object to compare
+ * @param y second object to compare
+ * @param inc boolean true if should test for inclusion of y in x
+ * @param sort boolean true if comparison used for sorting
+ *
+ * @return an integer indicating the computed result. Refer to
+ * the table below for meaning of the returned value.
+ *
+ * inc | sort | x < y | x == y | x > y | y in x
+ * ----+------+---------+----------+---------+---------
+ * 0 | 0 | != 0 | 0 | != 0 | > 0
+ * 0 | 1 | < 0 | 0 | > 0 | > 0
+ * 1 | 0 | != 0 | 0 | != 0 | 0
+ * 1 | 1 | < 0 | 0 | > 0 | 0
+ *
+ *
+ * if 'x' is found, respectively, to be less than, to match,
+ * or be greater than 'y'. This is valid when 'sort'
+ */
+static int jcmp(struct json_object *x, struct json_object *y, int inc, int sort)
+{
+ double dx, dy;
+ int64_t ix, iy;
+ const char *sx, *sy;
+ enum json_type tx, ty;
+ int r, nx, ny, i;
+ struct json_object_iterator it, end;
+ struct json_object *jx, *jy;
+
+ /* check equality of pointers */
+ if (x == y)
+ return 0;
+
+ /* get the types */
+ tx = json_object_get_type(x);
+ ty = json_object_get_type(y);
+ r = (int)tx - (int)ty;
+ if (r)
+ return r;
+
+ /* compare following the type */
+ switch (tx) {
+ default:
+ case json_type_null:
+ break;
+
+ case json_type_boolean:
+ r = (int)json_object_get_boolean(x)
+ - (int)json_object_get_boolean(y);
+ break;
+
+ case json_type_double:
+ dx = json_object_get_double(x);
+ dy = json_object_get_double(y);
+ r = dx < dy ? -1 : dx > dy;
+ break;
+
+ case json_type_int:
+ ix = json_object_get_int64(x);
+ iy = json_object_get_int64(y);
+ r = ix < iy ? -1 : ix > iy;
+ break;
+
+ case json_type_object:
+ it = json_object_iter_begin(y);
+ end = json_object_iter_end(y);
+ nx = json_object_object_length(x);
+ ny = json_object_object_length(y);
+ r = nx - ny;
+ if (r > 0 && inc)
+ r = 0;
+ while (!r && !json_object_iter_equal(&it, &end)) {
+ if (json_object_object_get_ex(x, json_object_iter_peek_name(&it), &jx)) {
+ jy = json_object_iter_peek_value(&it);
+ json_object_iter_next(&it);
+ r = jcmp(jx, jy, inc, sort);
+ } else if (sort) {
+ jx = wrap_json_keys(x);
+ jy = wrap_json_keys(y);
+ r = wrap_json_cmp(jx, jy);
+ json_object_put(jx);
+ json_object_put(jy);
+ } else
+ r = 1;
+ }
+ break;
+
+ case json_type_array:
+ nx = json_object_array_length(x);
+ ny = json_object_array_length(y);
+ r = nx - ny;
+ if (r > 0 && inc)
+ r = 0;
+ for (i = 0 ; !r && i < ny ; i++) {
+ jx = json_object_array_get_idx(x, i);
+ jy = json_object_array_get_idx(y, i);
+ r = jcmp(jx, jy, inc, sort);
+ }
+ break;
+
+ case json_type_string:
+ sx = json_object_get_string(x);
+ sy = json_object_get_string(y);
+ r = strcmp(sx, sy);
+ break;
+ }
+ return r;
+}
+
+/**
+ * Compares 'x' with 'y'
+ *
+ * @param x first object to compare
+ * @param y second object to compare
+ *
+ * @return an integer less than, equal to, or greater than zero
+ * if 'x' is found, respectively, to be less than, to match,
+ * or be greater than 'y'.
+ */
+int wrap_json_cmp(struct json_object *x, struct json_object *y)
+{
+ return jcmp(x, y, 0, 1);
+}
+
+/**
+ * Searchs wether 'x' equals 'y'
+ *
+ * @param x first object to compare
+ * @param y second object to compare
+ *
+ * @return an integer equal to zero when 'x' != 'y' or 1 when 'x' == 'y'.
+ */
+int wrap_json_equal(struct json_object *x, struct json_object *y)
+{
+ return !jcmp(x, y, 0, 0);
+}
+
+/**
+ * Searchs wether 'x' contains 'y'
+ *
+ * @param x first object to compare
+ * @param y second object to compare
+ *
+ * @return an integer equal to 1 when 'y' is a subset of 'x' or zero otherwise
+ */
+int wrap_json_contains(struct json_object *x, struct json_object *y)
+{
+ return !jcmp(x, y, 1, 0);
+}
+
#if defined(WRAP_JSON_TEST)
#include <stdio.h>
+void tclone(struct json_object *object)
+{
+ struct json_object *o;
+
+ o = wrap_json_clone(object);
+ if (!wrap_json_equal(object, o))
+ printf("ERROR in clone or equal: %s VERSUS %s\n", json_object_to_json_string(object), json_object_to_json_string(o));
+ json_object_put(o);
+
+ o = wrap_json_clone_deep(object);
+ if (!wrap_json_equal(object, o))
+ printf("ERROR in clone_deep or equal: %s VERSUS %s\n", json_object_to_json_string(object), json_object_to_json_string(o));
+ json_object_put(o);
+}
+
void p(const char *desc, ...)
{
int rc;
@@ -929,6 +1276,7 @@ void p(const char *desc, ...)
printf(" SUCCESS %s\n\n", json_object_to_json_string(result));
else
printf(" ERROR[char %d err %d] %s\n\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc));
+ tclone(result);
json_object_put(result);
}
@@ -945,7 +1293,7 @@ void u(const char *value, const char *desc, ...)
unsigned m, k;
int rc;
va_list args;
- struct json_object *obj, *o;
+ struct json_object *object, *o;
memset(xs, 0, sizeof xs);
memset(xi, 0, sizeof xi);
@@ -954,9 +1302,9 @@ void u(const char *value, const char *desc, ...)
memset(xo, 0, sizeof xo);
memset(xy, 0, sizeof xy);
memset(xz, 0, sizeof xz);
- obj = json_tokener_parse(value);
+ object = json_tokener_parse(value);
va_start(args, desc);
- rc = wrap_json_vunpack(obj, desc, args);
+ rc = wrap_json_vunpack(object, desc, args);
va_end(args);
if (rc)
printf(" ERROR[char %d err %d] %s\n\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc));
@@ -996,7 +1344,30 @@ void u(const char *value, const char *desc, ...)
va_end(args);
printf("\n\n");
}
- json_object_put(obj);
+ tclone(object);
+ json_object_put(object);
+}
+
+void c(const char *sx, const char *sy, int e, int c)
+{
+ int re, rc;
+ struct json_object *jx, *jy;
+
+ jx = json_tokener_parse(sx);
+ jy = json_tokener_parse(sy);
+
+ re = wrap_json_cmp(jx, jy);
+ rc = wrap_json_contains(jx, jy);
+
+ printf("compare(%s)(%s)\n", sx, sy);
+ printf(" -> %d / %d\n", re, rc);
+
+ if (!re != !!e)
+ printf(" ERROR should be %s\n", e ? "equal" : "different");
+ if (!rc != !c)
+ printf(" ERROR should %scontain\n", c ? "" : "not ");
+
+ printf("\n");
}
#define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
@@ -1145,6 +1516,41 @@ int main()
U("{\"foo\":\"Pz8_Pz8_P2hlbGxvPj4-Pj4-Pg\"}", "{s?y}", "foo", &xy[0], &xz[0]);
U("{\"foo\":\"\"}", "{s?y}", "foo", &xy[0], &xz[0]);
U("{}", "{s?y}", "foo", &xy[0], &xz[0]);
+
+ c("null", "null", 1, 1);
+ c("true", "true", 1, 1);
+ c("false", "false", 1, 1);
+ c("1", "1", 1, 1);
+ c("1.0", "1.0", 1, 1);
+ c("\"\"", "\"\"", 1, 1);
+ c("\"hi\"", "\"hi\"", 1, 1);
+ c("{}", "{}", 1, 1);
+ c("{\"a\":true,\"b\":false}", "{\"b\":false,\"a\":true}", 1, 1);
+ c("[]", "[]", 1, 1);
+ c("[1,true,null]", "[1,true,null]", 1, 1);
+
+ c("null", "true", 0, 0);
+ c("null", "false", 0, 0);
+ c("0", "1", 0, 0);
+ c("1", "0", 0, 0);
+ c("0", "true", 0, 0);
+ c("0", "false", 0, 0);
+ c("0", "null", 0, 0);
+
+ c("\"hi\"", "\"hello\"", 0, 0);
+ c("\"hello\"", "\"hi\"", 0, 0);
+
+ c("{}", "null", 0, 0);
+ c("{}", "true", 0, 0);
+ c("{}", "1", 0, 0);
+ c("{}", "1.0", 0, 0);
+ c("{}", "[]", 0, 0);
+ c("{}", "\"x\"", 0, 0);
+
+ c("[1,true,null]", "[1,true]", 0, 1);
+ c("{\"a\":true,\"b\":false}", "{\"a\":true}", 0, 1);
+ c("{\"a\":true,\"b\":false}", "{\"a\":true,\"c\":false}", 0, 0);
+ c("{\"a\":true,\"c\":false}", "{\"a\":true,\"b\":false}", 0, 0);
return 0;
}
diff --git a/src/wrap-json.h b/src/wrap-json.h
index 56f99198..d75ebc43 100644
--- a/src/wrap-json.h
+++ b/src/wrap-json.h
@@ -18,6 +18,10 @@
#pragma once
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
#include <stdarg.h>
#include <json-c/json.h>
@@ -44,3 +48,18 @@ extern void wrap_json_object_for_all(struct json_object *object, void (*callback
extern void wrap_json_optobject_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure);
extern void wrap_json_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure);
+extern struct json_object *wrap_json_clone(struct json_object *object);
+extern struct json_object *wrap_json_clone_deep(struct json_object *object);
+extern struct json_object *wrap_json_clone_depth(struct json_object *object, int depth);
+
+extern struct json_object *wrap_json_object_add(struct json_object *dest, struct json_object *added);
+
+extern struct json_object *wrap_json_sort(struct json_object *array);
+extern struct json_object *wrap_json_keys(struct json_object *object);
+extern int wrap_json_cmp(struct json_object *x, struct json_object *y);
+extern int wrap_json_equal(struct json_object *x, struct json_object *y);
+extern int wrap_json_contains(struct json_object *x, struct json_object *y);
+
+#ifdef __cplusplus
+ }
+#endif