+ struct svc_req *svcreq;
+ size_t lenapi, lenverb;
+ char *copy;
+
+ /* allocates the request */
+ lenapi = 1 + strlen(api);
+ lenverb = 1 + strlen(verb);
+ svcreq = malloc(lenapi + lenverb + sizeof *svcreq);
+ if (svcreq != NULL) {
+ /* initialises the request */
+ afb_xreq_init(&svcreq->xreq, &afb_svc_xreq_itf);
+ afb_context_init(&svcreq->xreq.context, svc->session, NULL);
+ svcreq->xreq.context.validated = 1;
+ copy = (char*)&svcreq[1];
+ memcpy(copy, api, lenapi);
+ svcreq->xreq.api = copy;
+ copy = ©[lenapi];
+ memcpy(copy, verb, lenverb);
+ svcreq->xreq.verb = copy;
+ svcreq->xreq.listener = svc->listener;
+ svcreq->xreq.json = args;
+ svcreq->svc = svc;
+ }
+ return svcreq;
+}
+
+/*
+ * destroys the svc_req
+ */
+static void svcreq_destroy(struct afb_xreq *xreq)
+{
+ struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq);
+
+ afb_context_disconnect(&svcreq->xreq.context);
+ json_object_put(svcreq->xreq.json);
+ afb_cred_unref(svcreq->xreq.cred);
+ free(svcreq);
+}
+
+static void svcreq_sync_leave(struct svc_req *svcreq)
+{
+ struct jobloop *jobloop = svcreq->jobloop;
+
+ if (jobloop) {
+ svcreq->jobloop = NULL;
+ jobs_leave(jobloop);
+ }
+}
+
+static void svcreq_reply(struct afb_xreq *xreq, int status, json_object *obj)
+{
+ struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq);
+ if (svcreq->callback) {
+ struct afb_svc *svc = svcreq->svc;
+ svcreq->callback(svcreq->closure, status, obj);
+ HOOK(call_result, svc, status, obj);
+ json_object_put(obj);
+ } else {
+ svcreq->status = status;
+ svcreq->result = obj;
+ svcreq_sync_leave(svcreq);
+ }
+}
+
+static void svcreq_sync_enter(int signum, void *closure, struct jobloop *jobloop)
+{
+ struct svc_req *svcreq = closure;
+
+ if (!signum) {
+ svcreq->jobloop = jobloop;
+ afb_xreq_process(&svcreq->xreq, svcreq->svc->apiset);
+ } else {
+ svcreq->result = afb_msg_json_internal_error();
+ svcreq->status = -1;
+ svcreq_sync_leave(svcreq);
+ }