+
+ 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 = 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)
+{
+ struct afb_xreq *xreq = from_request(closure);
+ struct afb_arg arg;
+ struct json_object *object, *value;
+