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"
33 #include "afb-systemd.h"
36 #include "afb-export.h"
38 #include "afb-msg-json.h"
39 #include "afb-session.h"
44 /*************************************************************************
45 * internal types and structures
46 ************************************************************************/
65 struct afb_dynapi dynapi;
70 /* version of the api */
81 struct afb_api_dyn *apidyn;
83 /* session for service */
84 struct afb_session *session;
86 /* apiset for service */
87 struct afb_apiset *apiset;
89 /* event listener for service or NULL */
90 struct afb_evt_listener *listener;
94 int (*v1)(struct afb_service);
96 int (*vdyn)(struct afb_dynapi *dynapi);
101 void (*v12)(const char *event, struct json_object *object);
102 void (*vdyn)(struct afb_dynapi *dynapi, const char *event, struct json_object *object);
107 struct afb_binding_interface_v1 v1;
108 struct afb_binding_data_v2 *v2;
112 /************************************************************************************************************/
114 static inline struct afb_dynapi *to_dynapi(struct afb_export *export)
116 return (struct afb_dynapi*)export;
119 static inline struct afb_export *from_dynapi(struct afb_dynapi *dynapi)
121 return (struct afb_export*)dynapi;
124 /*************************************************************************************************************
125 *************************************************************************************************************
126 *************************************************************************************************************
127 *************************************************************************************************************
129 *************************************************************************************************************
130 *************************************************************************************************************
131 *************************************************************************************************************
132 *************************************************************************************************************/
134 /**********************************************
136 **********************************************/
137 static void vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
140 struct afb_export *export = closure;
142 if (!fmt || vasprintf(&p, fmt, args) < 0)
143 vverbose(level, file, line, function, fmt, args);
145 verbose(level, file, line, function, "[API %s] %s", export->apiname, p);
150 static void old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
152 vverbose_cb(closure, level, file, line, NULL, fmt, args);
155 static struct afb_eventid *eventid_make_cb(void *closure, const char *name)
157 struct afb_export *export = closure;
159 /* check daemon state */
160 if (export->state == Api_State_Pre_Init) {
161 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->apiname, name);
166 /* create the event */
167 return afb_evt_eventid_create2(export->apiname, name);
170 static struct afb_event event_make_cb(void *closure, const char *name)
172 struct afb_eventid *eventid = eventid_make_cb(closure, name);
173 return afb_evt_event_from_evtid(afb_evt_eventid_to_evtid(eventid));
176 static int event_broadcast_cb(void *closure, const char *name, struct json_object *object)
180 struct afb_export *export = closure;
182 /* check daemon state */
183 if (export->state == Api_State_Pre_Init) {
184 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));
189 /* makes the event name */
190 plen = strlen(export->apiname);
192 event = alloca(nlen + plen + 2);
193 memcpy(event, export->apiname, plen);
195 memcpy(event + plen + 1, name, nlen + 1);
197 /* broadcast the event */
198 return afb_evt_broadcast(event, object);
201 static int rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
203 return afb_common_rootdir_open_locale(filename, flags, locale);
206 static int queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
208 return jobs_queue(group, timeout, callback, argument);
211 static struct afb_req unstore_req_cb(void *closure, struct afb_stored_req *sreq)
213 return afb_xreq_unstore(sreq);
216 static int require_api_cb(void *closure, const char *name, int initialized)
218 struct afb_export *export = closure;
219 if (export->state != Api_State_Init) {
220 ERROR("[API %s] Bad call to 'afb_daemon_require(%s, %d)', must be in Init", export->apiname, name, initialized);
224 return -!(initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->apiset, name, 1);
227 static int rename_api_cb(void *closure, const char *name)
229 struct afb_export *export = closure;
230 if (export->state != Api_State_Pre_Init) {
231 ERROR("[API %s] Bad call to 'afb_daemon_rename(%s)', must be in PreInit", export->apiname, name);
235 if (!afb_api_is_valid_name(name, 1)) {
236 ERROR("[API %s] Can't rename to %s: bad API name", export->apiname, name);
240 NOTICE("[API %s] renamed to [API %s]", export->apiname, name);
241 afb_export_rename(export, name);
245 static int api_new_api_cb(
250 int (*preinit)(void*, struct afb_dynapi *),
251 void *preinit_closure)
253 struct afb_export *export = closure;
254 return afb_api_dyn_add(export->apiset, api, info, noconcurrency, preinit, preinit_closure);
257 /**********************************************
259 **********************************************/
260 static void hooked_vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
262 struct afb_export *export = closure;
265 vverbose_cb(closure, level, file, line, function, fmt, args);
266 afb_hook_ditf_vverbose(export, level, file, line, function, fmt, ap);
270 static void hooked_old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
272 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
275 static struct afb_eventid *hooked_eventid_make_cb(void *closure, const char *name)
277 struct afb_export *export = closure;
278 struct afb_eventid *r = eventid_make_cb(closure, name);
279 afb_hook_ditf_event_make(export, name, r);
283 static struct afb_event hooked_event_make_cb(void *closure, const char *name)
285 struct afb_eventid *eventid = hooked_eventid_make_cb(closure, name);
286 return (struct afb_event){ .itf = eventid ? eventid->itf : NULL, .closure = eventid };
289 static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object)
292 struct afb_export *export = closure;
293 json_object_get(object);
294 afb_hook_ditf_event_broadcast_before(export, name, json_object_get(object));
295 r = event_broadcast_cb(closure, name, object);
296 afb_hook_ditf_event_broadcast_after(export, name, object, r);
297 json_object_put(object);
301 static struct sd_event *hooked_get_event_loop(void *closure)
303 struct afb_export *export = closure;
304 struct sd_event *r = afb_systemd_get_event_loop();
305 return afb_hook_ditf_get_event_loop(export, r);
308 static struct sd_bus *hooked_get_user_bus(void *closure)
310 struct afb_export *export = closure;
311 struct sd_bus *r = afb_systemd_get_user_bus();
312 return afb_hook_ditf_get_user_bus(export, r);
315 static struct sd_bus *hooked_get_system_bus(void *closure)
317 struct afb_export *export = closure;
318 struct sd_bus *r = afb_systemd_get_system_bus();
319 return afb_hook_ditf_get_system_bus(export, r);
322 static int hooked_rootdir_get_fd(void *closure)
324 struct afb_export *export = closure;
325 int r = afb_common_rootdir_get_fd();
326 return afb_hook_ditf_rootdir_get_fd(export, r);
329 static int hooked_rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
331 struct afb_export *export = closure;
332 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
333 return afb_hook_ditf_rootdir_open_locale(export, filename, flags, locale, r);
336 static int hooked_queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
338 struct afb_export *export = closure;
339 int r = queue_job_cb(closure, callback, argument, group, timeout);
340 return afb_hook_ditf_queue_job(export, callback, argument, group, timeout, r);
343 static struct afb_req hooked_unstore_req_cb(void *closure, struct afb_stored_req *sreq)
345 struct afb_export *export = closure;
346 afb_hook_ditf_unstore_req(export, sreq);
347 return unstore_req_cb(closure, sreq);
350 static int hooked_require_api_cb(void *closure, const char *name, int initialized)
353 struct afb_export *export = closure;
354 afb_hook_ditf_require_api(export, name, initialized);
355 result = require_api_cb(closure, name, initialized);
356 return afb_hook_ditf_require_api_result(export, name, initialized, result);
359 static int hooked_rename_api_cb(void *closure, const char *name)
361 struct afb_export *export = closure;
362 const char *oldname = export->apiname;
363 int result = rename_api_cb(closure, name);
364 return afb_hook_ditf_rename_api(export, oldname, name, result);
367 static int hooked_api_new_api_cb(
372 int (*preinit)(void*, struct afb_dynapi *),
373 void *preinit_closure)
376 return api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
378 /**********************************************
380 **********************************************/
381 static const struct afb_daemon_itf daemon_itf = {
382 .vverbose_v1 = old_vverbose_cb,
383 .vverbose_v2 = vverbose_cb,
384 .event_make = event_make_cb,
385 .event_broadcast = event_broadcast_cb,
386 .get_event_loop = afb_systemd_get_event_loop,
387 .get_user_bus = afb_systemd_get_user_bus,
388 .get_system_bus = afb_systemd_get_system_bus,
389 .rootdir_get_fd = afb_common_rootdir_get_fd,
390 .rootdir_open_locale = rootdir_open_locale_cb,
391 .queue_job = queue_job_cb,
392 .unstore_req = unstore_req_cb,
393 .require_api = require_api_cb,
394 .rename_api = rename_api_cb,
395 .new_api = api_new_api_cb,
398 static const struct afb_daemon_itf hooked_daemon_itf = {
399 .vverbose_v1 = hooked_old_vverbose_cb,
400 .vverbose_v2 = hooked_vverbose_cb,
401 .event_make = hooked_event_make_cb,
402 .event_broadcast = hooked_event_broadcast_cb,
403 .get_event_loop = hooked_get_event_loop,
404 .get_user_bus = hooked_get_user_bus,
405 .get_system_bus = hooked_get_system_bus,
406 .rootdir_get_fd = hooked_rootdir_get_fd,
407 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
408 .queue_job = hooked_queue_job_cb,
409 .unstore_req = hooked_unstore_req_cb,
410 .require_api = hooked_require_api_cb,
411 .rename_api = hooked_rename_api_cb,
412 .new_api = hooked_api_new_api_cb,
415 /*************************************************************************************************************
416 *************************************************************************************************************
417 *************************************************************************************************************
418 *************************************************************************************************************
420 *************************************************************************************************************
421 *************************************************************************************************************
422 *************************************************************************************************************
423 *************************************************************************************************************/
425 /* the common session for services sharing their session */
426 static struct afb_session *common_session;
428 /*************************************************************************************************************
429 *************************************************************************************************************
430 *************************************************************************************************************
431 *************************************************************************************************************
433 *************************************************************************************************************
434 *************************************************************************************************************
435 *************************************************************************************************************
436 *************************************************************************************************************/
439 * Structure for requests initiated by the service
443 struct afb_xreq xreq;
445 struct afb_export *export;
449 void (*callback)(void*, int, struct json_object*);
450 void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
455 struct jobloop *jobloop;
456 struct json_object *result;
461 * destroys the call_req
463 static void callreq_destroy(struct afb_xreq *xreq)
465 struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
467 afb_context_disconnect(&callreq->xreq.context);
468 json_object_put(callreq->xreq.json);
469 afb_cred_unref(callreq->xreq.cred);
473 static void callreq_reply_async(struct afb_xreq *xreq, int status, json_object *obj)
475 struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
476 if (callreq->callback)
477 callreq->callback(callreq->closure, status, obj);
478 json_object_put(obj);
481 static void callreq_reply_async_dynapi(struct afb_xreq *xreq, int status, json_object *obj)
483 struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
484 if (callreq->callback_dynapi)
485 callreq->callback_dynapi(callreq->closure, status, obj, to_dynapi(callreq->export));
486 json_object_put(obj);
489 static void callreq_sync_leave(struct call_req *callreq)
491 struct jobloop *jobloop = callreq->jobloop;
494 callreq->jobloop = NULL;
499 static void callreq_reply_sync(struct afb_xreq *xreq, int status, json_object *obj)
501 struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
502 callreq->status = status;
503 callreq->result = obj;
504 callreq_sync_leave(callreq);
507 static void callreq_sync_enter(int signum, void *closure, struct jobloop *jobloop)
509 struct call_req *callreq = closure;
512 callreq->jobloop = jobloop;
513 afb_xreq_process(&callreq->xreq, callreq->export->apiset);
515 callreq->result = afb_msg_json_internal_error();
516 callreq->status = -1;
517 callreq_sync_leave(callreq);
521 /* interface for requests of services */
522 const struct afb_xreq_query_itf afb_export_xreq_async_itf = {
523 .unref = callreq_destroy,
524 .reply = callreq_reply_async
527 /* interface for requests of services */
528 const struct afb_xreq_query_itf afb_export_xreq_async_dynapi_itf = {
529 .unref = callreq_destroy,
530 .reply = callreq_reply_async_dynapi
533 /* interface for requests of services */
534 const struct afb_xreq_query_itf afb_export_xreq_sync_itf = {
535 .unref = callreq_destroy,
536 .reply = callreq_reply_sync
542 static struct call_req *callreq_create(
543 struct afb_export *export,
546 struct json_object *args,
547 const struct afb_xreq_query_itf *itf)
549 struct call_req *callreq;
550 size_t lenapi, lenverb;
553 /* allocates the request */
554 lenapi = 1 + strlen(api);
555 lenverb = 1 + strlen(verb);
556 callreq = malloc(lenapi + lenverb + sizeof *callreq);
557 if (callreq != NULL) {
558 /* initialises the request */
559 afb_xreq_init(&callreq->xreq, itf);
560 afb_context_init(&callreq->xreq.context, export->session, NULL);
561 callreq->xreq.context.validated = 1;
562 copy = (char*)&callreq[1];
563 memcpy(copy, api, lenapi);
564 callreq->xreq.request.api = copy;
565 copy = ©[lenapi];
566 memcpy(copy, verb, lenverb);
567 callreq->xreq.request.verb = copy;
568 callreq->xreq.listener = export->listener;
569 callreq->xreq.json = args;
570 callreq->export = export;
576 * Initiates a call for the service
578 static void svc_call(
582 struct json_object *args,
583 void (*callback)(void*, int, struct json_object*),
586 struct afb_export *export = closure;
587 struct call_req *callreq;
588 struct json_object *ierr;
590 /* allocates the request */
591 callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_itf);
592 if (callreq == NULL) {
593 ERROR("out of memory");
594 json_object_put(args);
595 ierr = afb_msg_json_internal_error();
597 callback(cbclosure, -1, ierr);
598 json_object_put(ierr);
602 /* initialises the request */
603 callreq->jobloop = NULL;
604 callreq->callback = callback;
605 callreq->closure = cbclosure;
607 /* terminates and frees ressources if needed */
608 afb_xreq_process(&callreq->xreq, export->apiset);
611 static void svc_call_dynapi(
612 struct afb_dynapi *dynapi,
615 struct json_object *args,
616 void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
619 struct afb_export *export = from_dynapi(dynapi);
620 struct call_req *callreq;
621 struct json_object *ierr;
623 /* allocates the request */
624 callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_dynapi_itf);
625 if (callreq == NULL) {
626 ERROR("out of memory");
627 json_object_put(args);
628 ierr = afb_msg_json_internal_error();
630 callback(cbclosure, -1, ierr, to_dynapi(export));
631 json_object_put(ierr);
635 /* initialises the request */
636 callreq->jobloop = NULL;
637 callreq->callback_dynapi = callback;
638 callreq->closure = cbclosure;
640 /* terminates and frees ressources if needed */
641 afb_xreq_process(&callreq->xreq, export->apiset);
644 static int svc_call_sync(
648 struct json_object *args,
649 struct json_object **result)
651 struct afb_export *export = closure;
652 struct call_req *callreq;
653 struct json_object *resu;
656 /* allocates the request */
657 callreq = callreq_create(export, api, verb, args, &afb_export_xreq_sync_itf);
658 if (callreq == NULL) {
659 ERROR("out of memory");
661 json_object_put(args);
662 resu = afb_msg_json_internal_error();
665 /* initialises the request */
666 callreq->jobloop = NULL;
667 callreq->callback = NULL;
668 callreq->result = NULL;
670 afb_xreq_unhooked_addref(&callreq->xreq); /* avoid early callreq destruction */
671 rc = jobs_enter(NULL, 0, callreq_sync_enter, callreq);
673 rc = callreq->status;
674 resu = (rc >= 0 || callreq->result) ? callreq->result : afb_msg_json_internal_error();
675 afb_xreq_unhooked_unref(&callreq->xreq);
680 json_object_put(resu);
686 struct afb_export *export;
688 void (*callback)(void*, int, struct json_object*);
689 void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
694 static void svc_hooked_call_result(void *closure, int status, struct json_object *result)
696 struct hooked_call *hc = closure;
697 afb_hook_svc_call_result(hc->export, status, result);
698 hc->callback(hc->cbclosure, status, result);
702 static void svc_hooked_call_dynapi_result(void *closure, int status, struct json_object *result, struct afb_dynapi *dynapi)
704 struct hooked_call *hc = closure;
705 afb_hook_svc_call_result(hc->export, status, result);
706 hc->callback_dynapi(hc->cbclosure, status, result, dynapi);
710 static void svc_hooked_call(
714 struct json_object *args,
715 void (*callback)(void*, int, struct json_object*),
718 struct afb_export *export = closure;
719 struct hooked_call *hc;
721 if (export->hooksvc & afb_hook_flag_svc_call)
722 afb_hook_svc_call(export, api, verb, args);
724 if (export->hooksvc & afb_hook_flag_svc_call_result) {
725 hc = malloc(sizeof *hc);
727 WARNING("allocation failed");
730 hc->callback = callback;
731 hc->cbclosure = cbclosure;
732 callback = svc_hooked_call_result;
736 svc_call(closure, api, verb, args, callback, cbclosure);
739 static void svc_hooked_call_dynapi(
740 struct afb_dynapi *dynapi,
743 struct json_object *args,
744 void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
747 struct afb_export *export = from_dynapi(dynapi);
748 struct hooked_call *hc;
750 if (export->hooksvc & afb_hook_flag_svc_call)
751 afb_hook_svc_call(export, api, verb, args);
753 if (export->hooksvc & afb_hook_flag_svc_call_result) {
754 hc = malloc(sizeof *hc);
756 WARNING("allocation failed");
759 hc->callback_dynapi = callback;
760 hc->cbclosure = cbclosure;
761 callback = svc_hooked_call_dynapi_result;
765 svc_call_dynapi(dynapi, api, verb, args, callback, cbclosure);
768 static int svc_hooked_call_sync(
772 struct json_object *args,
773 struct json_object **result)
775 struct afb_export *export = closure;
776 struct json_object *resu;
779 if (export->hooksvc & afb_hook_flag_svc_callsync)
780 afb_hook_svc_callsync(export, api, verb, args);
782 rc = svc_call_sync(closure, api, verb, args, &resu);
784 if (export->hooksvc & afb_hook_flag_svc_callsync_result)
785 afb_hook_svc_callsync_result(export, rc, resu);
790 json_object_put(resu);
795 /* the interface for services */
796 static const struct afb_service_itf service_itf = {
798 .call_sync = svc_call_sync
801 /* the interface for services */
802 static const struct afb_service_itf hooked_service_itf = {
803 .call = svc_hooked_call,
804 .call_sync = svc_hooked_call_sync
807 /*************************************************************************************************************
808 *************************************************************************************************************
809 *************************************************************************************************************
810 *************************************************************************************************************
812 *************************************************************************************************************
813 *************************************************************************************************************
814 *************************************************************************************************************
815 *************************************************************************************************************/
817 static int api_set_verbs_v2_cb(
818 struct afb_dynapi *dynapi,
819 const struct afb_verb_v2 *verbs)
821 struct afb_export *export = from_dynapi(dynapi);
823 if (export->apidyn) {
824 afb_api_dyn_set_verbs_v2(export->apidyn, verbs);
832 static int api_add_verb_cb(
833 struct afb_dynapi *dynapi,
836 void (*callback)(struct afb_request *request),
838 const struct afb_auth *auth,
841 struct afb_export *export = from_dynapi(dynapi);
844 return afb_api_dyn_add_verb(export->apidyn, verb, info, callback, vcbdata, auth, session);
850 static int api_sub_verb_cb(
851 struct afb_dynapi *dynapi,
854 struct afb_export *export = from_dynapi(dynapi);
857 return afb_api_dyn_sub_verb(export->apidyn, verb);
863 static int api_set_on_event_cb(
864 struct afb_dynapi *dynapi,
865 void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
867 struct afb_export *export = from_dynapi(dynapi);
868 return afb_export_handle_events_vdyn(export, onevent);
871 static int api_set_on_init_cb(
872 struct afb_dynapi *dynapi,
873 int (*oninit)(struct afb_dynapi *dynapi))
875 struct afb_export *export = from_dynapi(dynapi);
877 return afb_export_handle_init_vdyn(export, oninit);
880 static void api_seal_cb(
881 struct afb_dynapi *dynapi)
883 struct afb_export *export = from_dynapi(dynapi);
885 export->apidyn = NULL;
888 static int hooked_api_set_verbs_v2_cb(
889 struct afb_dynapi *dynapi,
890 const struct afb_verb_v2 *verbs)
893 return api_set_verbs_v2_cb(dynapi, verbs);
896 static int hooked_api_add_verb_cb(
897 struct afb_dynapi *dynapi,
900 void (*callback)(struct afb_request *request),
902 const struct afb_auth *auth,
906 return api_add_verb_cb(dynapi, verb, info, callback, vcbdata, auth, session);
909 static int hooked_api_sub_verb_cb(
910 struct afb_dynapi *dynapi,
914 return api_sub_verb_cb(dynapi, verb);
917 static int hooked_api_set_on_event_cb(
918 struct afb_dynapi *dynapi,
919 void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
922 return api_set_on_event_cb(dynapi, onevent);
925 static int hooked_api_set_on_init_cb(
926 struct afb_dynapi *dynapi,
927 int (*oninit)(struct afb_dynapi *dynapi))
930 return api_set_on_init_cb(dynapi, oninit);
933 static void hooked_api_seal_cb(
934 struct afb_dynapi *dynapi)
940 static const struct afb_dynapi_itf dynapi_itf = {
942 .vverbose = (void*)vverbose_cb,
944 .get_event_loop = afb_systemd_get_event_loop,
945 .get_user_bus = afb_systemd_get_user_bus,
946 .get_system_bus = afb_systemd_get_system_bus,
947 .rootdir_get_fd = afb_common_rootdir_get_fd,
948 .rootdir_open_locale = rootdir_open_locale_cb,
949 .queue_job = queue_job_cb,
951 .require_api = require_api_cb,
952 .rename_api = rename_api_cb,
954 .event_broadcast = event_broadcast_cb,
955 .eventid_make = eventid_make_cb,
957 .call = svc_call_dynapi,
958 .call_sync = svc_call_sync,
960 .api_new_api = api_new_api_cb,
961 .api_set_verbs_v2 = api_set_verbs_v2_cb,
962 .api_add_verb = api_add_verb_cb,
963 .api_sub_verb = api_sub_verb_cb,
964 .api_set_on_event = api_set_on_event_cb,
965 .api_set_on_init = api_set_on_init_cb,
966 .api_seal = api_seal_cb,
969 static const struct afb_dynapi_itf hooked_dynapi_itf = {
971 .vverbose = hooked_vverbose_cb,
973 .get_event_loop = hooked_get_event_loop,
974 .get_user_bus = hooked_get_user_bus,
975 .get_system_bus = hooked_get_system_bus,
976 .rootdir_get_fd = hooked_rootdir_get_fd,
977 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
978 .queue_job = hooked_queue_job_cb,
980 .require_api = hooked_require_api_cb,
981 .rename_api = hooked_rename_api_cb,
983 .event_broadcast = hooked_event_broadcast_cb,
984 .eventid_make = hooked_eventid_make_cb,
986 .call = svc_hooked_call_dynapi,
987 .call_sync = svc_hooked_call_sync,
989 .api_new_api = hooked_api_new_api_cb,
990 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
991 .api_add_verb = hooked_api_add_verb_cb,
992 .api_sub_verb = hooked_api_sub_verb_cb,
993 .api_set_on_event = hooked_api_set_on_event_cb,
994 .api_set_on_init = hooked_api_set_on_init_cb,
995 .api_seal = hooked_api_seal_cb,
998 /*************************************************************************************************************
999 *************************************************************************************************************
1000 *************************************************************************************************************
1001 *************************************************************************************************************
1003 *************************************************************************************************************
1004 *************************************************************************************************************
1005 *************************************************************************************************************
1006 *************************************************************************************************************/
1009 * Propagates the event to the service
1011 static void export_on_event_v12(void *closure, const char *event, int eventid, struct json_object *object)
1013 struct afb_export *export = closure;
1015 if (export->hooksvc & afb_hook_flag_svc_on_event_before)
1016 afb_hook_svc_on_event_before(export, event, eventid, object);
1017 export->on_event.v12(event, object);
1018 if (export->hooksvc & afb_hook_flag_svc_on_event_after)
1019 afb_hook_svc_on_event_after(export, event, eventid, object);
1020 json_object_put(object);
1023 /* the interface for events */
1024 static const struct afb_evt_itf evt_v12_itf = {
1025 .broadcast = export_on_event_v12,
1026 .push = export_on_event_v12
1030 * Propagates the event to the service
1032 static void export_on_event_vdyn(void *closure, const char *event, int eventid, struct json_object *object)
1034 struct afb_export *export = closure;
1036 if (export->hooksvc & afb_hook_flag_svc_on_event_before)
1037 afb_hook_svc_on_event_before(export, event, eventid, object);
1038 export->on_event.vdyn(to_dynapi(export), event, object);
1039 if (export->hooksvc & afb_hook_flag_svc_on_event_after)
1040 afb_hook_svc_on_event_after(export, event, eventid, object);
1041 json_object_put(object);
1044 /* the interface for events */
1045 static const struct afb_evt_itf evt_vdyn_itf = {
1046 .broadcast = export_on_event_vdyn,
1047 .push = export_on_event_vdyn
1050 /*************************************************************************************************************
1051 *************************************************************************************************************
1052 *************************************************************************************************************
1053 *************************************************************************************************************
1055 *************************************************************************************************************
1056 *************************************************************************************************************
1057 *************************************************************************************************************
1058 *************************************************************************************************************/
1060 static struct afb_export *create(struct afb_apiset *apiset, const char *apiname, enum afb_api_version version)
1062 struct afb_export *export;
1064 /* session shared with other exports */
1065 if (common_session == NULL) {
1066 common_session = afb_session_create (0);
1067 if (common_session == NULL)
1070 export = calloc(1, sizeof *export);
1074 memset(export, 0, sizeof *export);
1075 export->apiname = strdup(apiname);
1076 export->dynapi.apiname = export->apiname;
1077 export->version = version;
1078 export->state = Api_State_Pre_Init;
1079 export->session = afb_session_addref(common_session);
1080 export->apiset = afb_apiset_addref(apiset);
1085 void afb_export_destroy(struct afb_export *export)
1088 if (export->listener != NULL)
1089 afb_evt_listener_unref(export->listener);
1090 afb_session_unref(export->session);
1091 afb_apiset_unref(export->apiset);
1092 free(export->apiname);
1097 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*))
1099 struct afb_export *export = create(apiset, apiname, Api_Version_1);
1101 export->init.v1 = init;
1102 export->on_event.v12 = onevent;
1103 export->export.v1.mode = AFB_MODE_LOCAL;
1104 export->export.v1.daemon.closure = export;
1105 afb_export_verbosity_set(export, verbosity);
1106 afb_export_update_hook(export);
1111 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*))
1113 struct afb_export *export = create(apiset, apiname, Api_Version_2);
1115 export->init.v2 = init;
1116 export->on_event.v12 = onevent;
1117 export->export.v2 = data;
1118 data->daemon.closure = export;
1119 data->service.closure = export;
1120 afb_export_verbosity_set(export, verbosity);
1121 afb_export_update_hook(export);
1126 struct afb_export *afb_export_create_vdyn(struct afb_apiset *apiset, const char *apiname, struct afb_api_dyn *apidyn)
1128 struct afb_export *export = create(apiset, apiname, Api_Version_Dyn);
1130 export->apidyn = apidyn;
1131 afb_export_verbosity_set(export, verbosity);
1132 afb_export_update_hook(export);
1137 void afb_export_rename(struct afb_export *export, const char *apiname)
1139 free(export->apiname);
1140 export->apiname = strdup(apiname);
1141 export->dynapi.apiname = export->apiname;
1142 afb_export_update_hook(export);
1145 const char *afb_export_apiname(const struct afb_export *export)
1147 return export->apiname;
1150 void afb_export_update_hook(struct afb_export *export)
1152 export->hookditf = afb_hook_flags_ditf(export->apiname);
1153 export->hooksvc = afb_hook_flags_svc(export->apiname);
1154 export->dynapi.itf = export->hookditf|export->hooksvc ? &hooked_dynapi_itf : &dynapi_itf;
1156 switch (export->version) {
1158 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1161 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1162 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1167 struct afb_binding_interface_v1 *afb_export_get_interface_v1(struct afb_export *export)
1169 return export->version == Api_Version_1 ? &export->export.v1 : NULL;
1172 int afb_export_unshare_session(struct afb_export *export)
1174 if (export->session == common_session) {
1175 export->session = afb_session_create (0);
1176 if (export->session)
1177 afb_session_unref(common_session);
1179 export->session = common_session;
1186 void afb_export_set_apiset(struct afb_export *export, struct afb_apiset *apiset)
1188 struct afb_apiset *prvset = export->apiset;
1189 export->apiset = afb_apiset_addref(apiset);
1190 afb_apiset_unref(prvset);
1193 struct afb_apiset *afb_export_get_apiset(struct afb_export *export)
1195 return export->apiset;
1198 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1201 switch (export->version) {
1202 case Api_Version_1: case Api_Version_2: break;
1204 ERROR("invalid version 12 for API %s", export->apiname);
1209 /* set the event handler */
1211 if (export->listener) {
1212 afb_evt_listener_unref(export->listener);
1213 export->listener = NULL;
1215 export->on_event.v12 = on_event;
1217 export->on_event.v12 = on_event;
1218 if (!export->listener) {
1219 export->listener = afb_evt_listener_create(&evt_v12_itf, export);
1220 if (export->listener == NULL)
1227 int afb_export_handle_events_vdyn(struct afb_export *export, void (*on_event)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
1230 switch (export->version) {
1231 case Api_Version_Dyn: break;
1233 ERROR("invalid version Dyn for API %s", export->apiname);
1238 /* set the event handler */
1240 if (export->listener) {
1241 afb_evt_listener_unref(export->listener);
1242 export->listener = NULL;
1244 export->on_event.vdyn = on_event;
1246 export->on_event.vdyn = on_event;
1247 if (!export->listener) {
1248 export->listener = afb_evt_listener_create(&evt_vdyn_itf, export);
1249 if (export->listener == NULL)
1256 int afb_export_handle_init_vdyn(struct afb_export *export, int (*oninit)(struct afb_dynapi *dynapi))
1258 if (export->state != Api_State_Pre_Init) {
1259 ERROR("[API %s] Bad call to 'afb_dynapi_on_init', must be in PreInit", export->apiname);
1264 export->init.vdyn = oninit;
1269 * Starts a new service (v1)
1271 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1273 return regfun(&export->export.v1);
1276 int afb_export_preinit_vdyn(struct afb_export *export, int (*preinit)(void*, struct afb_dynapi*), void *closure)
1278 return preinit(closure, to_dynapi(export));
1281 int afb_export_verbosity_get(const struct afb_export *export)
1283 return export->dynapi.verbosity;
1286 void afb_export_verbosity_set(struct afb_export *export, int level)
1288 export->dynapi.verbosity = level;
1289 switch (export->version) {
1290 case Api_Version_1: export->export.v1.verbosity = level; break;
1291 case Api_Version_2: export->export.v2->verbosity = level; break;
1295 /*************************************************************************************************************
1296 *************************************************************************************************************
1297 *************************************************************************************************************
1298 *************************************************************************************************************
1300 *************************************************************************************************************
1301 *************************************************************************************************************
1302 *************************************************************************************************************
1303 *************************************************************************************************************/
1305 int afb_export_start(struct afb_export *export, int share_session, int onneed, struct afb_apiset *apiset)
1310 if (export->state != Api_State_Pre_Init) {
1311 /* not an error when onneed */
1315 /* already started: it is an error */
1316 ERROR("Service of API %s already started", export->apiname);
1320 /* unshare the session if asked */
1321 if (!share_session) {
1322 rc = afb_export_unshare_session(export);
1324 ERROR("Can't unshare the session for %s", export->apiname);
1329 /* set event handling */
1330 switch (export->version) {
1333 rc = afb_export_handle_events_v12(export, export->on_event.v12);
1340 ERROR("Can't set event handler for %s", export->apiname);
1344 /* Starts the service */
1345 if (export->hooksvc & afb_hook_flag_svc_start_before)
1346 afb_hook_svc_start_before(export);
1347 export->state = Api_State_Init;
1348 switch (export->version) {
1350 rc = export->init.v1 ? export->init.v1((struct afb_service){ .itf = &hooked_service_itf, .closure = export }) : 0;
1353 rc = export->init.v2 ? export->init.v2() : 0;
1355 case Api_Version_Dyn:
1356 rc = export->init.vdyn ? export->init.vdyn(to_dynapi(export)) : 0;
1361 export->state = Api_State_Run;
1362 if (export->hooksvc & afb_hook_flag_svc_start_after)
1363 afb_hook_svc_start_after(export, rc);
1365 /* initialisation error */
1366 ERROR("Initialisation of service API %s failed (%d): %m", export->apiname, rc);