X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-subcall.c;h=498f73b585aed9b05221dd1fe93c3fdd15aa5bf0;hb=03f863dd080d32f71c4a0755c02e23c72e4cb342;hp=65bef2ff33c46475ca54e3912da9941b76e6eaaa;hpb=44f21bd2a3b50f92669223cdafe79993654c1e19;p=src%2Fapp-framework-binder.git diff --git a/src/afb-subcall.c b/src/afb-subcall.c index 65bef2ff..498f73b5 100644 --- a/src/afb-subcall.c +++ b/src/afb-subcall.c @@ -27,168 +27,176 @@ #include "afb-msg-json.h" #include "afb-apis.h" #include "afb-context.h" +#include "afb-xreq.h" #include "verbose.h" +#include "jobs.h" -struct afb_subcall; - -static void subcall_addref(struct afb_subcall *subcall); -static void subcall_unref(struct afb_subcall *subcall); -static struct json_object *subcall_json(struct afb_subcall *subcall); -static struct afb_arg subcall_get(struct afb_subcall *subcall, const char *name); -static void subcall_fail(struct afb_subcall *subcall, const char *status, const char *info); -static void subcall_success(struct afb_subcall *subcall, struct json_object *obj, const char *info); -static const char *subcall_raw(struct afb_subcall *subcall, size_t *size); -static void subcall_send(struct afb_subcall *subcall, const char *buffer, size_t size); -static int subcall_subscribe(struct afb_subcall *subcall, struct afb_event event); -static int subcall_unsubscribe(struct afb_subcall *subcall, struct afb_event event); -static void subcall_session_close(struct afb_subcall *subcall); -static int subcall_session_set_LOA(struct afb_subcall *subcall, unsigned loa); -static void subcall_subcall(struct afb_subcall *subcall, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure); - -const struct afb_req_itf afb_subcall_req_itf = { - .json = (void*)subcall_json, - .get = (void*)subcall_get, - .success = (void*)subcall_success, - .fail = (void*)subcall_fail, - .raw = (void*)subcall_raw, - .send = (void*)subcall_send, - .context_get = (void*)afb_context_get, - .context_set = (void*)afb_context_set, - .addref = (void*)subcall_addref, - .unref = (void*)subcall_unref, - .session_close = (void*)subcall_session_close, - .session_set_LOA = (void*)subcall_session_set_LOA, - .subscribe = (void*)subcall_subscribe, - .unsubscribe = (void*)subcall_unsubscribe, - .subcall = (void*)subcall_subcall +struct subcall; + +static void subcall_destroy(struct afb_xreq *xreq); +static void subcall_reply(struct afb_xreq *xreq, int iserror, struct json_object *obj); +static int subcall_subscribe(struct afb_xreq *xreq, struct afb_event event); +static int subcall_unsubscribe(struct afb_xreq *xreq, struct afb_event event); + +const struct afb_xreq_query_itf afb_subcall_xreq_itf = { + .reply = subcall_reply, + .unref = subcall_destroy, + .subscribe = subcall_subscribe, + .unsubscribe = subcall_unsubscribe }; -struct afb_subcall +struct subcall { - /* - * CAUTION: 'context' field should be the first because there - * is an implicit convertion to struct afb_context - */ - struct afb_context context; - struct afb_context *original_context; - int refcount; - struct json_object *args; - struct afb_req req; + struct afb_xreq xreq; + struct afb_xreq *caller; void (*callback)(void*, int, struct json_object*); void *closure; }; -static void subcall_addref(struct afb_subcall *subcall) +static void subcall_destroy(struct afb_xreq *xreq) { - subcall->refcount++; -} + struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq); -static void subcall_unref(struct afb_subcall *subcall) -{ - if (0 == --subcall->refcount) { - json_object_put(subcall->args); - afb_req_unref(subcall->req); - free(subcall); - } + json_object_put(subcall->xreq.json); + afb_xreq_unref(subcall->caller); + free(subcall); } -static struct json_object *subcall_json(struct afb_subcall *subcall) +static void subcall_reply(struct afb_xreq *xreq, int iserror, struct json_object *obj) { - return subcall->args; -} + struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq); -static struct afb_arg subcall_get(struct afb_subcall *subcall, const char *name) -{ - return afb_msg_json_get_arg(subcall->args, name); + subcall->callback(subcall->closure, iserror, obj); + json_object_put(obj); } -static void subcall_emit(struct afb_subcall *subcall, int iserror, struct json_object *object) +static int subcall_subscribe(struct afb_xreq *xreq, struct afb_event event) { - if (subcall->context.refreshing != 0) - subcall->original_context->refreshing = 1; + struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq); - subcall->callback(subcall->closure, iserror, object); - json_object_put(object); + return afb_xreq_subscribe(subcall->caller, event); } -static void subcall_fail(struct afb_subcall *subcall, const char *status, const char *info) +static int subcall_unsubscribe(struct afb_xreq *xreq, struct afb_event event) { - subcall_emit(subcall, 1, afb_msg_json_reply_error(status, info, NULL, NULL)); -} + struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq); -static void subcall_success(struct afb_subcall *subcall, struct json_object *obj, const char *info) -{ - subcall_emit(subcall, 0, afb_msg_json_reply_ok(info, obj, NULL, NULL)); + return afb_xreq_unsubscribe(subcall->caller, event); } -static const char *subcall_raw(struct afb_subcall *subcall, size_t *size) +static struct subcall *create_subcall(struct afb_xreq *caller, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure) { - const char *result = json_object_to_json_string(subcall->args); - if (size != NULL) - *size = strlen(result); - return result; -} + struct subcall *subcall; -static void subcall_send(struct afb_subcall *subcall, const char *buffer, size_t size) -{ - subcall_emit(subcall, 0, json_tokener_parse(buffer)); -} + subcall = calloc(1, sizeof *subcall); + if (subcall == NULL) { + return NULL; + } -static void subcall_session_close(struct afb_subcall *subcall) -{ - afb_req_session_close(subcall->req); + afb_xreq_init(&subcall->xreq, &afb_subcall_xreq_itf); + afb_context_subinit(&subcall->xreq.context, &caller->context); + subcall->xreq.json = args; + subcall->xreq.api = api; /* TODO: alloc ? */ + subcall->xreq.verb = verb; /* TODO: alloc ? */ + subcall->caller = caller; + subcall->callback = callback; + subcall->closure = closure; + afb_xreq_addref(caller); + json_object_get(args); + return subcall; } -static int subcall_session_set_LOA(struct afb_subcall *subcall, unsigned loa) +void afb_subcall( + struct afb_xreq *caller, + const char *api, + const char *verb, + struct json_object *args, + void (*callback)(void*, int, struct json_object*), + void *closure +) { - return afb_req_session_set_LOA(subcall->req, loa); -} + struct subcall *subcall; -static int subcall_subscribe(struct afb_subcall *subcall, struct afb_event event) -{ - return afb_req_subscribe(subcall->req, event); + subcall = create_subcall(caller, api, verb, args, callback, closure); + if (subcall == NULL) { + callback(closure, 1, afb_msg_json_internal_error()); + return; + } + + afb_apis_call(&subcall->xreq); + afb_xreq_unref(&subcall->xreq); } -static int subcall_unsubscribe(struct afb_subcall *subcall, struct afb_event event) +struct subcall_sync { - return afb_req_unsubscribe(subcall->req, event); -} + struct afb_xreq *caller; + const char *api; + const char *verb; + struct json_object *args; + struct jobloop *jobloop; + struct json_object *result; + int iserror; +}; -static void subcall_subcall(struct afb_subcall *subcall, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure) +static void subcall_sync_leave(struct subcall_sync *sync) { - afb_subcall(&subcall->context, api, verb, args, callback, closure, (struct afb_req){ .itf = &afb_subcall_req_itf, .closure = subcall }); + struct jobloop *jobloop = sync->jobloop; + sync->jobloop = NULL; + if (jobloop) + jobs_leave(jobloop); } -void afb_subcall_internal_error(void (*callback)(void*, int, struct json_object*), void *closure) +static void subcall_sync_reply(void *closure, int iserror, struct json_object *obj) { - static struct json_object *obj; - - if (obj == NULL) - obj = afb_msg_json_reply_error("failed", "internal error", NULL, NULL); + struct subcall_sync *sync = closure; - callback(closure, 1, obj); + sync->iserror = iserror; + sync->result = obj; + json_object_get(obj); + subcall_sync_leave(sync); } -void afb_subcall(struct afb_context *context, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure, struct afb_req req) +static void subcall_sync_enter(int signum, void *closure, struct jobloop *jobloop) { - struct afb_subcall *subcall; + struct subcall_sync *sync = closure; - subcall = calloc(1, sizeof *subcall); - if (subcall == NULL) { - afb_subcall_internal_error(callback, closure); - return; + if (!signum) { + sync->jobloop = jobloop; + afb_xreq_unhooked_subcall(sync->caller, sync->api, sync->verb, sync->args, subcall_sync_reply, sync); + } else { + sync->result = json_object_get(afb_msg_json_internal_error()); + sync->iserror = 1; + subcall_sync_leave(sync); } +} - subcall->original_context = context; - subcall->refcount = 1; - subcall->args = args; - subcall->req = req; - subcall->callback = callback; - subcall->closure = closure; - subcall->context = *context; - afb_req_addref(req); - afb_apis_call((struct afb_req){ .itf = &afb_subcall_req_itf, .closure = subcall }, &subcall->context, api, verb); - subcall_unref(subcall); +int afb_subcall_sync( + struct afb_xreq *caller, + const char *api, + const char *verb, + struct json_object *args, + struct json_object **result +) +{ + int rc; + struct subcall_sync sync; + + sync.caller = caller; + sync.api = api; + sync.verb = verb; + sync.args = args; + sync.jobloop = NULL; + sync.result = NULL; + sync.iserror = 1; + + rc = jobs_enter(NULL, 0, subcall_sync_enter, &sync); + if (rc < 0) { + sync.result = json_object_get(afb_msg_json_internal_error()); + sync.iserror = 1; + } + rc = !sync.iserror; + *result = sync.result; + return rc; }