diff options
Diffstat (limited to 'src/afb-svc.c')
-rw-r--r-- | src/afb-svc.c | 381 |
1 files changed, 0 insertions, 381 deletions
diff --git a/src/afb-svc.c b/src/afb-svc.c deleted file mode 100644 index 212ecfa3..00000000 --- a/src/afb-svc.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (C) 2016, 2017 "IoT.bzh" - * Author: José Bollo <jose.bollo@iot.bzh> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE - -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include <json-c/json.h> - -#include <afb/afb-binding-v1.h> -#include <afb/afb-binding-v2.h> - -#include "afb-session.h" -#include "afb-context.h" -#include "afb-evt.h" -#include "afb-msg-json.h" -#include "afb-svc.h" -#include "afb-xreq.h" -#include "afb-cred.h" -#include "afb-apiset.h" -#include "afb-hook.h" -#include "jobs.h" -#include "verbose.h" - - -#define HOOK(x,...) if((svc)->hookflags & afb_hook_flag_svc_##x) afb_hook_svc_##x(__VA_ARGS__) - -/* - * Structure for requests initiated by the service - */ -struct svc_req -{ - struct afb_xreq xreq; - - struct afb_svc *svc; - - /* the args */ - void (*callback)(void*, int, struct json_object*); - void *closure; - - /* sync */ - struct jobloop *jobloop; - struct json_object *result; - int status; - int async; -}; - -/* functions for services */ -static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object); -static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args, - void (*callback)(void*, int, struct json_object*), void *cbclosure); -static int svc_call_sync(void *closure, const char *api, const char *verb, struct json_object *args, - struct json_object **result); - -/* the interface for services */ -static const struct afb_service_itf service_itf = { - .call = svc_call, - .call_sync = svc_call_sync -}; - -/* the interface for events */ -static const struct afb_evt_itf evt_itf = { - .broadcast = svc_on_event, - .push = svc_on_event -}; - -/* functions for requests of services */ -static void svcreq_destroy(struct afb_xreq *xreq); -static void svcreq_reply(struct afb_xreq *xreq, int status, json_object *obj); - -/* interface for requests of services */ -const struct afb_xreq_query_itf afb_svc_xreq_itf = { - .unref = svcreq_destroy, - .reply = svcreq_reply -}; - -/* the common session for services sharing their session */ -static struct afb_session *common_session; - -static inline struct afb_service to_afb_service(struct afb_svc *svc) -{ - return (struct afb_service){ .itf = &service_itf, .closure = svc }; -} - -/* - * Frees a service - */ -void afb_svc_destroy(struct afb_svc *svc, struct afb_service *service) -{ - if (service) - *service = (struct afb_service){ .itf = NULL, .closure = NULL }; - if (svc) { - if (svc->listener != NULL) - afb_evt_listener_unref(svc->listener); - if (svc->session) - afb_session_unref(svc->session); - afb_apiset_unref(svc->apiset); - free(svc); - } -} - -/* - * Creates a new service - */ -struct afb_svc *afb_svc_create( - const char *api, - struct afb_apiset *apiset, - int share_session, - void (*on_event)(const char *event, struct json_object *object), - struct afb_service *service -) -{ - struct afb_svc *svc; - - /* allocates the svc handler */ - svc = calloc(1, sizeof * svc); - if (svc == NULL) { - errno = ENOMEM; - return NULL; - } - - /* instanciate the apiset */ - svc->api = api; - svc->apiset = afb_apiset_addref(apiset); - - /* instanciate the session */ - if (share_session) { - /* session shared with other svcs */ - if (common_session == NULL) { - common_session = afb_session_create (NULL, 0); - if (common_session == NULL) - goto error; - } - svc->session = afb_session_addref(common_session); - } else { - /* session dedicated to the svc */ - svc->session = afb_session_create (NULL, 0); - if (svc->session == NULL) - goto error; - } - - svc->hookflags = afb_hook_flags_svc(svc->api); - if (service) - *service = to_afb_service(svc); - - /* initialises the listener if needed */ - if (on_event) { - svc->on_event = on_event; - svc->listener = afb_evt_listener_create(&evt_itf, svc); - if (svc->listener == NULL) - goto error; - } - - return svc; - -error: - afb_svc_destroy(svc, service); - return NULL; -} - -/* - * Starts a new service (v1) - */ -int afb_svc_start_v1(struct afb_svc *svc, int (*start)(struct afb_service)) -{ - int rc; - - HOOK(start_before, svc); - rc = start(to_afb_service(svc)); - HOOK(start_after, svc, rc); - return rc; -} - -/* - * Starts a new service (v2) - */ -int afb_svc_start_v2(struct afb_svc *svc, int (*start)()) -{ - int rc; - - HOOK(start_before, svc); - rc = start(); - HOOK(start_after, svc, rc); - return rc; -} - -/* - * Request to updates the hooks - */ -void afb_svc_update_hook(struct afb_svc *svc) -{ - svc->hookflags = afb_hook_flags_svc(svc->api); -} - -/* - * Propagates the event to the service - */ -static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object) -{ - struct afb_svc *svc = closure; - - HOOK(on_event_before, svc, event, eventid, object); - svc->on_event(event, object); - HOOK(on_event_after, svc, event, eventid, object); - json_object_put(object); -} - -/* - * create an svc_req - */ -static struct svc_req *svcreq_create(struct afb_svc *svc, const char *api, const char *verb, struct json_object *args) -{ - 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->async) { - struct afb_svc *svc = svcreq->svc; - if (svcreq->callback) - 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); - } -} - -/* - * Initiates a call for the service - */ -static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cbclosure) -{ - struct afb_svc *svc = closure; - struct svc_req *svcreq; - struct json_object *ierr; - - HOOK(call, svc, api, verb, args); - - /* allocates the request */ - svcreq = svcreq_create(svc, api, verb, args); - if (svcreq == NULL) { - ERROR("out of memory"); - json_object_put(args); - ierr = afb_msg_json_internal_error(); - if (callback) - callback(cbclosure, -1, ierr); - HOOK(call_result, svc, -1, ierr); - json_object_put(ierr); - return; - } - - /* initialises the request */ - svcreq->jobloop = NULL; - svcreq->callback = callback; - svcreq->closure = cbclosure; - svcreq->async = 1; - - /* terminates and frees ressources if needed */ - afb_xreq_process(&svcreq->xreq, svc->apiset); -} - -static int svc_call_sync(void *closure, const char *api, const char *verb, struct json_object *args, - struct json_object **result) -{ - struct afb_svc *svc = closure; - struct svc_req *svcreq; - struct json_object *resu; - int rc; - - HOOK(callsync, svc, api, verb, args); - - /* allocates the request */ - svcreq = svcreq_create(svc, api, verb, args); - if (svcreq == NULL) { - ERROR("out of memory"); - errno = ENOMEM; - json_object_put(args); - resu = afb_msg_json_internal_error(); - rc = -1; - } else { - /* initialises the request */ - svcreq->jobloop = NULL; - svcreq->callback = NULL; - svcreq->result = NULL; - svcreq->status = 0; - svcreq->async = 0; - afb_xreq_addref(&svcreq->xreq); - rc = jobs_enter(NULL, 0, svcreq_sync_enter, svcreq); - if (rc >= 0) - rc = svcreq->status; - resu = (rc >= 0 || svcreq->result) ? svcreq->result : afb_msg_json_internal_error(); - afb_xreq_unref(&svcreq->xreq); - } - HOOK(callsync_result, svc, rc, resu); - if (result) - *result = resu; - else - json_object_put(resu); - return rc; -} - |