2 * Copyright (C) 2016-2019 "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"
44 #include "afb-export.h"
46 #include "afb-msg-json.h"
47 #include "afb-session.h"
49 #include "afb-calls.h"
55 #include "sig-monitor.h"
56 #include "wrap-json.h"
58 /*************************************************************************
60 ************************************************************************/
63 * Actually supported versions
68 #if defined(WITH_LEGACY_BINDING_V1)
76 * The states of exported APIs
86 * structure of the exported API
91 struct afb_api_x3 api;
96 /* version of the api */
103 unsigned declared: 1;
106 unsigned unsealed: 1;
112 /* session for service */
113 struct afb_session *session;
115 /* apiset the API is declared in */
116 struct afb_apiset *declare_set;
118 /* apiset for calls */
119 struct afb_apiset *call_set;
121 /* event listener for service or NULL */
122 struct afb_evt_listener *listener;
124 /* event handler list */
125 struct globset *event_handlers;
128 struct afb_export *creator;
130 /* path indication if any */
134 struct json_object *settings;
136 /* internal descriptors */
138 #if defined(WITH_LEGACY_BINDING_V1)
139 struct afb_binding_v1 *v1;
141 const struct afb_binding_v2 *v2;
142 struct afb_api_v3 *v3;
147 #if defined(WITH_LEGACY_BINDING_V1)
148 int (*v1)(struct afb_service_x1);
151 int (*v3)(struct afb_api_x3 *api);
155 void (*on_any_event_v12)(const char *event, struct json_object *object);
156 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
160 #if defined(WITH_LEGACY_BINDING_V1)
161 struct afb_binding_interface_v1 v1;
163 struct afb_binding_data_v2 *v2;
170 /*****************************************************************************/
172 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
174 return (struct afb_api_x3*)export;
177 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
179 return (struct afb_export*)api;
182 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
184 return from_api_x3(api);
187 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
189 return to_api_x3(export);
192 /******************************************************************************
193 ******************************************************************************
194 ******************************************************************************
195 ******************************************************************************
197 ******************************************************************************
198 ******************************************************************************
199 ******************************************************************************
200 ******************************************************************************/
202 static struct json_object *configuration;
204 void afb_export_set_config(struct json_object *config)
206 struct json_object *save = configuration;
207 configuration = json_object_get(config);
208 json_object_put(save);
211 static struct json_object *make_settings(struct afb_export *export)
213 struct json_object *result;
214 struct json_object *obj;
215 struct afb_export *iter;
218 /* clone the globals */
219 if (json_object_object_get_ex(configuration, "*", &obj))
220 result = wrap_json_clone(obj);
222 result = json_object_new_object();
225 if (json_object_object_get_ex(configuration, export->name, &obj))
226 wrap_json_object_add(result, obj);
228 /* add library path */
229 for (iter = export ; iter && !iter->path ; iter = iter->creator);
231 path = realpath(iter->path, NULL);
232 json_object_object_add(result, "binding-path", json_object_new_string(path));
236 export->settings = result;
240 /******************************************************************************
241 ******************************************************************************
242 ******************************************************************************
243 ******************************************************************************
245 ******************************************************************************
246 ******************************************************************************
247 ******************************************************************************
248 ******************************************************************************/
250 /**********************************************
252 **********************************************/
253 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)
256 struct afb_export *export = from_api_x3(closure);
258 if (!fmt || vasprintf(&p, fmt, args) < 0)
259 vverbose(level, file, line, function, fmt, args);
261 verbose(level, file, line, function, (verbose_is_colorized() == 0 ? "[API %s] %s" : COLOR_API "[API %s]" COLOR_DEFAULT " %s"), export->api.apiname, p);
266 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
268 vverbose_cb(closure, level, file, line, NULL, fmt, args);
271 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
273 struct afb_export *export = from_api_x3(closure);
275 /* check daemon state */
276 if (export->state == Api_State_Pre_Init) {
277 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
282 /* create the event */
283 return afb_evt_event_x2_create2(export->api.apiname, name);
286 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
288 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
289 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
292 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
296 struct afb_export *export = from_api_x3(closure);
298 /* check daemon state */
299 if (export->state == Api_State_Pre_Init) {
300 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
301 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
306 /* makes the event name */
307 plen = strlen(export->api.apiname);
309 event = alloca(nlen + plen + 2);
310 memcpy(event, export->api.apiname, plen);
312 memcpy(event + plen + 1, name, nlen + 1);
314 /* broadcast the event */
315 return afb_evt_broadcast(event, object);
318 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
320 return afb_common_rootdir_open_locale(filename, flags, locale);
323 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
325 return jobs_queue(group, timeout, callback, argument);
328 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
330 return afb_xreq_unstore(sreq);
333 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
335 struct afb_export *export = from_api_x3(closure);
337 char *iter, *end, save;
339 /* emit a warning about unexpected require in preinit */
340 if (export->state == Api_State_Pre_Init)
341 WARNING("[API %s] requiring apis in pre-init may lead to unexpected result (requires%s: %s)",
342 export->api.apiname, initialized ? " initialized" : "", name);
344 /* scan the names in a local copy */
346 iter = strdupa(name);
352 if (!save) /* at end? */
355 /* search for the end */
357 while (save && !isspace(save))
361 /* check the required api */
362 if (export->state == Api_State_Pre_Init)
363 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
365 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
374 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
376 struct afb_export *export = from_api_x3(closure);
377 if (!afb_api_is_valid_name(aliasname)) {
378 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
382 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
383 afb_export_add_alias(export, apiname, aliasname);
387 static struct afb_api_x3 *api_new_api_cb(
388 struct afb_api_x3 *closure,
392 int (*preinit)(void*, struct afb_api_x3 *),
393 void *preinit_closure)
395 struct afb_export *export = from_api_x3(closure);
396 struct afb_api_v3 *apiv3 = afb_api_v3_create(
397 export->declare_set, export->call_set,
398 api, info, noconcurrency,
399 preinit, preinit_closure, 1,
401 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
404 /**********************************************
406 **********************************************/
407 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)
409 struct afb_export *export = from_api_x3(closure);
412 vverbose_cb(closure, level, file, line, function, fmt, args);
413 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
417 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)
419 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
422 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
424 struct afb_export *export = from_api_x3(closure);
425 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
426 afb_hook_api_event_make(export, name, r);
430 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
432 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
433 struct afb_event_x1 e;
435 e.itf = event ? event->itf : NULL;
439 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
442 struct afb_export *export = from_api_x3(closure);
443 json_object_get(object);
444 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
445 r = event_broadcast_cb(closure, name, object);
446 afb_hook_api_event_broadcast_after(export, name, object, r);
447 json_object_put(object);
451 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
453 struct afb_export *export = from_api_x3(closure);
454 struct sd_event *r = systemd_get_event_loop();
455 return afb_hook_api_get_event_loop(export, r);
458 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
460 struct afb_export *export = from_api_x3(closure);
461 struct sd_bus *r = systemd_get_user_bus();
462 return afb_hook_api_get_user_bus(export, r);
465 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
467 struct afb_export *export = from_api_x3(closure);
468 struct sd_bus *r = systemd_get_system_bus();
469 return afb_hook_api_get_system_bus(export, r);
472 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
474 struct afb_export *export = from_api_x3(closure);
475 int r = afb_common_rootdir_get_fd();
476 return afb_hook_api_rootdir_get_fd(export, r);
479 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
481 struct afb_export *export = from_api_x3(closure);
482 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
483 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
486 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
488 struct afb_export *export = from_api_x3(closure);
489 int r = queue_job_cb(closure, callback, argument, group, timeout);
490 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
493 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
495 struct afb_export *export = from_api_x3(closure);
496 afb_hook_api_legacy_unstore_req(export, sreq);
497 return legacy_unstore_req_cb(closure, sreq);
500 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
503 struct afb_export *export = from_api_x3(closure);
504 afb_hook_api_require_api(export, name, initialized);
505 result = require_api_cb(closure, name, initialized);
506 return afb_hook_api_require_api_result(export, name, initialized, result);
509 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
511 struct afb_export *export = from_api_x3(closure);
512 int result = add_alias_cb(closure, apiname, aliasname);
513 return afb_hook_api_add_alias(export, apiname, aliasname, result);
516 static struct afb_api_x3 *hooked_api_new_api_cb(
517 struct afb_api_x3 *closure,
521 int (*preinit)(void*, struct afb_api_x3 *),
522 void *preinit_closure)
524 struct afb_api_x3 *result;
525 struct afb_export *export = from_api_x3(closure);
526 afb_hook_api_new_api_before(export, api, info, noconcurrency);
527 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
528 afb_hook_api_new_api_after(export, -!result, api);
532 /**********************************************
534 **********************************************/
535 static const struct afb_daemon_itf_x1 daemon_itf = {
536 .vverbose_v1 = legacy_vverbose_v1_cb,
537 .vverbose_v2 = vverbose_cb,
538 .event_make = legacy_event_x1_make_cb,
539 .event_broadcast = event_broadcast_cb,
540 .get_event_loop = systemd_get_event_loop,
541 .get_user_bus = systemd_get_user_bus,
542 .get_system_bus = systemd_get_system_bus,
543 .rootdir_get_fd = afb_common_rootdir_get_fd,
544 .rootdir_open_locale = rootdir_open_locale_cb,
545 .queue_job = queue_job_cb,
546 .unstore_req = legacy_unstore_req_cb,
547 .require_api = require_api_cb,
548 .add_alias = add_alias_cb,
549 .new_api = api_new_api_cb,
552 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
553 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
554 .vverbose_v2 = hooked_vverbose_cb,
555 .event_make = legacy_hooked_event_x1_make_cb,
556 .event_broadcast = hooked_event_broadcast_cb,
557 .get_event_loop = hooked_get_event_loop,
558 .get_user_bus = hooked_get_user_bus,
559 .get_system_bus = hooked_get_system_bus,
560 .rootdir_get_fd = hooked_rootdir_get_fd,
561 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
562 .queue_job = hooked_queue_job_cb,
563 .unstore_req = legacy_hooked_unstore_req_cb,
564 .require_api = hooked_require_api_cb,
565 .add_alias = hooked_add_alias_cb,
566 .new_api = hooked_api_new_api_cb,
569 /******************************************************************************
570 ******************************************************************************
571 ******************************************************************************
572 ******************************************************************************
574 ******************************************************************************
575 ******************************************************************************
576 ******************************************************************************
577 ******************************************************************************/
579 /* the common session for services sharing their session */
580 static struct afb_session *common_session;
582 /******************************************************************************
583 ******************************************************************************
584 ******************************************************************************
585 ******************************************************************************
587 ******************************************************************************
588 ******************************************************************************
589 ******************************************************************************
590 ******************************************************************************/
593 struct afb_api_x3 *apix3,
596 struct json_object *args,
597 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
600 struct afb_export *export = from_api_x3(apix3);
601 return afb_calls_call(export, api, verb, args, callback, closure);
604 static int call_sync_x3(
605 struct afb_api_x3 *apix3,
608 struct json_object *args,
609 struct json_object **object,
613 struct afb_export *export = from_api_x3(apix3);
614 return afb_calls_call_sync(export, api, verb, args, object, error, info);
617 static void legacy_call_v12(
618 struct afb_api_x3 *apix3,
621 struct json_object *args,
622 void (*callback)(void*, int, struct json_object*),
625 struct afb_export *export = from_api_x3(apix3);
626 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
629 static void legacy_call_x3(
630 struct afb_api_x3 *apix3,
633 struct json_object *args,
634 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
637 struct afb_export *export = from_api_x3(apix3);
638 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
641 static int legacy_call_sync(
642 struct afb_api_x3 *apix3,
645 struct json_object *args,
646 struct json_object **result)
648 struct afb_export *export = from_api_x3(apix3);
649 return afb_calls_legacy_call_sync(export, api, verb, args, result);
652 static void hooked_call_x3(
653 struct afb_api_x3 *apix3,
656 struct json_object *args,
657 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
660 struct afb_export *export = from_api_x3(apix3);
661 afb_calls_hooked_call(export, api, verb, args, callback, closure);
664 static int hooked_call_sync_x3(
665 struct afb_api_x3 *apix3,
668 struct json_object *args,
669 struct json_object **object,
673 struct afb_export *export = from_api_x3(apix3);
674 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
677 static void legacy_hooked_call_v12(
678 struct afb_api_x3 *apix3,
681 struct json_object *args,
682 void (*callback)(void*, int, struct json_object*),
685 struct afb_export *export = from_api_x3(apix3);
686 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
689 static void legacy_hooked_call_x3(
690 struct afb_api_x3 *apix3,
693 struct json_object *args,
694 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
697 struct afb_export *export = from_api_x3(apix3);
698 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
701 static int legacy_hooked_call_sync(
702 struct afb_api_x3 *apix3,
705 struct json_object *args,
706 struct json_object **result)
708 struct afb_export *export = from_api_x3(apix3);
709 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
712 /* the interface for services */
713 static const struct afb_service_itf_x1 service_itf = {
714 .call = legacy_call_v12,
715 .call_sync = legacy_call_sync
718 /* the interface for services */
719 static const struct afb_service_itf_x1 hooked_service_itf = {
720 .call = legacy_hooked_call_v12,
721 .call_sync = legacy_hooked_call_sync
724 /******************************************************************************
725 ******************************************************************************
726 ******************************************************************************
727 ******************************************************************************
729 ******************************************************************************
730 ******************************************************************************
731 ******************************************************************************
732 ******************************************************************************/
734 static int api_set_verbs_v2_cb(
735 struct afb_api_x3 *api,
736 const struct afb_verb_v2 *verbs)
738 struct afb_export *export = from_api_x3(api);
740 if (export->unsealed) {
741 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
749 static int api_set_verbs_v3_cb(
750 struct afb_api_x3 *api,
751 const struct afb_verb_v3 *verbs)
753 struct afb_export *export = from_api_x3(api);
755 if (!export->unsealed) {
760 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
764 static int api_add_verb_cb(
765 struct afb_api_x3 *api,
768 void (*callback)(struct afb_req_x2 *req),
770 const struct afb_auth *auth,
774 struct afb_export *export = from_api_x3(api);
776 if (!export->unsealed) {
781 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
784 static int api_del_verb_cb(
785 struct afb_api_x3 *api,
789 struct afb_export *export = from_api_x3(api);
791 if (!export->unsealed) {
796 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
799 static int api_set_on_event_cb(
800 struct afb_api_x3 *api,
801 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
803 struct afb_export *export = from_api_x3(api);
804 return afb_export_handle_events_v3(export, onevent);
807 static int api_set_on_init_cb(
808 struct afb_api_x3 *api,
809 int (*oninit)(struct afb_api_x3 *api))
811 struct afb_export *export = from_api_x3(api);
813 return afb_export_handle_init_v3(export, oninit);
816 static void api_seal_cb(
817 struct afb_api_x3 *api)
819 struct afb_export *export = from_api_x3(api);
821 export->unsealed = 0;
824 static int event_handler_add_cb(
825 struct afb_api_x3 *api,
827 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
830 struct afb_export *export = from_api_x3(api);
832 return afb_export_event_handler_add(export, pattern, callback, closure);
835 static int event_handler_del_cb(
836 struct afb_api_x3 *api,
840 struct afb_export *export = from_api_x3(api);
842 return afb_export_event_handler_del(export, pattern, closure);
845 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
847 struct afb_export *export = from_api_x3(api);
850 char *iter, *end, save;
852 iter = strdupa(name);
858 if (!save) /* at end? */
861 /* search for the end */
863 while (save && !isspace(save))
867 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
876 static int class_require_cb(struct afb_api_x3 *api, const char *name)
878 struct afb_export *export = from_api_x3(api);
881 char *iter, *end, save;
883 iter = strdupa(name);
889 if (!save) /* at end? */
892 /* search for the end */
894 while (save && !isspace(save))
898 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
907 static int delete_api_cb(struct afb_api_x3 *api)
909 struct afb_export *export = from_api_x3(api);
911 if (!export->unsealed) {
916 afb_export_undeclare(export);
917 afb_export_unref(export);
921 static struct json_object *settings_cb(struct afb_api_x3 *api)
923 struct afb_export *export = from_api_x3(api);
924 struct json_object *result = export->settings;
926 result = make_settings(export);
930 static int hooked_api_set_verbs_v2_cb(
931 struct afb_api_x3 *api,
932 const struct afb_verb_v2 *verbs)
934 struct afb_export *export = from_api_x3(api);
935 int result = api_set_verbs_v2_cb(api, verbs);
936 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
939 static int hooked_api_set_verbs_v3_cb(
940 struct afb_api_x3 *api,
941 const struct afb_verb_v3 *verbs)
943 struct afb_export *export = from_api_x3(api);
944 int result = api_set_verbs_v3_cb(api, verbs);
945 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
948 static int hooked_api_add_verb_cb(
949 struct afb_api_x3 *api,
952 void (*callback)(struct afb_req_x2 *req),
954 const struct afb_auth *auth,
958 struct afb_export *export = from_api_x3(api);
959 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
960 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
963 static int hooked_api_del_verb_cb(
964 struct afb_api_x3 *api,
968 struct afb_export *export = from_api_x3(api);
969 int result = api_del_verb_cb(api, verb, vcbdata);
970 return afb_hook_api_api_del_verb(export, result, verb);
973 static int hooked_api_set_on_event_cb(
974 struct afb_api_x3 *api,
975 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
977 struct afb_export *export = from_api_x3(api);
978 int result = api_set_on_event_cb(api, onevent);
979 return afb_hook_api_api_set_on_event(export, result);
982 static int hooked_api_set_on_init_cb(
983 struct afb_api_x3 *api,
984 int (*oninit)(struct afb_api_x3 *api))
986 struct afb_export *export = from_api_x3(api);
987 int result = api_set_on_init_cb(api, oninit);
988 return afb_hook_api_api_set_on_init(export, result);
991 static void hooked_api_seal_cb(
992 struct afb_api_x3 *api)
994 struct afb_export *export = from_api_x3(api);
995 afb_hook_api_api_seal(export);
999 static int hooked_event_handler_add_cb(
1000 struct afb_api_x3 *api,
1001 const char *pattern,
1002 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1005 struct afb_export *export = from_api_x3(api);
1006 int result = event_handler_add_cb(api, pattern, callback, closure);
1007 return afb_hook_api_event_handler_add(export, result, pattern);
1010 static int hooked_event_handler_del_cb(
1011 struct afb_api_x3 *api,
1012 const char *pattern,
1015 struct afb_export *export = from_api_x3(api);
1016 int result = event_handler_del_cb(api, pattern, closure);
1017 return afb_hook_api_event_handler_del(export, result, pattern);
1020 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1022 struct afb_export *export = from_api_x3(api);
1023 int result = class_provide_cb(api, name);
1024 return afb_hook_api_class_provide(export, result, name);
1027 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1029 struct afb_export *export = from_api_x3(api);
1030 int result = class_require_cb(api, name);
1031 return afb_hook_api_class_require(export, result, name);
1034 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1036 struct afb_export *export = afb_export_addref(from_api_x3(api));
1037 int result = delete_api_cb(api);
1038 result = afb_hook_api_delete_api(export, result);
1039 afb_export_unref(export);
1043 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1045 struct afb_export *export = from_api_x3(api);
1046 struct json_object *result = settings_cb(api);
1047 result = afb_hook_api_settings(export, result);
1051 static const struct afb_api_x3_itf api_x3_itf = {
1053 .vverbose = (void*)vverbose_cb,
1055 .get_event_loop = systemd_get_event_loop,
1056 .get_user_bus = systemd_get_user_bus,
1057 .get_system_bus = systemd_get_system_bus,
1058 .rootdir_get_fd = afb_common_rootdir_get_fd,
1059 .rootdir_open_locale = rootdir_open_locale_cb,
1060 .queue_job = queue_job_cb,
1062 .require_api = require_api_cb,
1063 .add_alias = add_alias_cb,
1065 .event_broadcast = event_broadcast_cb,
1066 .event_make = event_x2_make_cb,
1068 .legacy_call = legacy_call_x3,
1069 .legacy_call_sync = legacy_call_sync,
1071 .api_new_api = api_new_api_cb,
1072 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1073 .api_add_verb = api_add_verb_cb,
1074 .api_del_verb = api_del_verb_cb,
1075 .api_set_on_event = api_set_on_event_cb,
1076 .api_set_on_init = api_set_on_init_cb,
1077 .api_seal = api_seal_cb,
1078 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1079 .event_handler_add = event_handler_add_cb,
1080 .event_handler_del = event_handler_del_cb,
1083 .call_sync = call_sync_x3,
1085 .class_provide = class_provide_cb,
1086 .class_require = class_require_cb,
1088 .delete_api = delete_api_cb,
1089 .settings = settings_cb,
1092 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1094 .vverbose = hooked_vverbose_cb,
1096 .get_event_loop = hooked_get_event_loop,
1097 .get_user_bus = hooked_get_user_bus,
1098 .get_system_bus = hooked_get_system_bus,
1099 .rootdir_get_fd = hooked_rootdir_get_fd,
1100 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1101 .queue_job = hooked_queue_job_cb,
1103 .require_api = hooked_require_api_cb,
1104 .add_alias = hooked_add_alias_cb,
1106 .event_broadcast = hooked_event_broadcast_cb,
1107 .event_make = hooked_event_x2_make_cb,
1109 .legacy_call = legacy_hooked_call_x3,
1110 .legacy_call_sync = legacy_hooked_call_sync,
1112 .api_new_api = hooked_api_new_api_cb,
1113 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1114 .api_add_verb = hooked_api_add_verb_cb,
1115 .api_del_verb = hooked_api_del_verb_cb,
1116 .api_set_on_event = hooked_api_set_on_event_cb,
1117 .api_set_on_init = hooked_api_set_on_init_cb,
1118 .api_seal = hooked_api_seal_cb,
1119 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1120 .event_handler_add = hooked_event_handler_add_cb,
1121 .event_handler_del = hooked_event_handler_del_cb,
1123 .call = hooked_call_x3,
1124 .call_sync = hooked_call_sync_x3,
1126 .class_provide = hooked_class_provide_cb,
1127 .class_require = hooked_class_require_cb,
1129 .delete_api = hooked_delete_api_cb,
1130 .settings = hooked_settings_cb,
1133 /******************************************************************************
1134 ******************************************************************************
1135 ******************************************************************************
1136 ******************************************************************************
1138 ******************************************************************************
1139 ******************************************************************************
1140 ******************************************************************************
1141 ******************************************************************************/
1144 * Propagates the event to the service
1146 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1148 const struct globset_handler *handler;
1149 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
1150 struct afb_export *export = from_api_x3(closure);
1152 /* hook the event before */
1153 if (export->hooksvc & afb_hook_flag_api_on_event)
1154 afb_hook_api_on_event_before(export, event, eventid, object);
1156 /* transmit to specific handlers */
1157 /* search the handler */
1158 handler = export->event_handlers ? globset_match(export->event_handlers, event) : NULL;
1160 callback = handler->callback;
1161 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1162 callback(handler->closure, event, object, to_api_x3(export));
1164 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1165 callback(handler->closure, event, object, to_api_x3(export));
1166 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1169 /* transmit to default handler */
1170 if (export->on_any_event_v3)
1171 export->on_any_event_v3(to_api_x3(export), event, object);
1172 else if (export->on_any_event_v12)
1173 export->on_any_event_v12(event, object);
1176 /* hook the event after */
1177 if (export->hooksvc & afb_hook_flag_api_on_event)
1178 afb_hook_api_on_event_after(export, event, eventid, object);
1179 json_object_put(object);
1182 /* the interface for events */
1183 static const struct afb_evt_itf evt_itf = {
1184 .broadcast = listener_of_events,
1185 .push = listener_of_events
1188 /* ensure an existing listener */
1189 static int ensure_listener(struct afb_export *export)
1191 if (!export->listener) {
1192 export->listener = afb_evt_listener_create(&evt_itf, export);
1193 if (export->listener == NULL)
1199 int afb_export_event_handler_add(
1200 struct afb_export *export,
1201 const char *pattern,
1202 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1207 /* ensure the listener */
1208 rc = ensure_listener(export);
1212 /* ensure the globset for event handling */
1213 if (!export->event_handlers) {
1214 export->event_handlers = globset_create();
1215 if (!export->event_handlers)
1219 /* add the handler */
1220 rc = globset_add(export->event_handlers, pattern, callback, closure);
1224 if (errno == EEXIST) {
1225 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1230 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1234 int afb_export_event_handler_del(
1235 struct afb_export *export,
1236 const char *pattern,
1239 if (export->event_handlers
1240 && !globset_del(export->event_handlers, pattern, closure))
1243 ERROR("[API %s] event handler %s not found", export->api.apiname, pattern);
1248 /******************************************************************************
1249 ******************************************************************************
1250 ******************************************************************************
1251 ******************************************************************************
1253 ******************************************************************************
1254 ******************************************************************************
1255 ******************************************************************************
1256 ******************************************************************************/
1258 static struct afb_export *create(
1259 struct afb_apiset *declare_set,
1260 struct afb_apiset *call_set,
1261 const char *apiname,
1263 enum afb_api_version version)
1265 struct afb_export *export;
1268 /* session shared with other exports */
1269 if (common_session == NULL) {
1270 common_session = afb_session_create (0);
1271 if (common_session == NULL)
1274 lenapi = strlen(apiname);
1275 export = calloc(1, sizeof *export + lenapi + (path == apiname || !path ? 0 : strlen(path)));
1279 export->refcount = 1;
1280 strcpy(export->name, apiname);
1281 export->api.apiname = export->name;
1282 if (path == apiname)
1283 export->path = export->name;
1285 export->path = strcpy(&export->name[lenapi + 1], path);
1286 export->version = version;
1287 export->state = Api_State_Pre_Init;
1288 export->session = afb_session_addref(common_session);
1289 export->declare_set = afb_apiset_addref(declare_set);
1290 export->call_set = afb_apiset_addref(call_set);
1295 struct afb_export *afb_export_addref(struct afb_export *export)
1298 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1302 void afb_export_unref(struct afb_export *export)
1304 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1305 afb_export_destroy(export);
1308 void afb_export_destroy(struct afb_export *export)
1311 if (export->event_handlers)
1312 globset_destroy(export->event_handlers);
1313 if (export->listener != NULL)
1314 afb_evt_listener_unref(export->listener);
1315 afb_session_unref(export->session);
1316 afb_apiset_unref(export->declare_set);
1317 afb_apiset_unref(export->call_set);
1318 json_object_put(export->settings);
1319 afb_export_unref(export->creator);
1320 if (export->api.apiname != export->name)
1321 free((void*)export->api.apiname);
1326 struct afb_export *afb_export_create_none_for_path(
1327 struct afb_apiset *declare_set,
1328 struct afb_apiset *call_set,
1330 int (*creator)(void*, struct afb_api_x3*),
1333 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1335 afb_export_logmask_set(export, logmask);
1336 afb_export_update_hooks(export);
1337 if (creator && creator(closure, to_api_x3(export)) < 0) {
1338 afb_export_unref(export);
1345 #if defined(WITH_LEGACY_BINDING_V1)
1346 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1347 struct afb_apiset *call_set,
1348 const char *apiname,
1349 int (*init)(struct afb_service_x1),
1350 void (*onevent)(const char*, struct json_object*),
1353 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1355 export->init.v1 = init;
1356 export->on_any_event_v12 = onevent;
1357 export->export.v1.mode = AFB_MODE_LOCAL;
1358 export->export.v1.daemon.closure = to_api_x3(export);
1359 afb_export_logmask_set(export, logmask);
1360 afb_export_update_hooks(export);
1366 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1367 struct afb_apiset *call_set,
1368 const char *apiname,
1369 const struct afb_binding_v2 *binding,
1370 struct afb_binding_data_v2 *data,
1372 void (*onevent)(const char*, struct json_object*),
1375 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1377 export->init.v2 = init;
1378 export->on_any_event_v12 = onevent;
1379 export->desc.v2 = binding;
1380 export->export.v2 = data;
1381 data->daemon.closure = to_api_x3(export);
1382 data->service.closure = to_api_x3(export);
1383 afb_export_logmask_set(export, logmask);
1384 afb_export_update_hooks(export);
1389 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1390 struct afb_apiset *call_set,
1391 const char *apiname,
1392 struct afb_api_v3 *apiv3,
1393 struct afb_export* creator,
1396 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1398 export->unsealed = 1;
1399 export->desc.v3 = apiv3;
1400 export->creator = afb_export_addref(creator);
1401 afb_export_logmask_set(export, logmask);
1402 afb_export_update_hooks(export);
1407 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1409 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1412 int afb_export_rename(struct afb_export *export, const char *apiname)
1416 if (export->declared) {
1421 /* copy the name locally */
1422 name = strdup(apiname);
1428 if (export->api.apiname != export->name)
1429 free((void*)export->api.apiname);
1430 export->api.apiname = name;
1432 afb_export_update_hooks(export);
1436 const char *afb_export_apiname(const struct afb_export *export)
1438 return export->api.apiname;
1441 void afb_export_update_hooks(struct afb_export *export)
1443 export->hookditf = afb_hook_flags_api(export->api.apiname);
1444 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1445 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1447 switch (export->version) {
1448 #if defined(WITH_LEGACY_BINDING_V1)
1450 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1454 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1455 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1460 int afb_export_unshare_session(struct afb_export *export)
1462 if (export->session == common_session) {
1463 export->session = afb_session_create (0);
1464 if (export->session)
1465 afb_session_unref(common_session);
1467 export->session = common_session;
1474 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1477 switch (export->version) {
1478 #if defined(WITH_LEGACY_BINDING_V1)
1484 ERROR("invalid version 12 for API %s", export->api.apiname);
1489 export->on_any_event_v12 = on_event;
1490 return ensure_listener(export);
1493 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))
1496 switch (export->version) {
1497 case Api_Version_3: break;
1499 ERROR("invalid version Dyn for API %s", export->api.apiname);
1504 export->on_any_event_v3 = on_event;
1505 return ensure_listener(export);
1508 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1510 if (export->state != Api_State_Pre_Init) {
1511 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1516 export->init.v3 = oninit;
1520 #if defined(WITH_LEGACY_BINDING_V1)
1522 * Starts a new service (v1)
1524 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1526 return export->desc.v1 = regfun(&export->export.v1);
1530 int afb_export_preinit_x3(
1531 struct afb_export *export,
1532 int (*preinit)(void*, struct afb_api_x3*),
1535 return preinit(closure, to_api_x3(export));
1538 int afb_export_logmask_get(const struct afb_export *export)
1540 return export->api.logmask;
1543 void afb_export_logmask_set(struct afb_export *export, int mask)
1545 export->api.logmask = mask;
1546 switch (export->version) {
1547 #if defined(WITH_LEGACY_BINDING_V1)
1548 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1550 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1554 void *afb_export_userdata_get(const struct afb_export *export)
1556 return export->api.userdata;
1559 void afb_export_userdata_set(struct afb_export *export, void *data)
1561 export->api.userdata = data;
1564 /******************************************************************************
1565 ******************************************************************************
1566 ******************************************************************************
1567 ******************************************************************************
1569 ******************************************************************************
1570 ******************************************************************************
1571 ******************************************************************************
1572 ******************************************************************************/
1577 struct afb_export *export;
1580 static void do_init(int sig, void *closure)
1583 struct init *init = closure;
1584 struct afb_export *export;
1589 export = init->export;
1590 switch (export->version) {
1591 #if defined(WITH_LEGACY_BINDING_V1)
1593 rc = export->init.v1 ? export->init.v1(
1594 (struct afb_service_x1){
1595 .itf = &hooked_service_itf,
1596 .closure = to_api_x3(export) }) : 0;
1600 rc = export->init.v2 ? export->init.v2() : 0;
1603 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1610 init->return_code = rc;
1614 int afb_export_start(struct afb_export *export)
1620 switch (export->state) {
1624 case Api_State_Init:
1625 /* starting in progress: it is an error */
1626 ERROR("Service of API %s required started while starting", export->api.apiname);
1633 /* set event handling */
1634 switch (export->version) {
1635 #if defined(WITH_LEGACY_BINDING_V1)
1639 if (export->on_any_event_v12) {
1640 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1649 ERROR("Can't set event handler for %s", export->api.apiname);
1653 /* Starts the service */
1654 if (export->hooksvc & afb_hook_flag_api_start)
1655 afb_hook_api_start_before(export);
1657 export->state = Api_State_Init;
1658 init.export = export;
1659 sig_monitor(0, do_init, &init);
1660 rc = init.return_code;
1661 export->state = Api_State_Run;
1663 if (export->hooksvc & afb_hook_flag_api_start)
1664 afb_hook_api_start_after(export, rc);
1667 /* initialisation error */
1668 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1675 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1677 struct afb_export *export = closure;
1679 xreq->request.api = to_api_x3(export);
1681 switch (export->version) {
1682 #if defined(WITH_LEGACY_BINDING_V1)
1684 afb_api_so_v1_process_call(export->desc.v1, xreq);
1688 afb_api_so_v2_process_call(export->desc.v2, xreq);
1691 afb_api_v3_process_call(export->desc.v3, xreq);
1694 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1699 static struct json_object *api_describe_cb(void *closure)
1701 struct afb_export *export = closure;
1702 struct json_object *result;
1704 switch (export->version) {
1705 #if defined(WITH_LEGACY_BINDING_V1)
1707 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1711 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1714 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1723 static int api_service_start_cb(void *closure)
1725 struct afb_export *export = closure;
1727 return afb_export_start(export);
1730 static void api_update_hooks_cb(void *closure)
1732 struct afb_export *export = closure;
1734 afb_export_update_hooks(export);
1737 static int api_get_logmask_cb(void *closure)
1739 struct afb_export *export = closure;
1741 return afb_export_logmask_get(export);
1744 static void api_set_logmask_cb(void *closure, int level)
1746 struct afb_export *export = closure;
1748 afb_export_logmask_set(export, level);
1751 static void api_unref_cb(void *closure)
1753 struct afb_export *export = closure;
1755 afb_export_unref(export);
1758 static struct afb_api_itf export_api_itf =
1760 .call = api_call_cb,
1761 .service_start = api_service_start_cb,
1762 .update_hooks = api_update_hooks_cb,
1763 .get_logmask = api_get_logmask_cb,
1764 .set_logmask = api_set_logmask_cb,
1765 .describe = api_describe_cb,
1766 .unref = api_unref_cb
1769 int afb_export_declare(struct afb_export *export,
1773 struct afb_api_item afb_api;
1775 if (export->declared)
1778 /* init the record structure */
1779 afb_api.closure = afb_export_addref(export);
1780 afb_api.itf = &export_api_itf;
1781 afb_api.group = noconcurrency ? export : NULL;
1783 /* records the binding */
1784 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1786 export->declared = 1;
1788 ERROR("can't declare export %s to set %s, ABORTING it!",
1789 export->api.apiname,
1790 afb_apiset_name(export->declare_set));
1791 afb_export_unref(export);
1798 void afb_export_undeclare(struct afb_export *export)
1800 if (export->declared) {
1801 export->declared = 0;
1802 afb_apiset_del(export->declare_set, export->api.apiname);
1806 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1808 return afb_evt_event_x2_add_watch(export->listener, event);
1811 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1813 return afb_evt_event_x2_remove_watch(export->listener, event);
1816 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1818 afb_xreq_process(xreq, export->call_set);
1821 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1823 afb_context_init(context, export->session, NULL);
1824 context->validated = 1;