2 * Copyright (C) 2016, 2017 "IoT.bzh"
3 * Author: José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
24 #include <json-c/json.h>
26 #define AFB_BINDING_VERSION 0
27 #include <afb/afb-binding.h>
30 #include "afb-apiset.h"
31 #include "afb-api-dyn.h"
32 #include "afb-common.h"
35 #include "afb-export.h"
37 #include "afb-msg-json.h"
38 #include "afb-session.h"
43 /*************************************************************************
44 * internal types and structures
45 ************************************************************************/
64 struct afb_dynapi dynapi;
69 /* version of the api */
80 struct afb_api_dyn *apidyn;
82 /* session for service */
83 struct afb_session *session;
85 /* apiset for service */
86 struct afb_apiset *apiset;
88 /* event listener for service or NULL */
89 struct afb_evt_listener *listener;
93 int (*v1)(struct afb_service);
95 int (*vdyn)(struct afb_dynapi *dynapi);
100 void (*v12)(const char *event, struct json_object *object);
101 void (*vdyn)(struct afb_dynapi *dynapi, const char *event, struct json_object *object);
106 struct afb_binding_interface_v1 v1;
107 struct afb_binding_data_v2 *v2;
111 /************************************************************************************************************/
113 static inline struct afb_dynapi *to_dynapi(struct afb_export *export)
115 return (struct afb_dynapi*)export;
118 static inline struct afb_export *from_dynapi(struct afb_dynapi *dynapi)
120 return (struct afb_export*)dynapi;
123 /*************************************************************************************************************
124 *************************************************************************************************************
125 *************************************************************************************************************
126 *************************************************************************************************************
128 *************************************************************************************************************
129 *************************************************************************************************************
130 *************************************************************************************************************
131 *************************************************************************************************************/
133 /**********************************************
135 **********************************************/
136 static void vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
139 struct afb_export *export = closure;
141 if (!fmt || vasprintf(&p, fmt, args) < 0)
142 vverbose(level, file, line, function, fmt, args);
144 verbose(level, file, line, function, "[API %s] %s", export->apiname, p);
149 static void old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
151 vverbose_cb(closure, level, file, line, NULL, fmt, args);
154 static struct afb_eventid *eventid_make_cb(void *closure, const char *name)
158 struct afb_export *export = closure;
160 /* check daemon state */
161 if (export->state == Api_State_Pre_Init) {
162 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->apiname, name);
167 /* makes the event name */
168 plen = strlen(export->apiname);
170 event = alloca(nlen + plen + 2);
171 memcpy(event, export->apiname, plen);
173 memcpy(event + plen + 1, name, nlen + 1);
175 /* create the event */
176 return afb_evt_eventid_create(event);
179 static struct afb_event event_make_cb(void *closure, const char *name)
181 struct afb_eventid *eventid = eventid_make_cb(closure, name);
182 return afb_evt_event_from_evtid(afb_evt_eventid_to_evtid(eventid));
185 static int event_broadcast_cb(void *closure, const char *name, struct json_object *object)
189 struct afb_export *export = closure;
191 /* check daemon state */
192 if (export->state == Api_State_Pre_Init) {
193 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit", export->apiname, name, json_object_to_json_string(object));
198 /* makes the event name */
199 plen = strlen(export->apiname);
201 event = alloca(nlen + plen + 2);
202 memcpy(event, export->apiname, plen);
204 memcpy(event + plen + 1, name, nlen + 1);
206 /* broadcast the event */
207 return afb_evt_broadcast(event, object);
210 static int rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
212 return afb_common_rootdir_open_locale(filename, flags, locale);
215 static int queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
217 return jobs_queue(group, timeout, callback, argument);
220 static struct afb_req unstore_req_cb(void *closure, struct afb_stored_req *sreq)
222 return afb_xreq_unstore(sreq);
225 static int require_api_cb(void *closure, const char *name, int initialized)
227 struct afb_export *export = closure;
228 if (export->state != Api_State_Init) {
229 ERROR("[API %s] Bad call to 'afb_daemon_require(%s, %d)', must be in Init", export->apiname, name, initialized);
233 return -!(initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->apiset, name, 1);
236 static int rename_api_cb(void *closure, const char *name)
238 struct afb_export *export = closure;
239 if (export->state != Api_State_Pre_Init) {
240 ERROR("[API %s] Bad call to 'afb_daemon_rename(%s)', must be in PreInit", export->apiname, name);
244 if (!afb_api_is_valid_name(name)) {
245 ERROR("[API %s] Can't rename to %s: bad API name", export->apiname, name);
249 NOTICE("[API %s] renamed to [API %s]", export->apiname, name);
250 afb_export_rename(export, name);
254 static int api_new_api_cb(
259 int (*preinit)(void*, struct afb_dynapi *),
260 void *preinit_closure)
262 struct afb_export *export = closure;
263 return afb_api_dyn_add(export->apiset, api, info, noconcurrency, preinit, preinit_closure);
266 /**********************************************
268 **********************************************/
269 static void hooked_vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
271 struct afb_export *export = closure;
274 vverbose_cb(closure, level, file, line, function, fmt, args);
275 afb_hook_ditf_vverbose(export, level, file, line, function, fmt, ap);
279 static void hooked_old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
281 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
284 static struct afb_eventid *hooked_eventid_make_cb(void *closure, const char *name)
286 struct afb_export *export = closure;
287 struct afb_eventid *r = eventid_make_cb(closure, name);
288 afb_hook_ditf_event_make(export, name, r);
292 static struct afb_event hooked_event_make_cb(void *closure, const char *name)
294 struct afb_eventid *eventid = hooked_eventid_make_cb(closure, name);
295 return (struct afb_event){ .itf = eventid ? eventid->itf : NULL, .closure = eventid };
298 static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object)
301 struct afb_export *export = closure;
302 json_object_get(object);
303 afb_hook_ditf_event_broadcast_before(export, name, json_object_get(object));
304 r = event_broadcast_cb(closure, name, object);
305 afb_hook_ditf_event_broadcast_after(export, name, object, r);
306 json_object_put(object);
310 static struct sd_event *hooked_get_event_loop(void *closure)
312 struct afb_export *export = closure;
313 struct sd_event *r = afb_common_get_event_loop();
314 return afb_hook_ditf_get_event_loop(export, r);
317 static struct sd_bus *hooked_get_user_bus(void *closure)
319 struct afb_export *export = closure;
320 struct sd_bus *r = afb_common_get_user_bus();
321 return afb_hook_ditf_get_user_bus(export, r);
324 static struct sd_bus *hooked_get_system_bus(void *closure)
326 struct afb_export *export = closure;
327 struct sd_bus *r = afb_common_get_system_bus();
328 return afb_hook_ditf_get_system_bus(export, r);
331 static int hooked_rootdir_get_fd(void *closure)
333 struct afb_export *export = closure;
334 int r = afb_common_rootdir_get_fd();
335 return afb_hook_ditf_rootdir_get_fd(export, r);
338 static int hooked_rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
340 struct afb_export *export = closure;
341 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
342 return afb_hook_ditf_rootdir_open_locale(export, filename, flags, locale, r);
345 static int hooked_queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
347 struct afb_export *export = closure;
348 int r = queue_job_cb(closure, callback, argument, group, timeout);
349 return afb_hook_ditf_queue_job(export, callback, argument, group, timeout, r);
352 static struct afb_req hooked_unstore_req_cb(void *closure, struct afb_stored_req *sreq)
354 struct afb_export *export = closure;
355 afb_hook_ditf_unstore_req(export, sreq);
356 return unstore_req_cb(closure, sreq);
359 static int hooked_require_api_cb(void *closure, const char *name, int initialized)
362 struct afb_export *export = closure;
363 afb_hook_ditf_require_api(export, name, initialized);
364 result = require_api_cb(closure, name, initialized);
365 return afb_hook_ditf_require_api_result(export, name, initialized, result);
368 static int hooked_rename_api_cb(void *closure, const char *name)
370 struct afb_export *export = closure;
371 const char *oldname = export->apiname;
372 int result = rename_api_cb(closure, name);
373 return afb_hook_ditf_rename_api(export, oldname, name, result);
376 static int hooked_api_new_api_cb(
381 int (*preinit)(void*, struct afb_dynapi *),
382 void *preinit_closure)
385 return api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
387 /**********************************************
389 **********************************************/
390 static const struct afb_daemon_itf daemon_itf = {
391 .vverbose_v1 = old_vverbose_cb,
392 .vverbose_v2 = vverbose_cb,
393 .event_make = event_make_cb,
394 .event_broadcast = event_broadcast_cb,
395 .get_event_loop = afb_common_get_event_loop,
396 .get_user_bus = afb_common_get_user_bus,
397 .get_system_bus = afb_common_get_system_bus,
398 .rootdir_get_fd = afb_common_rootdir_get_fd,
399 .rootdir_open_locale = rootdir_open_locale_cb,
400 .queue_job = queue_job_cb,
401 .unstore_req = unstore_req_cb,
402 .require_api = require_api_cb,
403 .rename_api = rename_api_cb,
404 .new_api = api_new_api_cb,
407 static const struct afb_daemon_itf hooked_daemon_itf = {
408 .vverbose_v1 = hooked_old_vverbose_cb,
409 .vverbose_v2 = hooked_vverbose_cb,
410 .event_make = hooked_event_make_cb,
411 .event_broadcast = hooked_event_broadcast_cb,
412 .get_event_loop = hooked_get_event_loop,
413 .get_user_bus = hooked_get_user_bus,
414 .get_system_bus = hooked_get_system_bus,
415 .rootdir_get_fd = hooked_rootdir_get_fd,
416 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
417 .queue_job = hooked_queue_job_cb,
418 .unstore_req = hooked_unstore_req_cb,
419 .require_api = hooked_require_api_cb,
420 .rename_api = hooked_rename_api_cb,
421 .new_api = hooked_api_new_api_cb,
424 /*************************************************************************************************************
425 *************************************************************************************************************
426 *************************************************************************************************************
427 *************************************************************************************************************
429 *************************************************************************************************************
430 *************************************************************************************************************
431 *************************************************************************************************************
432 *************************************************************************************************************/
434 /* the common session for services sharing their session */
435 static struct afb_session *common_session;
437 /*************************************************************************************************************
438 *************************************************************************************************************
439 *************************************************************************************************************
440 *************************************************************************************************************
442 *************************************************************************************************************
443 *************************************************************************************************************
444 *************************************************************************************************************
445 *************************************************************************************************************/
448 * Structure for requests initiated by the service
452 struct afb_xreq xreq;
454 struct afb_export *export;
458 void (*callback)(void*, int, struct json_object*);
459 void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
464 struct jobloop *jobloop;
465 struct json_object *result;
470 * destroys the call_req
472 static void callreq_destroy(struct afb_xreq *xreq)
474 struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
476 afb_context_disconnect(&callreq->xreq.context);
477 json_object_put(callreq->xreq.json);
478 afb_cred_unref(callreq->xreq.cred);
482 static void callreq_reply_async(struct afb_xreq *xreq, int status, json_object *obj)
484 struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
485 if (callreq->callback)
486 callreq->callback(callreq->closure, status, obj);
487 json_object_put(obj);
490 static void callreq_reply_async_dynapi(struct afb_xreq *xreq, int status, json_object *obj)
492 struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
493 if (callreq->callback_dynapi)
494 callreq->callback_dynapi(callreq->closure, status, obj, to_dynapi(callreq->export));
495 json_object_put(obj);
498 static void callreq_sync_leave(struct call_req *callreq)
500 struct jobloop *jobloop = callreq->jobloop;
503 callreq->jobloop = NULL;
508 static void callreq_reply_sync(struct afb_xreq *xreq, int status, json_object *obj)
510 struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
511 callreq->status = status;
512 callreq->result = obj;
513 callreq_sync_leave(callreq);
516 static void callreq_sync_enter(int signum, void *closure, struct jobloop *jobloop)
518 struct call_req *callreq = closure;
521 callreq->jobloop = jobloop;
522 afb_xreq_process(&callreq->xreq, callreq->export->apiset);
524 callreq->result = afb_msg_json_internal_error();
525 callreq->status = -1;
526 callreq_sync_leave(callreq);
530 /* interface for requests of services */
531 const struct afb_xreq_query_itf afb_export_xreq_async_itf = {
532 .unref = callreq_destroy,
533 .reply = callreq_reply_async
536 /* interface for requests of services */
537 const struct afb_xreq_query_itf afb_export_xreq_async_dynapi_itf = {
538 .unref = callreq_destroy,
539 .reply = callreq_reply_async_dynapi
542 /* interface for requests of services */
543 const struct afb_xreq_query_itf afb_export_xreq_sync_itf = {
544 .unref = callreq_destroy,
545 .reply = callreq_reply_sync
551 static struct call_req *callreq_create(
552 struct afb_export *export,
555 struct json_object *args,
556 const struct afb_xreq_query_itf *itf)
558 struct call_req *callreq;
559 size_t lenapi, lenverb;
562 /* allocates the request */
563 lenapi = 1 + strlen(api);
564 lenverb = 1 + strlen(verb);
565 callreq = malloc(lenapi + lenverb + sizeof *callreq);
566 if (callreq != NULL) {
567 /* initialises the request */
568 afb_xreq_init(&callreq->xreq, itf);
569 afb_context_init(&callreq->xreq.context, export->session, NULL);
570 callreq->xreq.context.validated = 1;
571 copy = (char*)&callreq[1];
572 memcpy(copy, api, lenapi);
573 callreq->xreq.request.api = copy;
574 copy = ©[lenapi];
575 memcpy(copy, verb, lenverb);
576 callreq->xreq.request.verb = copy;
577 callreq->xreq.listener = export->listener;
578 callreq->xreq.json = args;
579 callreq->export = export;
585 * Initiates a call for the service
587 static void svc_call(
591 struct json_object *args,
592 void (*callback)(void*, int, struct json_object*),
595 struct afb_export *export = closure;
596 struct call_req *callreq;
597 struct json_object *ierr;
599 /* allocates the request */
600 callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_itf);
601 if (callreq == NULL) {
602 ERROR("out of memory");
603 json_object_put(args);
604 ierr = afb_msg_json_internal_error();
606 callback(cbclosure, -1, ierr);
607 json_object_put(ierr);
611 /* initialises the request */
612 callreq->jobloop = NULL;
613 callreq->callback = callback;
614 callreq->closure = cbclosure;
616 /* terminates and frees ressources if needed */
617 afb_xreq_process(&callreq->xreq, export->apiset);
620 static void svc_call_dynapi(
621 struct afb_dynapi *dynapi,
624 struct json_object *args,
625 void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
628 struct afb_export *export = from_dynapi(dynapi);
629 struct call_req *callreq;
630 struct json_object *ierr;
632 /* allocates the request */
633 callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_dynapi_itf);
634 if (callreq == NULL) {
635 ERROR("out of memory");
636 json_object_put(args);
637 ierr = afb_msg_json_internal_error();
639 callback(cbclosure, -1, ierr, to_dynapi(export));
640 json_object_put(ierr);
644 /* initialises the request */
645 callreq->jobloop = NULL;
646 callreq->callback_dynapi = callback;
647 callreq->closure = cbclosure;
649 /* terminates and frees ressources if needed */
650 afb_xreq_process(&callreq->xreq, export->apiset);
653 static int svc_call_sync(
657 struct json_object *args,
658 struct json_object **result)
660 struct afb_export *export = closure;
661 struct call_req *callreq;
662 struct json_object *resu;
665 /* allocates the request */
666 callreq = callreq_create(export, api, verb, args, &afb_export_xreq_sync_itf);
667 if (callreq == NULL) {
668 ERROR("out of memory");
670 json_object_put(args);
671 resu = afb_msg_json_internal_error();
674 /* initialises the request */
675 callreq->jobloop = NULL;
676 callreq->callback = NULL;
677 callreq->result = NULL;
679 afb_xreq_unhooked_addref(&callreq->xreq); /* avoid early callreq destruction */
680 rc = jobs_enter(NULL, 0, callreq_sync_enter, callreq);
682 rc = callreq->status;
683 resu = (rc >= 0 || callreq->result) ? callreq->result : afb_msg_json_internal_error();
684 afb_xreq_unhooked_unref(&callreq->xreq);
689 json_object_put(resu);
695 struct afb_export *export;
697 void (*callback)(void*, int, struct json_object*);
698 void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
703 static void svc_hooked_call_result(void *closure, int status, struct json_object *result)
705 struct hooked_call *hc = closure;
706 afb_hook_svc_call_result(hc->export, status, result);
707 hc->callback(hc->cbclosure, status, result);
711 static void svc_hooked_call_dynapi_result(void *closure, int status, struct json_object *result, struct afb_dynapi *dynapi)
713 struct hooked_call *hc = closure;
714 afb_hook_svc_call_result(hc->export, status, result);
715 hc->callback_dynapi(hc->cbclosure, status, result, dynapi);
719 static void svc_hooked_call(
723 struct json_object *args,
724 void (*callback)(void*, int, struct json_object*),
727 struct afb_export *export = closure;
728 struct hooked_call *hc;
730 if (export->hooksvc & afb_hook_flag_svc_call)
731 afb_hook_svc_call(export, api, verb, args);
733 if (export->hooksvc & afb_hook_flag_svc_call_result) {
734 hc = malloc(sizeof *hc);
736 WARNING("allocation failed");
739 hc->callback = callback;
740 hc->cbclosure = cbclosure;
741 callback = svc_hooked_call_result;
745 svc_call(closure, api, verb, args, callback, cbclosure);
748 static void svc_hooked_call_dynapi(
749 struct afb_dynapi *dynapi,
752 struct json_object *args,
753 void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
756 struct afb_export *export = from_dynapi(dynapi);
757 struct hooked_call *hc;
759 if (export->hooksvc & afb_hook_flag_svc_call)
760 afb_hook_svc_call(export, api, verb, args);
762 if (export->hooksvc & afb_hook_flag_svc_call_result) {
763 hc = malloc(sizeof *hc);
765 WARNING("allocation failed");
768 hc->callback_dynapi = callback;
769 hc->cbclosure = cbclosure;
770 callback = svc_hooked_call_dynapi_result;
774 svc_call_dynapi(dynapi, api, verb, args, callback, cbclosure);
777 static int svc_hooked_call_sync(
781 struct json_object *args,
782 struct json_object **result)
784 struct afb_export *export = closure;
785 struct json_object *resu;
788 if (export->hooksvc & afb_hook_flag_svc_callsync)
789 afb_hook_svc_callsync(export, api, verb, args);
791 rc = svc_call_sync(closure, api, verb, args, &resu);
793 if (export->hooksvc & afb_hook_flag_svc_callsync_result)
794 afb_hook_svc_callsync_result(export, rc, resu);
799 json_object_put(resu);
804 /* the interface for services */
805 static const struct afb_service_itf service_itf = {
807 .call_sync = svc_call_sync
810 /* the interface for services */
811 static const struct afb_service_itf hooked_service_itf = {
812 .call = svc_hooked_call,
813 .call_sync = svc_hooked_call_sync
816 /*************************************************************************************************************
817 *************************************************************************************************************
818 *************************************************************************************************************
819 *************************************************************************************************************
821 *************************************************************************************************************
822 *************************************************************************************************************
823 *************************************************************************************************************
824 *************************************************************************************************************/
826 static int api_set_verbs_v2_cb(
827 struct afb_dynapi *dynapi,
828 const struct afb_verb_v2 *verbs)
830 struct afb_export *export = from_dynapi(dynapi);
832 if (export->apidyn) {
833 afb_api_dyn_set_verbs_v2(export->apidyn, verbs);
841 static int api_add_verb_cb(
842 struct afb_dynapi *dynapi,
845 void (*callback)(struct afb_request *request),
847 const struct afb_auth *auth,
850 struct afb_export *export = from_dynapi(dynapi);
853 return afb_api_dyn_add_verb(export->apidyn, verb, info, callback, vcbdata, auth, session);
859 static int api_sub_verb_cb(
860 struct afb_dynapi *dynapi,
863 struct afb_export *export = from_dynapi(dynapi);
866 return afb_api_dyn_sub_verb(export->apidyn, verb);
872 static int api_set_on_event_cb(
873 struct afb_dynapi *dynapi,
874 void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
876 struct afb_export *export = from_dynapi(dynapi);
877 return afb_export_handle_events_vdyn(export, onevent);
880 static int api_set_on_init_cb(
881 struct afb_dynapi *dynapi,
882 int (*oninit)(struct afb_dynapi *dynapi))
884 struct afb_export *export = from_dynapi(dynapi);
886 return afb_export_handle_init_vdyn(export, oninit);
889 static void api_seal_cb(
890 struct afb_dynapi *dynapi)
892 struct afb_export *export = from_dynapi(dynapi);
894 export->apidyn = NULL;
897 static int hooked_api_set_verbs_v2_cb(
898 struct afb_dynapi *dynapi,
899 const struct afb_verb_v2 *verbs)
902 return api_set_verbs_v2_cb(dynapi, verbs);
905 static int hooked_api_add_verb_cb(
906 struct afb_dynapi *dynapi,
909 void (*callback)(struct afb_request *request),
911 const struct afb_auth *auth,
915 return api_add_verb_cb(dynapi, verb, info, callback, vcbdata, auth, session);
918 static int hooked_api_sub_verb_cb(
919 struct afb_dynapi *dynapi,
923 return api_sub_verb_cb(dynapi, verb);
926 static int hooked_api_set_on_event_cb(
927 struct afb_dynapi *dynapi,
928 void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
931 return api_set_on_event_cb(dynapi, onevent);
934 static int hooked_api_set_on_init_cb(
935 struct afb_dynapi *dynapi,
936 int (*oninit)(struct afb_dynapi *dynapi))
939 return api_set_on_init_cb(dynapi, oninit);
942 static void hooked_api_seal_cb(
943 struct afb_dynapi *dynapi)
949 static const struct afb_dynapi_itf dynapi_itf = {
951 .vverbose = (void*)vverbose_cb,
953 .get_event_loop = afb_common_get_event_loop,
954 .get_user_bus = afb_common_get_user_bus,
955 .get_system_bus = afb_common_get_system_bus,
956 .rootdir_get_fd = afb_common_rootdir_get_fd,
957 .rootdir_open_locale = rootdir_open_locale_cb,
958 .queue_job = queue_job_cb,
960 .require_api = require_api_cb,
961 .rename_api = rename_api_cb,
963 .event_broadcast = event_broadcast_cb,
964 .eventid_make = eventid_make_cb,
966 .call = svc_call_dynapi,
967 .call_sync = svc_call_sync,
969 .api_new_api = api_new_api_cb,
970 .api_set_verbs_v2 = api_set_verbs_v2_cb,
971 .api_add_verb = api_add_verb_cb,
972 .api_sub_verb = api_sub_verb_cb,
973 .api_set_on_event = api_set_on_event_cb,
974 .api_set_on_init = api_set_on_init_cb,
975 .api_seal = api_seal_cb,
978 static const struct afb_dynapi_itf hooked_dynapi_itf = {
980 .vverbose = hooked_vverbose_cb,
982 .get_event_loop = hooked_get_event_loop,
983 .get_user_bus = hooked_get_user_bus,
984 .get_system_bus = hooked_get_system_bus,
985 .rootdir_get_fd = hooked_rootdir_get_fd,
986 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
987 .queue_job = hooked_queue_job_cb,
989 .require_api = hooked_require_api_cb,
990 .rename_api = hooked_rename_api_cb,
992 .event_broadcast = hooked_event_broadcast_cb,
993 .eventid_make = hooked_eventid_make_cb,
995 .call = svc_hooked_call_dynapi,
996 .call_sync = svc_hooked_call_sync,
998 .api_new_api = hooked_api_new_api_cb,
999 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1000 .api_add_verb = hooked_api_add_verb_cb,
1001 .api_sub_verb = hooked_api_sub_verb_cb,
1002 .api_set_on_event = hooked_api_set_on_event_cb,
1003 .api_set_on_init = hooked_api_set_on_init_cb,
1004 .api_seal = hooked_api_seal_cb,
1007 /*************************************************************************************************************
1008 *************************************************************************************************************
1009 *************************************************************************************************************
1010 *************************************************************************************************************
1012 *************************************************************************************************************
1013 *************************************************************************************************************
1014 *************************************************************************************************************
1015 *************************************************************************************************************/
1018 * Propagates the event to the service
1020 static void export_on_event_v12(void *closure, const char *event, int eventid, struct json_object *object)
1022 struct afb_export *export = closure;
1024 if (export->hooksvc & afb_hook_flag_svc_on_event_before)
1025 afb_hook_svc_on_event_before(export, event, eventid, object);
1026 export->on_event.v12(event, object);
1027 if (export->hooksvc & afb_hook_flag_svc_on_event_after)
1028 afb_hook_svc_on_event_after(export, event, eventid, object);
1029 json_object_put(object);
1032 /* the interface for events */
1033 static const struct afb_evt_itf evt_v12_itf = {
1034 .broadcast = export_on_event_v12,
1035 .push = export_on_event_v12
1039 * Propagates the event to the service
1041 static void export_on_event_vdyn(void *closure, const char *event, int eventid, struct json_object *object)
1043 struct afb_export *export = closure;
1045 if (export->hooksvc & afb_hook_flag_svc_on_event_before)
1046 afb_hook_svc_on_event_before(export, event, eventid, object);
1047 export->on_event.vdyn(to_dynapi(export), event, object);
1048 if (export->hooksvc & afb_hook_flag_svc_on_event_after)
1049 afb_hook_svc_on_event_after(export, event, eventid, object);
1050 json_object_put(object);
1053 /* the interface for events */
1054 static const struct afb_evt_itf evt_vdyn_itf = {
1055 .broadcast = export_on_event_vdyn,
1056 .push = export_on_event_vdyn
1059 /*************************************************************************************************************
1060 *************************************************************************************************************
1061 *************************************************************************************************************
1062 *************************************************************************************************************
1064 *************************************************************************************************************
1065 *************************************************************************************************************
1066 *************************************************************************************************************
1067 *************************************************************************************************************/
1069 static struct afb_export *create(struct afb_apiset *apiset, const char *apiname, enum afb_api_version version)
1071 struct afb_export *export;
1073 /* session shared with other exports */
1074 if (common_session == NULL) {
1075 common_session = afb_session_create (0);
1076 if (common_session == NULL)
1079 export = calloc(1, sizeof *export);
1083 memset(export, 0, sizeof *export);
1084 export->apiname = strdup(apiname);
1085 export->dynapi.apiname = export->apiname;
1086 export->version = version;
1087 export->state = Api_State_Pre_Init;
1088 export->session = afb_session_addref(common_session);
1089 export->apiset = afb_apiset_addref(apiset);
1094 void afb_export_destroy(struct afb_export *export)
1097 if (export->listener != NULL)
1098 afb_evt_listener_unref(export->listener);
1099 afb_session_unref(export->session);
1100 afb_apiset_unref(export->apiset);
1101 free(export->apiname);
1106 struct afb_export *afb_export_create_v1(struct afb_apiset *apiset, const char *apiname, int (*init)(struct afb_service), void (*onevent)(const char*, struct json_object*))
1108 struct afb_export *export = create(apiset, apiname, Api_Version_1);
1110 export->init.v1 = init;
1111 export->on_event.v12 = onevent;
1112 export->export.v1.mode = AFB_MODE_LOCAL;
1113 export->export.v1.daemon.closure = export;
1114 afb_export_verbosity_set(export, verbosity);
1115 afb_export_update_hook(export);
1120 struct afb_export *afb_export_create_v2(struct afb_apiset *apiset, const char *apiname, struct afb_binding_data_v2 *data, int (*init)(), void (*onevent)(const char*, struct json_object*))
1122 struct afb_export *export = create(apiset, apiname, Api_Version_2);
1124 export->init.v2 = init;
1125 export->on_event.v12 = onevent;
1126 export->export.v2 = data;
1127 data->daemon.closure = export;
1128 data->service.closure = export;
1129 afb_export_verbosity_set(export, verbosity);
1130 afb_export_update_hook(export);
1135 struct afb_export *afb_export_create_vdyn(struct afb_apiset *apiset, const char *apiname, struct afb_api_dyn *apidyn)
1137 struct afb_export *export = create(apiset, apiname, Api_Version_Dyn);
1139 export->apidyn = apidyn;
1140 afb_export_verbosity_set(export, verbosity);
1141 afb_export_update_hook(export);
1146 void afb_export_rename(struct afb_export *export, const char *apiname)
1148 free(export->apiname);
1149 export->apiname = strdup(apiname);
1150 export->dynapi.apiname = export->apiname;
1151 afb_export_update_hook(export);
1154 const char *afb_export_apiname(const struct afb_export *export)
1156 return export->apiname;
1159 void afb_export_update_hook(struct afb_export *export)
1161 export->hookditf = afb_hook_flags_ditf(export->apiname);
1162 export->hooksvc = afb_hook_flags_svc(export->apiname);
1163 export->dynapi.itf = export->hookditf|export->hooksvc ? &hooked_dynapi_itf : &dynapi_itf;
1165 switch (export->version) {
1167 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1170 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1171 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1176 struct afb_binding_interface_v1 *afb_export_get_interface_v1(struct afb_export *export)
1178 return export->version == Api_Version_1 ? &export->export.v1 : NULL;
1181 int afb_export_unshare_session(struct afb_export *export)
1183 if (export->session == common_session) {
1184 export->session = afb_session_create (0);
1185 if (export->session)
1186 afb_session_unref(common_session);
1188 export->session = common_session;
1195 void afb_export_set_apiset(struct afb_export *export, struct afb_apiset *apiset)
1197 struct afb_apiset *prvset = export->apiset;
1198 export->apiset = afb_apiset_addref(apiset);
1199 afb_apiset_unref(prvset);
1202 struct afb_apiset *afb_export_get_apiset(struct afb_export *export)
1204 return export->apiset;
1207 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1210 switch (export->version) {
1211 case Api_Version_1: case Api_Version_2: break;
1213 ERROR("invalid version 12 for API %s", export->apiname);
1218 /* set the event handler */
1220 if (export->listener) {
1221 afb_evt_listener_unref(export->listener);
1222 export->listener = NULL;
1224 export->on_event.v12 = on_event;
1226 export->on_event.v12 = on_event;
1227 if (!export->listener) {
1228 export->listener = afb_evt_listener_create(&evt_v12_itf, export);
1229 if (export->listener == NULL)
1236 int afb_export_handle_events_vdyn(struct afb_export *export, void (*on_event)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
1239 switch (export->version) {
1240 case Api_Version_Dyn: break;
1242 ERROR("invalid version Dyn for API %s", export->apiname);
1247 /* set the event handler */
1249 if (export->listener) {
1250 afb_evt_listener_unref(export->listener);
1251 export->listener = NULL;
1253 export->on_event.vdyn = on_event;
1255 export->on_event.vdyn = on_event;
1256 if (!export->listener) {
1257 export->listener = afb_evt_listener_create(&evt_vdyn_itf, export);
1258 if (export->listener == NULL)
1265 int afb_export_handle_init_vdyn(struct afb_export *export, int (*oninit)(struct afb_dynapi *dynapi))
1267 if (export->state != Api_State_Pre_Init) {
1268 ERROR("[API %s] Bad call to 'afb_dynapi_on_init', must be in PreInit", export->apiname);
1273 export->init.vdyn = oninit;
1278 * Starts a new service (v1)
1280 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1282 return regfun(&export->export.v1);
1285 int afb_export_preinit_vdyn(struct afb_export *export, int (*preinit)(void*, struct afb_dynapi*), void *closure)
1287 return preinit(closure, to_dynapi(export));
1290 int afb_export_verbosity_get(const struct afb_export *export)
1292 return export->dynapi.verbosity;
1295 void afb_export_verbosity_set(struct afb_export *export, int level)
1297 export->dynapi.verbosity = level;
1298 switch (export->version) {
1299 case Api_Version_1: export->export.v1.verbosity = level; break;
1300 case Api_Version_2: export->export.v2->verbosity = level; break;
1304 /*************************************************************************************************************
1305 *************************************************************************************************************
1306 *************************************************************************************************************
1307 *************************************************************************************************************
1309 *************************************************************************************************************
1310 *************************************************************************************************************
1311 *************************************************************************************************************
1312 *************************************************************************************************************/
1314 int afb_export_start(struct afb_export *export, int share_session, int onneed, struct afb_apiset *apiset)
1319 if (export->state != Api_State_Pre_Init) {
1320 /* not an error when onneed */
1324 /* already started: it is an error */
1325 ERROR("Service of API %s already started", export->apiname);
1329 /* unshare the session if asked */
1330 if (!share_session) {
1331 rc = afb_export_unshare_session(export);
1333 ERROR("Can't unshare the session for %s", export->apiname);
1338 /* set event handling */
1339 switch (export->version) {
1342 rc = afb_export_handle_events_v12(export, export->on_event.v12);
1349 ERROR("Can't set event handler for %s", export->apiname);
1353 /* Starts the service */
1354 if (export->hooksvc & afb_hook_flag_svc_start_before)
1355 afb_hook_svc_start_before(export);
1356 export->state = Api_State_Init;
1357 switch (export->version) {
1359 rc = export->init.v1 ? export->init.v1((struct afb_service){ .itf = &hooked_service_itf, .closure = export }) : 0;
1362 rc = export->init.v2 ? export->init.v2() : 0;
1364 case Api_Version_Dyn:
1365 rc = export->init.vdyn ? export->init.vdyn(to_dynapi(export)) : 0;
1370 export->state = Api_State_Run;
1371 if (export->hooksvc & afb_hook_flag_svc_start_after)
1372 afb_hook_svc_start_after(export, rc);
1374 /* initialisation error */
1375 ERROR("Initialisation of service API %s failed (%d): %m", export->apiname, rc);