2 * Copyright (C) 2016, 2017, 2018 "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.
26 #include <json-c/json.h>
27 #if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
28 #define JSON_C_TO_STRING_NOSLASHESCAPE 0
31 #define AFB_BINDING_VERSION 0
32 #include <afb/afb-binding.h>
35 #include "afb-apiset.h"
36 #if defined(WITH_LEGACY_BINDING_V1)
37 #include "afb-api-so-v1.h"
39 #include "afb-api-so-v2.h"
40 #include "afb-api-v3.h"
41 #include "afb-common.h"
42 #include "afb-systemd.h"
45 #include "afb-export.h"
47 #include "afb-msg-json.h"
48 #include "afb-session.h"
50 #include "afb-calls.h"
53 #include "sig-monitor.h"
55 /*************************************************************************
57 ************************************************************************/
60 * structure for handling events
64 /* link to the next event handler of the list */
65 struct event_handler *next;
67 /* function to call on the case of the event */
68 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
70 /* closure for the callback */
73 /* the handled pattern */
78 * Actually supported versions
83 #if defined(WITH_LEGACY_BINDING_V1)
91 * The states of exported APIs
101 * structure of the exported API
106 struct afb_api_x3 api;
108 /* reference count */
111 /* version of the api */
118 unsigned declared: 1;
121 unsigned unsealed: 1;
127 /* session for service */
128 struct afb_session *session;
130 /* apiset the API is declared in */
131 struct afb_apiset *declare_set;
133 /* apiset for calls */
134 struct afb_apiset *call_set;
136 /* event listener for service or NULL */
137 struct afb_evt_listener *listener;
139 /* event handler list */
140 struct event_handler *event_handlers;
142 /* internal descriptors */
144 #if defined(WITH_LEGACY_BINDING_V1)
145 struct afb_binding_v1 *v1;
147 const struct afb_binding_v2 *v2;
148 struct afb_api_v3 *v3;
153 #if defined(WITH_LEGACY_BINDING_V1)
154 int (*v1)(struct afb_service_x1);
157 int (*v3)(struct afb_api_x3 *api);
161 void (*on_any_event_v12)(const char *event, struct json_object *object);
162 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
166 #if defined(WITH_LEGACY_BINDING_V1)
167 struct afb_binding_interface_v1 v1;
169 struct afb_binding_data_v2 *v2;
176 /*****************************************************************************/
178 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
180 return (struct afb_api_x3*)export;
183 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
185 return (struct afb_export*)api;
188 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
190 return from_api_x3(api);
193 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
195 return to_api_x3(export);
198 /******************************************************************************
199 ******************************************************************************
200 ******************************************************************************
201 ******************************************************************************
203 ******************************************************************************
204 ******************************************************************************
205 ******************************************************************************
206 ******************************************************************************/
208 /**********************************************
210 **********************************************/
211 static void vverbose_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
214 struct afb_export *export = from_api_x3(closure);
216 if (!fmt || vasprintf(&p, fmt, args) < 0)
217 vverbose(level, file, line, function, fmt, args);
219 verbose(level, file, line, function, "[API %s] %s", export->api.apiname, p);
224 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
226 vverbose_cb(closure, level, file, line, NULL, fmt, args);
229 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
231 struct afb_export *export = from_api_x3(closure);
233 /* check daemon state */
234 if (export->state == Api_State_Pre_Init) {
235 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
240 /* create the event */
241 return afb_evt_event_x2_create2(export->api.apiname, name);
244 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
246 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
247 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
250 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
254 struct afb_export *export = from_api_x3(closure);
256 /* check daemon state */
257 if (export->state == Api_State_Pre_Init) {
258 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
259 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
264 /* makes the event name */
265 plen = strlen(export->api.apiname);
267 event = alloca(nlen + plen + 2);
268 memcpy(event, export->api.apiname, plen);
270 memcpy(event + plen + 1, name, nlen + 1);
272 /* broadcast the event */
273 return afb_evt_broadcast(event, object);
276 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
278 return afb_common_rootdir_open_locale(filename, flags, locale);
281 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
283 return jobs_queue(group, timeout, callback, argument);
286 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
288 return afb_xreq_unstore(sreq);
291 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
293 struct afb_export *export = from_api_x3(closure);
295 char *iter, *end, save;
297 /* scan the names in a local copy */
299 iter = strdupa(name);
305 if (!save) /* at end? */
308 /* search for the end */
310 while (save && !isspace(save))
314 /* check the required api */
315 if (export->state == Api_State_Pre_Init)
316 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
318 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
327 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
329 struct afb_export *export = from_api_x3(closure);
330 if (!afb_api_is_valid_name(aliasname)) {
331 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
335 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
336 afb_export_add_alias(export, apiname, aliasname);
340 static struct afb_api_x3 *api_new_api_cb(
341 struct afb_api_x3 *closure,
345 int (*preinit)(void*, struct afb_api_x3 *),
346 void *preinit_closure)
348 struct afb_export *export = from_api_x3(closure);
349 struct afb_api_v3 *apiv3 = afb_api_v3_create(export->declare_set, export->call_set, api, info, noconcurrency, preinit, preinit_closure, 1);
350 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
353 /**********************************************
355 **********************************************/
356 static void hooked_vverbose_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
358 struct afb_export *export = from_api_x3(closure);
361 vverbose_cb(closure, level, file, line, function, fmt, args);
362 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
366 static void legacy_hooked_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
368 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
371 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
373 struct afb_export *export = from_api_x3(closure);
374 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
375 afb_hook_api_event_make(export, name, r);
379 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
381 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
382 struct afb_event_x1 e;
384 e.itf = event ? event->itf : NULL;
388 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
391 struct afb_export *export = from_api_x3(closure);
392 json_object_get(object);
393 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
394 r = event_broadcast_cb(closure, name, object);
395 afb_hook_api_event_broadcast_after(export, name, object, r);
396 json_object_put(object);
400 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
402 struct afb_export *export = from_api_x3(closure);
403 struct sd_event *r = afb_systemd_get_event_loop();
404 return afb_hook_api_get_event_loop(export, r);
407 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
409 struct afb_export *export = from_api_x3(closure);
410 struct sd_bus *r = afb_systemd_get_user_bus();
411 return afb_hook_api_get_user_bus(export, r);
414 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
416 struct afb_export *export = from_api_x3(closure);
417 struct sd_bus *r = afb_systemd_get_system_bus();
418 return afb_hook_api_get_system_bus(export, r);
421 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
423 struct afb_export *export = from_api_x3(closure);
424 int r = afb_common_rootdir_get_fd();
425 return afb_hook_api_rootdir_get_fd(export, r);
428 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
430 struct afb_export *export = from_api_x3(closure);
431 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
432 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
435 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
437 struct afb_export *export = from_api_x3(closure);
438 int r = queue_job_cb(closure, callback, argument, group, timeout);
439 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
442 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
444 struct afb_export *export = from_api_x3(closure);
445 afb_hook_api_legacy_unstore_req(export, sreq);
446 return legacy_unstore_req_cb(closure, sreq);
449 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
452 struct afb_export *export = from_api_x3(closure);
453 afb_hook_api_require_api(export, name, initialized);
454 result = require_api_cb(closure, name, initialized);
455 return afb_hook_api_require_api_result(export, name, initialized, result);
458 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
460 struct afb_export *export = from_api_x3(closure);
461 int result = add_alias_cb(closure, apiname, aliasname);
462 return afb_hook_api_add_alias(export, apiname, aliasname, result);
465 static struct afb_api_x3 *hooked_api_new_api_cb(
466 struct afb_api_x3 *closure,
470 int (*preinit)(void*, struct afb_api_x3 *),
471 void *preinit_closure)
473 struct afb_api_x3 *result;
474 struct afb_export *export = from_api_x3(closure);
475 afb_hook_api_new_api_before(export, api, info, noconcurrency);
476 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
477 afb_hook_api_new_api_after(export, -!result, api);
481 /**********************************************
483 **********************************************/
484 static const struct afb_daemon_itf_x1 daemon_itf = {
485 .vverbose_v1 = legacy_vverbose_v1_cb,
486 .vverbose_v2 = vverbose_cb,
487 .event_make = legacy_event_x1_make_cb,
488 .event_broadcast = event_broadcast_cb,
489 .get_event_loop = afb_systemd_get_event_loop,
490 .get_user_bus = afb_systemd_get_user_bus,
491 .get_system_bus = afb_systemd_get_system_bus,
492 .rootdir_get_fd = afb_common_rootdir_get_fd,
493 .rootdir_open_locale = rootdir_open_locale_cb,
494 .queue_job = queue_job_cb,
495 .unstore_req = legacy_unstore_req_cb,
496 .require_api = require_api_cb,
497 .add_alias = add_alias_cb,
498 .new_api = api_new_api_cb,
501 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
502 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
503 .vverbose_v2 = hooked_vverbose_cb,
504 .event_make = legacy_hooked_event_x1_make_cb,
505 .event_broadcast = hooked_event_broadcast_cb,
506 .get_event_loop = hooked_get_event_loop,
507 .get_user_bus = hooked_get_user_bus,
508 .get_system_bus = hooked_get_system_bus,
509 .rootdir_get_fd = hooked_rootdir_get_fd,
510 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
511 .queue_job = hooked_queue_job_cb,
512 .unstore_req = legacy_hooked_unstore_req_cb,
513 .require_api = hooked_require_api_cb,
514 .add_alias = hooked_add_alias_cb,
515 .new_api = hooked_api_new_api_cb,
518 /******************************************************************************
519 ******************************************************************************
520 ******************************************************************************
521 ******************************************************************************
523 ******************************************************************************
524 ******************************************************************************
525 ******************************************************************************
526 ******************************************************************************/
528 /* the common session for services sharing their session */
529 static struct afb_session *common_session;
531 /******************************************************************************
532 ******************************************************************************
533 ******************************************************************************
534 ******************************************************************************
536 ******************************************************************************
537 ******************************************************************************
538 ******************************************************************************
539 ******************************************************************************/
542 struct afb_api_x3 *apix3,
545 struct json_object *args,
546 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
549 struct afb_export *export = from_api_x3(apix3);
550 return afb_calls_call(export, api, verb, args, callback, closure);
553 static int call_sync_x3(
554 struct afb_api_x3 *apix3,
557 struct json_object *args,
558 struct json_object **object,
562 struct afb_export *export = from_api_x3(apix3);
563 return afb_calls_call_sync(export, api, verb, args, object, error, info);
566 static void legacy_call_v12(
567 struct afb_api_x3 *apix3,
570 struct json_object *args,
571 void (*callback)(void*, int, struct json_object*),
574 struct afb_export *export = from_api_x3(apix3);
575 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
578 static void legacy_call_x3(
579 struct afb_api_x3 *apix3,
582 struct json_object *args,
583 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
586 struct afb_export *export = from_api_x3(apix3);
587 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
590 static int legacy_call_sync(
591 struct afb_api_x3 *apix3,
594 struct json_object *args,
595 struct json_object **result)
597 struct afb_export *export = from_api_x3(apix3);
598 return afb_calls_legacy_call_sync(export, api, verb, args, result);
601 static void hooked_call_x3(
602 struct afb_api_x3 *apix3,
605 struct json_object *args,
606 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
609 struct afb_export *export = from_api_x3(apix3);
610 afb_calls_hooked_call(export, api, verb, args, callback, closure);
613 static int hooked_call_sync_x3(
614 struct afb_api_x3 *apix3,
617 struct json_object *args,
618 struct json_object **object,
622 struct afb_export *export = from_api_x3(apix3);
623 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
626 static void legacy_hooked_call_v12(
627 struct afb_api_x3 *apix3,
630 struct json_object *args,
631 void (*callback)(void*, int, struct json_object*),
634 struct afb_export *export = from_api_x3(apix3);
635 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
638 static void legacy_hooked_call_x3(
639 struct afb_api_x3 *apix3,
642 struct json_object *args,
643 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
646 struct afb_export *export = from_api_x3(apix3);
647 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
650 static int legacy_hooked_call_sync(
651 struct afb_api_x3 *apix3,
654 struct json_object *args,
655 struct json_object **result)
657 struct afb_export *export = from_api_x3(apix3);
658 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
661 /* the interface for services */
662 static const struct afb_service_itf_x1 service_itf = {
663 .call = legacy_call_v12,
664 .call_sync = legacy_call_sync
667 /* the interface for services */
668 static const struct afb_service_itf_x1 hooked_service_itf = {
669 .call = legacy_hooked_call_v12,
670 .call_sync = legacy_hooked_call_sync
673 /******************************************************************************
674 ******************************************************************************
675 ******************************************************************************
676 ******************************************************************************
678 ******************************************************************************
679 ******************************************************************************
680 ******************************************************************************
681 ******************************************************************************/
683 static int api_set_verbs_v2_cb(
684 struct afb_api_x3 *api,
685 const struct afb_verb_v2 *verbs)
687 struct afb_export *export = from_api_x3(api);
689 if (export->unsealed) {
690 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
698 static int api_set_verbs_v3_cb(
699 struct afb_api_x3 *api,
700 const struct afb_verb_v3 *verbs)
702 struct afb_export *export = from_api_x3(api);
704 if (!export->unsealed) {
709 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
713 static int api_add_verb_cb(
714 struct afb_api_x3 *api,
717 void (*callback)(struct afb_req_x2 *req),
719 const struct afb_auth *auth,
723 struct afb_export *export = from_api_x3(api);
725 if (!export->unsealed) {
730 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
733 static int api_del_verb_cb(
734 struct afb_api_x3 *api,
738 struct afb_export *export = from_api_x3(api);
740 if (!export->unsealed) {
745 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
748 static int api_set_on_event_cb(
749 struct afb_api_x3 *api,
750 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
752 struct afb_export *export = from_api_x3(api);
753 return afb_export_handle_events_v3(export, onevent);
756 static int api_set_on_init_cb(
757 struct afb_api_x3 *api,
758 int (*oninit)(struct afb_api_x3 *api))
760 struct afb_export *export = from_api_x3(api);
762 return afb_export_handle_init_v3(export, oninit);
765 static void api_seal_cb(
766 struct afb_api_x3 *api)
768 struct afb_export *export = from_api_x3(api);
770 export->unsealed = 0;
773 static int event_handler_add_cb(
774 struct afb_api_x3 *api,
776 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
779 struct afb_export *export = from_api_x3(api);
781 return afb_export_event_handler_add(export, pattern, callback, closure);
784 static int event_handler_del_cb(
785 struct afb_api_x3 *api,
789 struct afb_export *export = from_api_x3(api);
791 return afb_export_event_handler_del(export, pattern, closure);
794 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
796 struct afb_export *export = from_api_x3(api);
799 char *iter, *end, save;
801 iter = strdupa(name);
807 if (!save) /* at end? */
810 /* search for the end */
812 while (save && !isspace(save))
816 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
825 static int class_require_cb(struct afb_api_x3 *api, const char *name)
827 struct afb_export *export = from_api_x3(api);
830 char *iter, *end, save;
832 iter = strdupa(name);
838 if (!save) /* at end? */
841 /* search for the end */
843 while (save && !isspace(save))
847 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
856 static int delete_api_cb(struct afb_api_x3 *api)
858 struct afb_export *export = from_api_x3(api);
860 if (!export->unsealed) {
865 afb_export_undeclare(export);
866 afb_export_unref(export);
870 static int hooked_api_set_verbs_v2_cb(
871 struct afb_api_x3 *api,
872 const struct afb_verb_v2 *verbs)
874 struct afb_export *export = from_api_x3(api);
875 int result = api_set_verbs_v2_cb(api, verbs);
876 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
879 static int hooked_api_set_verbs_v3_cb(
880 struct afb_api_x3 *api,
881 const struct afb_verb_v3 *verbs)
883 struct afb_export *export = from_api_x3(api);
884 int result = api_set_verbs_v3_cb(api, verbs);
885 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
888 static int hooked_api_add_verb_cb(
889 struct afb_api_x3 *api,
892 void (*callback)(struct afb_req_x2 *req),
894 const struct afb_auth *auth,
898 struct afb_export *export = from_api_x3(api);
899 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
900 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
903 static int hooked_api_del_verb_cb(
904 struct afb_api_x3 *api,
908 struct afb_export *export = from_api_x3(api);
909 int result = api_del_verb_cb(api, verb, vcbdata);
910 return afb_hook_api_api_del_verb(export, result, verb);
913 static int hooked_api_set_on_event_cb(
914 struct afb_api_x3 *api,
915 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
917 struct afb_export *export = from_api_x3(api);
918 int result = api_set_on_event_cb(api, onevent);
919 return afb_hook_api_api_set_on_event(export, result);
922 static int hooked_api_set_on_init_cb(
923 struct afb_api_x3 *api,
924 int (*oninit)(struct afb_api_x3 *api))
926 struct afb_export *export = from_api_x3(api);
927 int result = api_set_on_init_cb(api, oninit);
928 return afb_hook_api_api_set_on_init(export, result);
931 static void hooked_api_seal_cb(
932 struct afb_api_x3 *api)
934 struct afb_export *export = from_api_x3(api);
935 afb_hook_api_api_seal(export);
939 static int hooked_event_handler_add_cb(
940 struct afb_api_x3 *api,
942 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
945 struct afb_export *export = from_api_x3(api);
946 int result = event_handler_add_cb(api, pattern, callback, closure);
947 return afb_hook_api_event_handler_add(export, result, pattern);
950 static int hooked_event_handler_del_cb(
951 struct afb_api_x3 *api,
955 struct afb_export *export = from_api_x3(api);
956 int result = event_handler_del_cb(api, pattern, closure);
957 return afb_hook_api_event_handler_del(export, result, pattern);
960 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
962 struct afb_export *export = from_api_x3(api);
963 int result = class_provide_cb(api, name);
964 return afb_hook_api_class_provide(export, result, name);
967 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
969 struct afb_export *export = from_api_x3(api);
970 int result = class_require_cb(api, name);
971 return afb_hook_api_class_require(export, result, name);
974 static int hooked_delete_api_cb(struct afb_api_x3 *api)
976 struct afb_export *export = afb_export_addref(from_api_x3(api));
977 int result = delete_api_cb(api);
978 result = afb_hook_api_delete_api(export, result);
979 afb_export_unref(export);
983 static const struct afb_api_x3_itf api_x3_itf = {
985 .vverbose = (void*)vverbose_cb,
987 .get_event_loop = afb_systemd_get_event_loop,
988 .get_user_bus = afb_systemd_get_user_bus,
989 .get_system_bus = afb_systemd_get_system_bus,
990 .rootdir_get_fd = afb_common_rootdir_get_fd,
991 .rootdir_open_locale = rootdir_open_locale_cb,
992 .queue_job = queue_job_cb,
994 .require_api = require_api_cb,
995 .add_alias = add_alias_cb,
997 .event_broadcast = event_broadcast_cb,
998 .event_make = event_x2_make_cb,
1000 .legacy_call = legacy_call_x3,
1001 .legacy_call_sync = legacy_call_sync,
1003 .api_new_api = api_new_api_cb,
1004 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1005 .api_add_verb = api_add_verb_cb,
1006 .api_del_verb = api_del_verb_cb,
1007 .api_set_on_event = api_set_on_event_cb,
1008 .api_set_on_init = api_set_on_init_cb,
1009 .api_seal = api_seal_cb,
1010 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1011 .event_handler_add = event_handler_add_cb,
1012 .event_handler_del = event_handler_del_cb,
1015 .call_sync = call_sync_x3,
1017 .class_provide = class_provide_cb,
1018 .class_require = class_require_cb,
1020 .delete_api = delete_api_cb,
1023 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1025 .vverbose = hooked_vverbose_cb,
1027 .get_event_loop = hooked_get_event_loop,
1028 .get_user_bus = hooked_get_user_bus,
1029 .get_system_bus = hooked_get_system_bus,
1030 .rootdir_get_fd = hooked_rootdir_get_fd,
1031 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1032 .queue_job = hooked_queue_job_cb,
1034 .require_api = hooked_require_api_cb,
1035 .add_alias = hooked_add_alias_cb,
1037 .event_broadcast = hooked_event_broadcast_cb,
1038 .event_make = hooked_event_x2_make_cb,
1040 .legacy_call = legacy_hooked_call_x3,
1041 .legacy_call_sync = legacy_hooked_call_sync,
1043 .api_new_api = hooked_api_new_api_cb,
1044 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1045 .api_add_verb = hooked_api_add_verb_cb,
1046 .api_del_verb = hooked_api_del_verb_cb,
1047 .api_set_on_event = hooked_api_set_on_event_cb,
1048 .api_set_on_init = hooked_api_set_on_init_cb,
1049 .api_seal = hooked_api_seal_cb,
1050 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1051 .event_handler_add = hooked_event_handler_add_cb,
1052 .event_handler_del = hooked_event_handler_del_cb,
1054 .call = hooked_call_x3,
1055 .call_sync = hooked_call_sync_x3,
1057 .class_provide = hooked_class_provide_cb,
1058 .class_require = hooked_class_require_cb,
1060 .delete_api = hooked_delete_api_cb,
1063 /******************************************************************************
1064 ******************************************************************************
1065 ******************************************************************************
1066 ******************************************************************************
1068 ******************************************************************************
1069 ******************************************************************************
1070 ******************************************************************************
1071 ******************************************************************************/
1074 * Propagates the event to the service
1076 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1078 struct event_handler *handler;
1079 struct afb_export *export = from_api_x3(closure);
1081 /* hook the event before */
1082 if (export->hooksvc & afb_hook_flag_api_on_event)
1083 afb_hook_api_on_event_before(export, event, eventid, object);
1085 /* transmit to specific handlers */
1086 /* search the handler */
1087 handler = export->event_handlers;
1089 if (fnmatch(handler->pattern, event, 0)) {
1090 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1091 handler->callback(handler->closure, event, object, to_api_x3(export));
1093 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1094 handler->callback(handler->closure, event, object, to_api_x3(export));
1095 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1098 handler = handler->next;
1101 /* transmit to default handler */
1102 if (export->on_any_event_v3)
1103 export->on_any_event_v3(to_api_x3(export), event, object);
1104 else if (export->on_any_event_v12)
1105 export->on_any_event_v12(event, object);
1107 /* hook the event after */
1108 if (export->hooksvc & afb_hook_flag_api_on_event)
1109 afb_hook_api_on_event_after(export, event, eventid, object);
1110 json_object_put(object);
1113 /* the interface for events */
1114 static const struct afb_evt_itf evt_itf = {
1115 .broadcast = listener_of_events,
1116 .push = listener_of_events
1119 /* ensure an existing listener */
1120 static int ensure_listener(struct afb_export *export)
1122 if (!export->listener) {
1123 export->listener = afb_evt_listener_create(&evt_itf, export);
1124 if (export->listener == NULL)
1130 int afb_export_event_handler_add(
1131 struct afb_export *export,
1132 const char *pattern,
1133 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1137 struct event_handler *handler, **previous;
1139 rc = ensure_listener(export);
1143 /* search the handler */
1144 previous = &export->event_handlers;
1145 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1146 previous = &handler->next;
1148 /* error if found */
1150 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1155 /* create the event */
1156 handler = malloc(strlen(pattern) + sizeof * handler);
1158 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1163 /* init and record */
1164 handler->next = NULL;
1165 handler->callback = callback;
1166 handler->closure = closure;
1167 strcpy(handler->pattern, pattern);
1168 *previous = handler;
1173 int afb_export_event_handler_del(
1174 struct afb_export *export,
1175 const char *pattern,
1178 struct event_handler *handler, **previous;
1180 /* search the handler */
1181 previous = &export->event_handlers;
1182 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1183 previous = &handler->next;
1185 /* error if found */
1187 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1192 /* remove the found event */
1194 *closure = handler->closure;
1196 *previous = handler->next;
1201 /******************************************************************************
1202 ******************************************************************************
1203 ******************************************************************************
1204 ******************************************************************************
1206 ******************************************************************************
1207 ******************************************************************************
1208 ******************************************************************************
1209 ******************************************************************************/
1211 static struct afb_export *create(
1212 struct afb_apiset *declare_set,
1213 struct afb_apiset *call_set,
1214 const char *apiname,
1215 enum afb_api_version version)
1217 struct afb_export *export;
1219 /* session shared with other exports */
1220 if (common_session == NULL) {
1221 common_session = afb_session_create (0);
1222 if (common_session == NULL)
1225 export = calloc(1, sizeof *export + strlen(apiname));
1229 export->refcount = 1;
1230 strcpy(export->name, apiname);
1231 export->api.apiname = export->name;
1232 export->version = version;
1233 export->state = Api_State_Pre_Init;
1234 export->session = afb_session_addref(common_session);
1235 export->declare_set = afb_apiset_addref(declare_set);
1236 export->call_set = afb_apiset_addref(call_set);
1241 struct afb_export *afb_export_addref(struct afb_export *export)
1244 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1248 void afb_export_unref(struct afb_export *export)
1250 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1251 afb_export_destroy(export);
1254 void afb_export_destroy(struct afb_export *export)
1256 struct event_handler *handler;
1259 while ((handler = export->event_handlers)) {
1260 export->event_handlers = handler->next;
1263 if (export->listener != NULL)
1264 afb_evt_listener_unref(export->listener);
1265 afb_session_unref(export->session);
1266 afb_apiset_unref(export->declare_set);
1267 afb_apiset_unref(export->call_set);
1268 if (export->api.apiname != export->name)
1269 free((void*)export->api.apiname);
1274 struct afb_export *afb_export_create_none_for_path(
1275 struct afb_apiset *declare_set,
1276 struct afb_apiset *call_set,
1278 int (*creator)(void*, struct afb_api_x3*),
1281 struct afb_export *export = create(declare_set, call_set, path, Api_Version_None);
1283 afb_export_logmask_set(export, logmask);
1284 afb_export_update_hooks(export);
1285 if (creator && creator(closure, to_api_x3(export)) < 0) {
1286 afb_export_unref(export);
1293 #if defined(WITH_LEGACY_BINDING_V1)
1294 struct afb_export *afb_export_create_v1(
1295 struct afb_apiset *declare_set,
1296 struct afb_apiset *call_set,
1297 const char *apiname,
1298 int (*init)(struct afb_service_x1),
1299 void (*onevent)(const char*, struct json_object*))
1301 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_1);
1303 export->init.v1 = init;
1304 export->on_any_event_v12 = onevent;
1305 export->export.v1.mode = AFB_MODE_LOCAL;
1306 export->export.v1.daemon.closure = to_api_x3(export);
1307 afb_export_logmask_set(export, logmask);
1308 afb_export_update_hooks(export);
1314 struct afb_export *afb_export_create_v2(
1315 struct afb_apiset *declare_set,
1316 struct afb_apiset *call_set,
1317 const char *apiname,
1318 const struct afb_binding_v2 *binding,
1319 struct afb_binding_data_v2 *data,
1321 void (*onevent)(const char*, struct json_object*))
1323 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_2);
1325 export->init.v2 = init;
1326 export->on_any_event_v12 = onevent;
1327 export->desc.v2 = binding;
1328 export->export.v2 = data;
1329 data->daemon.closure = to_api_x3(export);
1330 data->service.closure = to_api_x3(export);
1331 afb_export_logmask_set(export, logmask);
1332 afb_export_update_hooks(export);
1337 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1338 struct afb_apiset *call_set,
1339 const char *apiname,
1340 struct afb_api_v3 *apiv3)
1342 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_3);
1344 export->unsealed = 1;
1345 export->desc.v3 = apiv3;
1346 afb_export_logmask_set(export, logmask);
1347 afb_export_update_hooks(export);
1352 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1354 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1357 int afb_export_rename(struct afb_export *export, const char *apiname)
1361 if (export->declared) {
1366 /* copy the name locally */
1367 name = strdup(apiname);
1373 if (export->api.apiname != export->name)
1374 free((void*)export->api.apiname);
1375 export->api.apiname = name;
1377 afb_export_update_hooks(export);
1381 const char *afb_export_apiname(const struct afb_export *export)
1383 return export->api.apiname;
1386 void afb_export_update_hooks(struct afb_export *export)
1388 export->hookditf = afb_hook_flags_api(export->api.apiname);
1389 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1390 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1392 switch (export->version) {
1393 #if defined(WITH_LEGACY_BINDING_V1)
1395 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1399 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1400 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1405 int afb_export_unshare_session(struct afb_export *export)
1407 if (export->session == common_session) {
1408 export->session = afb_session_create (0);
1409 if (export->session)
1410 afb_session_unref(common_session);
1412 export->session = common_session;
1419 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1422 switch (export->version) {
1423 #if defined(WITH_LEGACY_BINDING_V1)
1429 ERROR("invalid version 12 for API %s", export->api.apiname);
1434 export->on_any_event_v12 = on_event;
1435 return ensure_listener(export);
1438 int afb_export_handle_events_v3(struct afb_export *export, void (*on_event)(struct afb_api_x3 *api, const char *event, struct json_object *object))
1441 switch (export->version) {
1442 case Api_Version_3: break;
1444 ERROR("invalid version Dyn for API %s", export->api.apiname);
1449 export->on_any_event_v3 = on_event;
1450 return ensure_listener(export);
1453 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1455 if (export->state != Api_State_Pre_Init) {
1456 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1461 export->init.v3 = oninit;
1465 #if defined(WITH_LEGACY_BINDING_V1)
1467 * Starts a new service (v1)
1469 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1471 return export->desc.v1 = regfun(&export->export.v1);
1475 int afb_export_preinit_x3(
1476 struct afb_export *export,
1477 int (*preinit)(void*, struct afb_api_x3*),
1480 return preinit(closure, to_api_x3(export));
1483 int afb_export_logmask_get(const struct afb_export *export)
1485 return export->api.logmask;
1488 void afb_export_logmask_set(struct afb_export *export, int mask)
1490 export->api.logmask = mask;
1491 switch (export->version) {
1492 #if defined(WITH_LEGACY_BINDING_V1)
1493 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1495 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1499 void *afb_export_userdata_get(const struct afb_export *export)
1501 return export->api.userdata;
1504 void afb_export_userdata_set(struct afb_export *export, void *data)
1506 export->api.userdata = data;
1509 /******************************************************************************
1510 ******************************************************************************
1511 ******************************************************************************
1512 ******************************************************************************
1514 ******************************************************************************
1515 ******************************************************************************
1516 ******************************************************************************
1517 ******************************************************************************/
1522 struct afb_export *export;
1525 static void do_init(int sig, void *closure)
1528 struct init *init = closure;
1529 struct afb_export *export;
1534 export = init->export;
1535 switch (export->version) {
1536 #if defined(WITH_LEGACY_BINDING_V1)
1538 rc = export->init.v1 ? export->init.v1(
1539 (struct afb_service_x1){
1540 .itf = &hooked_service_itf,
1541 .closure = to_api_x3(export) }) : 0;
1545 rc = export->init.v2 ? export->init.v2() : 0;
1548 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1555 init->return_code = rc;
1559 int afb_export_start(struct afb_export *export)
1565 switch (export->state) {
1569 case Api_State_Init:
1570 /* starting in progress: it is an error */
1571 ERROR("Service of API %s required started while starting", export->api.apiname);
1578 /* set event handling */
1579 switch (export->version) {
1580 #if defined(WITH_LEGACY_BINDING_V1)
1584 if (export->on_any_event_v12) {
1585 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1594 ERROR("Can't set event handler for %s", export->api.apiname);
1598 /* Starts the service */
1599 if (export->hooksvc & afb_hook_flag_api_start)
1600 afb_hook_api_start_before(export);
1602 export->state = Api_State_Init;
1603 init.export = export;
1604 sig_monitor(0, do_init, &init);
1605 rc = init.return_code;
1606 export->state = Api_State_Run;
1608 if (export->hooksvc & afb_hook_flag_api_start)
1609 afb_hook_api_start_after(export, rc);
1612 /* initialisation error */
1613 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1620 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1622 struct afb_export *export = closure;
1624 xreq->request.api = to_api_x3(export);
1626 switch (export->version) {
1627 #if defined(WITH_LEGACY_BINDING_V1)
1629 afb_api_so_v1_process_call(export->desc.v1, xreq);
1633 afb_api_so_v2_process_call(export->desc.v2, xreq);
1636 afb_api_v3_process_call(export->desc.v3, xreq);
1639 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1644 static struct json_object *api_describe_cb(void *closure)
1646 struct afb_export *export = closure;
1647 struct json_object *result;
1649 switch (export->version) {
1650 #if defined(WITH_LEGACY_BINDING_V1)
1652 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1656 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1659 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1668 static int api_service_start_cb(void *closure)
1670 struct afb_export *export = closure;
1672 return afb_export_start(export);
1675 static void api_update_hooks_cb(void *closure)
1677 struct afb_export *export = closure;
1679 afb_export_update_hooks(export);
1682 static int api_get_logmask_cb(void *closure)
1684 struct afb_export *export = closure;
1686 return afb_export_logmask_get(export);
1689 static void api_set_logmask_cb(void *closure, int level)
1691 struct afb_export *export = closure;
1693 afb_export_logmask_set(export, level);
1696 static void api_unref_cb(void *closure)
1698 struct afb_export *export = closure;
1700 afb_export_unref(export);
1703 static struct afb_api_itf export_api_itf =
1705 .call = api_call_cb,
1706 .service_start = api_service_start_cb,
1707 .update_hooks = api_update_hooks_cb,
1708 .get_logmask = api_get_logmask_cb,
1709 .set_logmask = api_set_logmask_cb,
1710 .describe = api_describe_cb,
1711 .unref = api_unref_cb
1714 int afb_export_declare(struct afb_export *export,
1718 struct afb_api_item afb_api;
1720 if (export->declared)
1723 /* init the record structure */
1724 afb_api.closure = afb_export_addref(export);
1725 afb_api.itf = &export_api_itf;
1726 afb_api.group = noconcurrency ? export : NULL;
1728 /* records the binding */
1729 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1731 export->declared = 1;
1733 ERROR("can't declare export %s to set %s, ABORTING it!",
1734 export->api.apiname,
1735 afb_apiset_name(export->declare_set));
1736 afb_export_addref(export);
1743 void afb_export_undeclare(struct afb_export *export)
1745 if (export->declared) {
1746 export->declared = 0;
1747 afb_apiset_del(export->declare_set, export->api.apiname);
1751 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1753 return afb_evt_event_x2_add_watch(export->listener, event);
1756 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1758 return afb_evt_event_x2_remove_watch(export->listener, event);
1761 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1763 afb_xreq_process(xreq, export->call_set);
1766 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1768 afb_context_init(context, export->session, NULL);