+ int rc;
+ struct xreq_sync sync;
+ struct afb_xreq *xreq = closure;
+
+ sync.caller = xreq;
+ sync.api = api;
+ sync.verb = verb;
+ sync.args = args;
+ sync.jobloop = NULL;
+ sync.result = NULL;
+ sync.iserror = 1;
+
+ rc = jobs_enter(NULL, 0, xreq_sync_enter, &sync);
+ if (rc < 0 || sync.iserror) {
+ *result = sync.result ? : afb_msg_json_internal_error();
+ return 0;
+ }
+ *result = sync.result;
+ return 1;
+}
+
+/******************************************************************************/
+
+static struct json_object *xreq_hooked_json_cb(void *closure)
+{
+ struct json_object *r = xreq_json_cb(closure);
+ struct afb_xreq *xreq = closure;
+ return afb_hook_xreq_json(xreq, r);
+}
+
+static struct afb_arg xreq_hooked_get_cb(void *closure, const char *name)
+{
+ struct afb_arg r = xreq_get_cb(closure, name);
+ struct afb_xreq *xreq = closure;
+ return afb_hook_xreq_get(xreq, name, r);
+}
+
+static void xreq_hooked_success_cb(void *closure, struct json_object *obj, const char *info)
+{
+ struct afb_xreq *xreq = closure;
+ afb_hook_xreq_success(xreq, obj, info);
+ xreq_success_cb(closure, obj, info);
+}
+
+static void xreq_hooked_fail_cb(void *closure, const char *status, const char *info)
+{
+ struct afb_xreq *xreq = closure;
+ afb_hook_xreq_fail(xreq, status, info);
+ xreq_fail_cb(closure, status, info);
+}
+
+static const char *xreq_hooked_raw_cb(void *closure, size_t *size)
+{
+ size_t s;
+ const char *r = xreq_raw_cb(closure, size ? : &s);
+ struct afb_xreq *xreq = closure;
+ return afb_hook_xreq_raw(xreq, r, *(size ? : &s));
+}
+
+static void xreq_hooked_send_cb(void *closure, const char *buffer, size_t size)
+{
+ struct afb_xreq *xreq = closure;
+ afb_hook_xreq_send(xreq, buffer, size);
+ xreq_send_cb(closure, buffer, size);
+}
+
+static void *xreq_hooked_context_get_cb(void *closure)
+{
+ void *r = xreq_context_get_cb(closure);
+ struct afb_xreq *xreq = closure;
+ return afb_hook_xreq_context_get(xreq, r);
+}
+
+static void xreq_hooked_context_set_cb(void *closure, void *value, void (*free_value)(void*))
+{
+ struct afb_xreq *xreq = closure;
+ afb_hook_xreq_context_set(xreq, value, free_value);
+ xreq_context_set_cb(closure, value, free_value);
+}
+
+static void xreq_hooked_addref_cb(void *closure)
+{
+ struct afb_xreq *xreq = closure;
+ afb_hook_xreq_addref(xreq);
+ xreq_addref_cb(closure);
+}
+
+static void xreq_hooked_unref_cb(void *closure)
+{
+ struct afb_xreq *xreq = closure;
+ afb_hook_xreq_unref(xreq);
+ if (!__atomic_sub_fetch(&xreq->refcount, 1, __ATOMIC_RELAXED)) {
+ afb_hook_xreq_end(xreq);
+ xreq->queryitf->unref(xreq);
+ }
+}
+
+static void xreq_hooked_session_close_cb(void *closure)
+{
+ struct afb_xreq *xreq = closure;
+ afb_hook_xreq_session_close(xreq);
+ xreq_session_close_cb(closure);
+}
+
+static int xreq_hooked_session_set_LOA_cb(void *closure, unsigned level)
+{
+ int r = xreq_session_set_LOA_cb(closure, level);
+ struct afb_xreq *xreq = closure;
+ return afb_hook_xreq_session_set_LOA(xreq, level, r);
+}
+
+static int xreq_hooked_subscribe_cb(void *closure, struct afb_event event)
+{
+ int r = xreq_subscribe_cb(closure, event);
+ struct afb_xreq *xreq = closure;
+ return afb_hook_xreq_subscribe(xreq, event, r);
+}
+
+static int xreq_hooked_unsubscribe_cb(void *closure, struct afb_event event)
+{
+ int r = xreq_unsubscribe_cb(closure, event);
+ struct afb_xreq *xreq = closure;
+ return afb_hook_xreq_unsubscribe(xreq, event, r);
+}
+
+struct reply
+{
+ struct afb_xreq *xreq;
+ void (*callback)(void*, int, struct json_object*);
+ void *closure;
+};
+
+static void xreq_hooked_subcall_reply_cb(void *closure, int iserror, struct json_object *result)
+{
+ struct reply *reply = closure;
+
+ afb_hook_xreq_subcall_result(reply->xreq, iserror, result);
+ reply->callback(reply->closure, iserror, result);
+ free(reply);
+}
+
+static void xreq_hooked_subcall_cb(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure)
+{
+ struct reply *reply = malloc(sizeof *reply);