+static struct afb_arg xreq_get_cb(struct afb_req_x2 *closure, const char *name)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ struct afb_arg arg;
+ struct json_object *object, *value;
+
+ if (xreq->queryitf->get)
+ arg = xreq->queryitf->get(xreq, name);
+ else {
+ object = xreq_json_cb(closure);
+ if (json_object_object_get_ex(object, name, &value)) {
+ arg.name = name;
+ arg.value = json_object_get_string(value);
+ } else {
+ arg.name = NULL;
+ arg.value = NULL;
+ }
+ arg.path = NULL;
+ }
+ return arg;
+}
+
+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_req_x2(closure);
+
+ if (xreq->replied) {
+ ERROR("reply called more than one time!!");
+ json_object_put(obj);
+ } else {
+ xreq->replied = 1;
+ xreq->queryitf->reply(xreq, obj, error, info);
+ }
+}
+
+static void xreq_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_reply_cb(closure, obj, error, info);
+ free(info);
+}
+
+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_legacy_fail_cb(struct afb_req_x2 *closure, const char *status, const char *info)
+{
+ xreq_reply_cb(closure, NULL, status, info);
+}
+
+static void xreq_legacy_vsuccess_cb(struct afb_req_x2 *closure, struct json_object *obj, const char *fmt, va_list args)
+{
+ xreq_vreply_cb(closure, obj, NULL, fmt, args);
+}
+
+static void xreq_legacy_vfail_cb(struct afb_req_x2 *closure, const char *status, const char *fmt, va_list args)
+{
+ 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_legacy_context_set_cb(struct afb_req_x2 *closure, void *value, void (*free_value)(void*))
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ afb_context_set(&xreq->context, value, free_value);
+}
+
+static struct afb_req_x2 *xreq_addref_cb(struct afb_req_x2 *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ afb_xreq_unhooked_addref(xreq);
+ return closure;
+}
+
+static void xreq_unref_cb(struct afb_req_x2 *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ afb_xreq_unhooked_unref(xreq);
+}
+
+static void xreq_session_close_cb(struct afb_req_x2 *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ afb_context_close(&xreq->context);
+}
+
+static int xreq_session_set_LOA_cb(struct afb_req_x2 *closure, unsigned level)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_context_change_loa(&xreq->context, level);
+}
+
+static int xreq_subscribe_event_x2_cb(struct afb_req_x2 *closure, struct afb_event_x2 *event)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_xreq_subscribe(xreq, event);
+}
+
+static int xreq_legacy_subscribe_event_x1_cb(struct afb_req_x2 *closure, struct afb_event_x1 event)
+{
+ return xreq_subscribe_event_x2_cb(closure, afb_event_x1_to_event_x2(event));
+}
+
+int afb_xreq_subscribe(struct afb_xreq *xreq, struct afb_event_x2 *event)
+{
+ if (xreq->replied) {
+ ERROR("request replied, subscription impossible");
+ errno = EINVAL;
+ } else {
+ if (xreq->queryitf->subscribe)
+ return xreq->queryitf->subscribe(xreq, event);
+ ERROR("no event listener, subscription impossible");
+ errno = ENOTSUP;
+ }
+ return -1;
+}
+
+static int xreq_unsubscribe_event_x2_cb(struct afb_req_x2 *closure, struct afb_event_x2 *event)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_xreq_unsubscribe(xreq, event);
+}
+
+static int xreq_legacy_unsubscribe_event_x1_cb(struct afb_req_x2 *closure, struct afb_event_x1 event)
+{
+ return xreq_unsubscribe_event_x2_cb(closure, afb_event_x1_to_event_x2(event));
+}
+
+int afb_xreq_unsubscribe(struct afb_xreq *xreq, struct afb_event_x2 *event)
+{
+ if (xreq->replied) {
+ ERROR("request replied, unsubscription impossible");
+ errno = EINVAL;
+ } else {
+ if (xreq->queryitf->unsubscribe)
+ return xreq->queryitf->unsubscribe(xreq, event);
+ ERROR("no event listener, unsubscription impossible");
+ errno = ENOTSUP;
+ }
+ return -1;
+}
+
+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_req_x2(req);
+ return afb_calls_legacy_subcall_v1(xreq, api, verb, args, callback, 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_req_x2(req);
+ return afb_calls_legacy_subcall_v2(xreq, api, verb, args, callback, 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_req_x2(req);
+ return afb_calls_legacy_subcall_v3(xreq, api, verb, args, callback, closure);
+}
+
+
+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)
+{
+ 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_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_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.called_api, p);
+ free(p);
+ }
+}
+
+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_req_x2 *closure, const char *permission)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ return afb_context_has_permission(&xreq->context, permission);
+}
+
+static char *xreq_get_application_id_cb(struct afb_req_x2 *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ struct afb_cred *cred = xreq->context.credentials;
+ return cred && cred->id ? strdup(cred->id) : NULL;
+}
+
+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_req_x2(closure);
+ return afb_context_make(&xreq->context, replace, create_value, free_value, create_closure);
+}
+
+static int xreq_get_uid_cb(struct afb_req_x2 *closure)
+{
+ struct afb_xreq *xreq = xreq_from_req_x2(closure);
+ struct afb_cred *cred = xreq->context.credentials;
+ return cred && cred->id ? (int)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 afb_cred *cred = xreq->context.credentials;
+ struct json_object *r = json_object_new_object();
+ if (cred && cred->id) {
+ json_object_object_add(r, "uid", json_object_new_int(cred->uid));
+ json_object_object_add(r, "gid", json_object_new_int(cred->gid));
+ json_object_object_add(r, "pid", json_object_new_int(cred->pid));
+ json_object_object_add(r, "user", json_object_new_string(cred->user));
+ json_object_object_add(r, "label", json_object_new_string(cred->label));
+ json_object_object_add(r, "id", json_object_new_string(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;
+}