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 WITH_LEGACY_BINDING_V1
37 #include "afb-api-so-v1.h"
39 #if WITH_LEGACY_BINDING_V2
40 #include "afb-api-so-v2.h"
42 #include "afb-api-v3.h"
43 #include "afb-common.h"
46 #include "afb-export.h"
48 #include "afb-msg-json.h"
49 #include "afb-session.h"
51 #include "afb-calls.h"
59 #include "sig-monitor.h"
60 #include "wrap-json.h"
62 /*************************************************************************
64 ************************************************************************/
67 * Actually supported versions
72 #if WITH_LEGACY_BINDING_V1
75 #if WITH_LEGACY_BINDING_V2
82 * The states of exported APIs
92 * structure of the exported API
97 struct afb_api_x3 api;
102 /* version of the api */
109 unsigned declared: 1;
112 unsigned unsealed: 1;
120 /* session for service */
121 struct afb_session *session;
123 /* apiset the API is declared in */
124 struct afb_apiset *declare_set;
126 /* apiset for calls */
127 struct afb_apiset *call_set;
129 /* event listener for service or NULL */
130 struct afb_evt_listener *listener;
132 /* event handler list */
133 struct globset *event_handlers;
136 struct afb_export *creator;
138 /* path indication if any */
142 struct json_object *settings;
144 /* internal descriptors */
146 #if WITH_LEGACY_BINDING_V1
147 struct afb_binding_v1 *v1;
149 const struct afb_binding_v2 *v2;
150 struct afb_api_v3 *v3;
155 #if WITH_LEGACY_BINDING_V1
156 int (*v1)(struct afb_service_x1);
159 int (*v3)(struct afb_api_x3 *api);
163 void (*on_any_event_v12)(const char *event, struct json_object *object);
164 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
168 #if WITH_LEGACY_BINDING_V1
169 struct afb_binding_interface_v1 v1;
171 struct afb_binding_data_v2 *v2;
178 /*****************************************************************************/
180 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
182 return (struct afb_api_x3*)export;
185 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
187 return (struct afb_export*)api;
190 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
192 return from_api_x3(api);
195 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
197 return to_api_x3(export);
200 /******************************************************************************
201 ******************************************************************************
202 ******************************************************************************
203 ******************************************************************************
205 ******************************************************************************
206 ******************************************************************************
207 ******************************************************************************
208 ******************************************************************************/
210 static struct json_object *configuration;
212 void afb_export_set_config(struct json_object *config)
214 struct json_object *save = configuration;
215 configuration = json_object_get(config);
216 json_object_put(save);
219 static struct json_object *make_settings(struct afb_export *export)
221 struct json_object *result;
222 struct json_object *obj;
223 struct afb_export *iter;
226 /* clone the globals */
227 if (json_object_object_get_ex(configuration, "*", &obj))
228 result = wrap_json_clone(obj);
230 result = json_object_new_object();
233 if (json_object_object_get_ex(configuration, export->name, &obj))
234 wrap_json_object_add(result, obj);
236 /* add library path */
237 for (iter = export ; iter && !iter->path ; iter = iter->creator);
239 path = realpath(iter->path, NULL);
240 json_object_object_add(result, "binding-path", json_object_new_string(path));
244 export->settings = result;
248 /******************************************************************************
249 ******************************************************************************
250 ******************************************************************************
251 ******************************************************************************
253 ******************************************************************************
254 ******************************************************************************
255 ******************************************************************************
256 ******************************************************************************/
258 /**********************************************
260 **********************************************/
261 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)
264 struct afb_export *export = from_api_x3(closure);
266 if (!fmt || vasprintf(&p, fmt, args) < 0)
267 vverbose(level, file, line, function, fmt, args);
269 verbose(level, file, line, function, (verbose_is_colorized() == 0 ? "[API %s] %s" : COLOR_API "[API %s]" COLOR_DEFAULT " %s"), export->api.apiname, p);
274 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
276 struct afb_export *export = from_api_x3(closure);
278 /* check daemon state */
279 if (export->state == Api_State_Pre_Init) {
280 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
285 /* create the event */
286 return afb_evt_event_x2_create2(export->api.apiname, name);
289 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
293 struct afb_export *export = from_api_x3(closure);
295 /* check daemon state */
296 if (export->state == Api_State_Pre_Init) {
297 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
298 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
303 /* makes the event name */
304 plen = strlen(export->api.apiname);
306 event = alloca(nlen + plen + 2);
307 memcpy(event, export->api.apiname, plen);
309 memcpy(event + plen + 1, name, nlen + 1);
311 /* broadcast the event */
312 return afb_evt_broadcast(event, object);
315 static struct sd_event *get_event_loop(struct afb_api_x3 *closure)
318 jobs_acquire_event_manager();
319 return systemd_get_event_loop();
326 static struct sd_bus *get_user_bus(struct afb_api_x3 *closure)
329 jobs_acquire_event_manager();
330 return systemd_get_user_bus();
337 static struct sd_bus *get_system_bus(struct afb_api_x3 *closure)
340 jobs_acquire_event_manager();
341 return systemd_get_system_bus();
348 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
350 return afb_common_rootdir_open_locale(filename, flags, locale);
353 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
355 return jobs_queue(group, timeout, callback, argument);
358 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
360 struct afb_export *export = from_api_x3(closure);
362 char *iter, *end, save;
364 /* emit a warning about unexpected require in preinit */
365 if (export->state == Api_State_Pre_Init)
366 WARNING("[API %s] requiring apis in pre-init may lead to unexpected result (requires%s: %s)",
367 export->api.apiname, initialized ? " initialized" : "", name);
369 /* scan the names in a local copy */
371 iter = strdupa(name);
377 if (!save) /* at end? */
380 /* search for the end */
382 while (save && !isspace(save))
386 /* check the required api */
387 if (export->state == Api_State_Pre_Init)
388 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
390 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
399 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
401 struct afb_export *export = from_api_x3(closure);
402 if (!afb_api_is_valid_name(aliasname)) {
403 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
407 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
408 afb_export_add_alias(export, apiname, aliasname);
412 static struct afb_api_x3 *api_new_api_cb(
413 struct afb_api_x3 *closure,
417 int (*preinit)(void*, struct afb_api_x3 *),
418 void *preinit_closure)
420 struct afb_export *export = from_api_x3(closure);
421 struct afb_api_v3 *apiv3 = afb_api_v3_create(
422 export->declare_set, export->call_set,
423 api, info, noconcurrency,
424 preinit, preinit_closure, 1,
426 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
429 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
431 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
433 vverbose_cb(closure, level, file, line, NULL, fmt, args);
436 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
438 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
439 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
442 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
444 return afb_xreq_unstore(sreq);
447 static const struct afb_daemon_itf_x1 daemon_itf = {
448 .vverbose_v1 = legacy_vverbose_v1_cb,
449 .vverbose_v2 = vverbose_cb,
450 .event_make = legacy_event_x1_make_cb,
451 .event_broadcast = event_broadcast_cb,
452 .get_event_loop = get_event_loop,
453 .get_user_bus = get_user_bus,
454 .get_system_bus = get_system_bus,
455 .rootdir_get_fd = afb_common_rootdir_get_fd,
456 .rootdir_open_locale = rootdir_open_locale_cb,
457 .queue_job = queue_job_cb,
458 .unstore_req = legacy_unstore_req_cb,
459 .require_api = require_api_cb,
460 .add_alias = add_alias_cb,
461 .new_api = api_new_api_cb,
466 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)
468 struct afb_export *export = from_api_x3(closure);
471 vverbose_cb(closure, level, file, line, function, fmt, args);
472 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
476 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
478 struct afb_export *export = from_api_x3(closure);
479 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
480 afb_hook_api_event_make(export, name, r);
484 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
487 struct afb_export *export = from_api_x3(closure);
488 json_object_get(object);
489 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
490 r = event_broadcast_cb(closure, name, object);
491 afb_hook_api_event_broadcast_after(export, name, object, r);
492 json_object_put(object);
496 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
498 struct afb_export *export = from_api_x3(closure);
501 r = get_event_loop(closure);
502 return afb_hook_api_get_event_loop(export, r);
505 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
507 struct afb_export *export = from_api_x3(closure);
510 r = get_user_bus(closure);
511 return afb_hook_api_get_user_bus(export, r);
514 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
516 struct afb_export *export = from_api_x3(closure);
519 r = get_system_bus(closure);
520 return afb_hook_api_get_system_bus(export, r);
523 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
525 struct afb_export *export = from_api_x3(closure);
526 int r = afb_common_rootdir_get_fd();
527 return afb_hook_api_rootdir_get_fd(export, r);
530 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
532 struct afb_export *export = from_api_x3(closure);
533 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
534 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
537 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
539 struct afb_export *export = from_api_x3(closure);
540 int r = queue_job_cb(closure, callback, argument, group, timeout);
541 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
544 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
547 struct afb_export *export = from_api_x3(closure);
548 afb_hook_api_require_api(export, name, initialized);
549 result = require_api_cb(closure, name, initialized);
550 return afb_hook_api_require_api_result(export, name, initialized, result);
553 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
555 struct afb_export *export = from_api_x3(closure);
556 int result = add_alias_cb(closure, apiname, aliasname);
557 return afb_hook_api_add_alias(export, apiname, aliasname, result);
560 static struct afb_api_x3 *hooked_api_new_api_cb(
561 struct afb_api_x3 *closure,
565 int (*preinit)(void*, struct afb_api_x3 *),
566 void *preinit_closure)
568 struct afb_api_x3 *result;
569 struct afb_export *export = from_api_x3(closure);
570 afb_hook_api_new_api_before(export, api, info, noconcurrency);
571 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
572 afb_hook_api_new_api_after(export, -!result, api);
576 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
578 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)
580 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
583 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
585 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
586 struct afb_event_x1 e;
588 e.itf = event ? event->itf : NULL;
592 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
594 struct afb_export *export = from_api_x3(closure);
595 afb_hook_api_legacy_unstore_req(export, sreq);
596 return legacy_unstore_req_cb(closure, sreq);
599 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
600 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
601 .vverbose_v2 = hooked_vverbose_cb,
602 .event_make = legacy_hooked_event_x1_make_cb,
603 .event_broadcast = hooked_event_broadcast_cb,
604 .get_event_loop = hooked_get_event_loop,
605 .get_user_bus = hooked_get_user_bus,
606 .get_system_bus = hooked_get_system_bus,
607 .rootdir_get_fd = hooked_rootdir_get_fd,
608 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
609 .queue_job = hooked_queue_job_cb,
610 .unstore_req = legacy_hooked_unstore_req_cb,
611 .require_api = hooked_require_api_cb,
612 .add_alias = hooked_add_alias_cb,
613 .new_api = hooked_api_new_api_cb,
619 /******************************************************************************
620 ******************************************************************************
621 ******************************************************************************
622 ******************************************************************************
624 ******************************************************************************
625 ******************************************************************************
626 ******************************************************************************
627 ******************************************************************************/
629 /* the common session for services sharing their session */
630 static struct afb_session *common_session;
632 /******************************************************************************
633 ******************************************************************************
634 ******************************************************************************
635 ******************************************************************************
637 ******************************************************************************
638 ******************************************************************************
639 ******************************************************************************
640 ******************************************************************************/
643 struct afb_api_x3 *apix3,
646 struct json_object *args,
647 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
650 struct afb_export *export = from_api_x3(apix3);
651 return afb_calls_call(export, api, verb, args, callback, closure);
654 static int call_sync_x3(
655 struct afb_api_x3 *apix3,
658 struct json_object *args,
659 struct json_object **object,
663 struct afb_export *export = from_api_x3(apix3);
664 return afb_calls_call_sync(export, api, verb, args, object, error, info);
667 static void legacy_call_x3(
668 struct afb_api_x3 *apix3,
671 struct json_object *args,
672 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
675 struct afb_export *export = from_api_x3(apix3);
676 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
679 static int legacy_call_sync(
680 struct afb_api_x3 *apix3,
683 struct json_object *args,
684 struct json_object **result)
686 struct afb_export *export = from_api_x3(apix3);
687 return afb_calls_legacy_call_sync(export, api, verb, args, result);
690 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
692 static void legacy_call_v12(
693 struct afb_api_x3 *apix3,
696 struct json_object *args,
697 void (*callback)(void*, int, struct json_object*),
700 struct afb_export *export = from_api_x3(apix3);
701 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
704 /* the interface for services */
705 static const struct afb_service_itf_x1 service_itf = {
706 .call = legacy_call_v12,
707 .call_sync = legacy_call_sync
712 static void hooked_call_x3(
713 struct afb_api_x3 *apix3,
716 struct json_object *args,
717 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
720 struct afb_export *export = from_api_x3(apix3);
721 afb_calls_hooked_call(export, api, verb, args, callback, closure);
724 static int hooked_call_sync_x3(
725 struct afb_api_x3 *apix3,
728 struct json_object *args,
729 struct json_object **object,
733 struct afb_export *export = from_api_x3(apix3);
734 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
737 static void legacy_hooked_call_x3(
738 struct afb_api_x3 *apix3,
741 struct json_object *args,
742 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
745 struct afb_export *export = from_api_x3(apix3);
746 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
749 static int legacy_hooked_call_sync(
750 struct afb_api_x3 *apix3,
753 struct json_object *args,
754 struct json_object **result)
756 struct afb_export *export = from_api_x3(apix3);
757 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
760 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
762 static void legacy_hooked_call_v12(
763 struct afb_api_x3 *apix3,
766 struct json_object *args,
767 void (*callback)(void*, int, struct json_object*),
770 struct afb_export *export = from_api_x3(apix3);
771 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
774 /* the interface for services */
775 static const struct afb_service_itf_x1 hooked_service_itf = {
776 .call = legacy_hooked_call_v12,
777 .call_sync = legacy_hooked_call_sync
783 /******************************************************************************
784 ******************************************************************************
785 ******************************************************************************
786 ******************************************************************************
788 ******************************************************************************
789 ******************************************************************************
790 ******************************************************************************
791 ******************************************************************************/
793 static int api_set_verbs_v2_cb(
794 struct afb_api_x3 *api,
795 const struct afb_verb_v2 *verbs)
797 #if WITH_LEGACY_BINDING_V2
798 struct afb_export *export = from_api_x3(api);
800 if (export->unsealed) {
801 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
812 static int api_set_verbs_v3_cb(
813 struct afb_api_x3 *api,
814 const struct afb_verb_v3 *verbs)
816 struct afb_export *export = from_api_x3(api);
818 if (!export->unsealed) {
823 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
827 static int api_add_verb_cb(
828 struct afb_api_x3 *api,
831 void (*callback)(struct afb_req_x2 *req),
833 const struct afb_auth *auth,
837 struct afb_export *export = from_api_x3(api);
839 if (!export->unsealed) {
844 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
847 static int api_del_verb_cb(
848 struct afb_api_x3 *api,
852 struct afb_export *export = from_api_x3(api);
854 if (!export->unsealed) {
859 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
862 static int api_set_on_event_cb(
863 struct afb_api_x3 *api,
864 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
866 struct afb_export *export = from_api_x3(api);
867 return afb_export_handle_events_v3(export, onevent);
870 static int api_set_on_init_cb(
871 struct afb_api_x3 *api,
872 int (*oninit)(struct afb_api_x3 *api))
874 struct afb_export *export = from_api_x3(api);
876 return afb_export_handle_init_v3(export, oninit);
879 static void api_seal_cb(
880 struct afb_api_x3 *api)
882 struct afb_export *export = from_api_x3(api);
884 export->unsealed = 0;
887 static int event_handler_add_cb(
888 struct afb_api_x3 *api,
890 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
893 struct afb_export *export = from_api_x3(api);
895 return afb_export_event_handler_add(export, pattern, callback, closure);
898 static int event_handler_del_cb(
899 struct afb_api_x3 *api,
903 struct afb_export *export = from_api_x3(api);
905 return afb_export_event_handler_del(export, pattern, closure);
908 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
910 struct afb_export *export = from_api_x3(api);
913 char *iter, *end, save;
915 iter = strdupa(name);
921 if (!save) /* at end? */
924 /* search for the end */
926 while (save && !isspace(save))
930 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
939 static int class_require_cb(struct afb_api_x3 *api, const char *name)
941 struct afb_export *export = from_api_x3(api);
944 char *iter, *end, save;
946 iter = strdupa(name);
952 if (!save) /* at end? */
955 /* search for the end */
957 while (save && !isspace(save))
961 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
970 static int delete_api_cb(struct afb_api_x3 *api)
972 struct afb_export *export = from_api_x3(api);
974 if (!export->unsealed) {
979 afb_export_undeclare(export);
980 afb_export_unref(export);
984 static struct json_object *settings_cb(struct afb_api_x3 *api)
986 struct afb_export *export = from_api_x3(api);
987 struct json_object *result = export->settings;
989 result = make_settings(export);
993 static const struct afb_api_x3_itf api_x3_itf = {
995 .vverbose = (void*)vverbose_cb,
997 .get_event_loop = get_event_loop,
998 .get_user_bus = get_user_bus,
999 .get_system_bus = get_system_bus,
1000 .rootdir_get_fd = afb_common_rootdir_get_fd,
1001 .rootdir_open_locale = rootdir_open_locale_cb,
1002 .queue_job = queue_job_cb,
1004 .require_api = require_api_cb,
1005 .add_alias = add_alias_cb,
1007 .event_broadcast = event_broadcast_cb,
1008 .event_make = event_x2_make_cb,
1010 .legacy_call = legacy_call_x3,
1011 .legacy_call_sync = legacy_call_sync,
1013 .api_new_api = api_new_api_cb,
1014 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1015 .api_add_verb = api_add_verb_cb,
1016 .api_del_verb = api_del_verb_cb,
1017 .api_set_on_event = api_set_on_event_cb,
1018 .api_set_on_init = api_set_on_init_cb,
1019 .api_seal = api_seal_cb,
1020 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1021 .event_handler_add = event_handler_add_cb,
1022 .event_handler_del = event_handler_del_cb,
1025 .call_sync = call_sync_x3,
1027 .class_provide = class_provide_cb,
1028 .class_require = class_require_cb,
1030 .delete_api = delete_api_cb,
1031 .settings = settings_cb,
1035 static int hooked_api_set_verbs_v2_cb(
1036 struct afb_api_x3 *api,
1037 const struct afb_verb_v2 *verbs)
1039 struct afb_export *export = from_api_x3(api);
1040 int result = api_set_verbs_v2_cb(api, verbs);
1041 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
1044 static int hooked_api_set_verbs_v3_cb(
1045 struct afb_api_x3 *api,
1046 const struct afb_verb_v3 *verbs)
1048 struct afb_export *export = from_api_x3(api);
1049 int result = api_set_verbs_v3_cb(api, verbs);
1050 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
1053 static int hooked_api_add_verb_cb(
1054 struct afb_api_x3 *api,
1057 void (*callback)(struct afb_req_x2 *req),
1059 const struct afb_auth *auth,
1063 struct afb_export *export = from_api_x3(api);
1064 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
1065 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
1068 static int hooked_api_del_verb_cb(
1069 struct afb_api_x3 *api,
1073 struct afb_export *export = from_api_x3(api);
1074 int result = api_del_verb_cb(api, verb, vcbdata);
1075 return afb_hook_api_api_del_verb(export, result, verb);
1078 static int hooked_api_set_on_event_cb(
1079 struct afb_api_x3 *api,
1080 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
1082 struct afb_export *export = from_api_x3(api);
1083 int result = api_set_on_event_cb(api, onevent);
1084 return afb_hook_api_api_set_on_event(export, result);
1087 static int hooked_api_set_on_init_cb(
1088 struct afb_api_x3 *api,
1089 int (*oninit)(struct afb_api_x3 *api))
1091 struct afb_export *export = from_api_x3(api);
1092 int result = api_set_on_init_cb(api, oninit);
1093 return afb_hook_api_api_set_on_init(export, result);
1096 static void hooked_api_seal_cb(
1097 struct afb_api_x3 *api)
1099 struct afb_export *export = from_api_x3(api);
1100 afb_hook_api_api_seal(export);
1104 static int hooked_event_handler_add_cb(
1105 struct afb_api_x3 *api,
1106 const char *pattern,
1107 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1110 struct afb_export *export = from_api_x3(api);
1111 int result = event_handler_add_cb(api, pattern, callback, closure);
1112 return afb_hook_api_event_handler_add(export, result, pattern);
1115 static int hooked_event_handler_del_cb(
1116 struct afb_api_x3 *api,
1117 const char *pattern,
1120 struct afb_export *export = from_api_x3(api);
1121 int result = event_handler_del_cb(api, pattern, closure);
1122 return afb_hook_api_event_handler_del(export, result, pattern);
1125 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1127 struct afb_export *export = from_api_x3(api);
1128 int result = class_provide_cb(api, name);
1129 return afb_hook_api_class_provide(export, result, name);
1132 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1134 struct afb_export *export = from_api_x3(api);
1135 int result = class_require_cb(api, name);
1136 return afb_hook_api_class_require(export, result, name);
1139 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1141 struct afb_export *export = afb_export_addref(from_api_x3(api));
1142 int result = delete_api_cb(api);
1143 result = afb_hook_api_delete_api(export, result);
1144 afb_export_unref(export);
1148 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1150 struct afb_export *export = from_api_x3(api);
1151 struct json_object *result = settings_cb(api);
1152 result = afb_hook_api_settings(export, result);
1156 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1158 .vverbose = hooked_vverbose_cb,
1160 .get_event_loop = hooked_get_event_loop,
1161 .get_user_bus = hooked_get_user_bus,
1162 .get_system_bus = hooked_get_system_bus,
1163 .rootdir_get_fd = hooked_rootdir_get_fd,
1164 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1165 .queue_job = hooked_queue_job_cb,
1167 .require_api = hooked_require_api_cb,
1168 .add_alias = hooked_add_alias_cb,
1170 .event_broadcast = hooked_event_broadcast_cb,
1171 .event_make = hooked_event_x2_make_cb,
1173 .legacy_call = legacy_hooked_call_x3,
1174 .legacy_call_sync = legacy_hooked_call_sync,
1176 .api_new_api = hooked_api_new_api_cb,
1177 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1178 .api_add_verb = hooked_api_add_verb_cb,
1179 .api_del_verb = hooked_api_del_verb_cb,
1180 .api_set_on_event = hooked_api_set_on_event_cb,
1181 .api_set_on_init = hooked_api_set_on_init_cb,
1182 .api_seal = hooked_api_seal_cb,
1183 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1184 .event_handler_add = hooked_event_handler_add_cb,
1185 .event_handler_del = hooked_event_handler_del_cb,
1187 .call = hooked_call_x3,
1188 .call_sync = hooked_call_sync_x3,
1190 .class_provide = hooked_class_provide_cb,
1191 .class_require = hooked_class_require_cb,
1193 .delete_api = hooked_delete_api_cb,
1194 .settings = hooked_settings_cb,
1198 /******************************************************************************
1199 ******************************************************************************
1200 ******************************************************************************
1201 ******************************************************************************
1203 ******************************************************************************
1204 ******************************************************************************
1205 ******************************************************************************
1206 ******************************************************************************/
1209 * Propagates the event to the service
1211 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1213 const struct globset_handler *handler;
1214 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
1215 struct afb_export *export = from_api_x3(closure);
1218 /* hook the event before */
1219 if (export->hooksvc & afb_hook_flag_api_on_event)
1220 afb_hook_api_on_event_before(export, event, eventid, object);
1223 /* transmit to specific handlers */
1224 /* search the handler */
1225 handler = export->event_handlers ? globset_match(export->event_handlers, event) : NULL;
1227 callback = handler->callback;
1229 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1231 callback(handler->closure, event, object, to_api_x3(export));
1234 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1235 callback(handler->closure, event, object, to_api_x3(export));
1236 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1240 /* transmit to default handler */
1241 if (export->on_any_event_v3)
1242 export->on_any_event_v3(to_api_x3(export), event, object);
1243 else if (export->on_any_event_v12)
1244 export->on_any_event_v12(event, object);
1248 /* hook the event after */
1249 if (export->hooksvc & afb_hook_flag_api_on_event)
1250 afb_hook_api_on_event_after(export, event, eventid, object);
1252 json_object_put(object);
1255 /* the interface for events */
1256 static const struct afb_evt_itf evt_itf = {
1257 .broadcast = listener_of_events,
1258 .push = listener_of_events
1261 /* ensure an existing listener */
1262 static int ensure_listener(struct afb_export *export)
1264 if (!export->listener) {
1265 export->listener = afb_evt_listener_create(&evt_itf, export);
1266 if (export->listener == NULL)
1272 int afb_export_event_handler_add(
1273 struct afb_export *export,
1274 const char *pattern,
1275 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1280 /* ensure the listener */
1281 rc = ensure_listener(export);
1285 /* ensure the globset for event handling */
1286 if (!export->event_handlers) {
1287 export->event_handlers = globset_create();
1288 if (!export->event_handlers)
1292 /* add the handler */
1293 rc = globset_add(export->event_handlers, pattern, callback, closure);
1297 if (errno == EEXIST) {
1298 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1303 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1307 int afb_export_event_handler_del(
1308 struct afb_export *export,
1309 const char *pattern,
1312 if (export->event_handlers
1313 && !globset_del(export->event_handlers, pattern, closure))
1316 ERROR("[API %s] event handler %s not found", export->api.apiname, pattern);
1321 /******************************************************************************
1322 ******************************************************************************
1323 ******************************************************************************
1324 ******************************************************************************
1326 ******************************************************************************
1327 ******************************************************************************
1328 ******************************************************************************
1329 ******************************************************************************/
1331 static void set_interfaces(struct afb_export *export)
1334 export->hookditf = afb_hook_flags_api(export->api.apiname);
1335 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1336 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1338 switch (export->version) {
1339 #if WITH_LEGACY_BINDING_V1
1341 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1344 #if WITH_LEGACY_BINDING_V2
1346 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1347 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1353 export->api.itf = &api_x3_itf;
1355 switch (export->version) {
1356 #if WITH_LEGACY_BINDING_V1
1358 export->export.v1.daemon.itf = &daemon_itf;
1361 #if WITH_LEGACY_BINDING_V2
1363 export->export.v2->daemon.itf = &daemon_itf;
1364 export->export.v2->service.itf = &service_itf;
1372 static struct afb_export *create(
1373 struct afb_apiset *declare_set,
1374 struct afb_apiset *call_set,
1375 const char *apiname,
1377 enum afb_api_version version)
1379 struct afb_export *export;
1382 /* session shared with other exports */
1383 if (common_session == NULL) {
1384 common_session = afb_session_create (0);
1385 if (common_session == NULL)
1388 lenapi = strlen(apiname);
1389 export = calloc(1, sizeof *export + lenapi + (path == apiname || !path ? 0 : strlen(path)));
1393 export->refcount = 1;
1394 strcpy(export->name, apiname);
1395 export->api.apiname = export->name;
1396 if (path == apiname)
1397 export->path = export->name;
1399 export->path = strcpy(&export->name[lenapi + 1], path);
1400 export->version = version;
1401 export->state = Api_State_Pre_Init;
1402 export->session = afb_session_addref(common_session);
1403 export->declare_set = afb_apiset_addref(declare_set);
1404 export->call_set = afb_apiset_addref(call_set);
1409 struct afb_export *afb_export_addref(struct afb_export *export)
1412 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1416 void afb_export_unref(struct afb_export *export)
1418 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1419 afb_export_destroy(export);
1422 void afb_export_destroy(struct afb_export *export)
1425 if (export->event_handlers)
1426 globset_destroy(export->event_handlers);
1427 if (export->listener != NULL)
1428 afb_evt_listener_unref(export->listener);
1429 afb_session_unref(export->session);
1430 afb_apiset_unref(export->declare_set);
1431 afb_apiset_unref(export->call_set);
1432 json_object_put(export->settings);
1433 afb_export_unref(export->creator);
1434 if (export->api.apiname != export->name)
1435 free((void*)export->api.apiname);
1440 struct afb_export *afb_export_create_none_for_path(
1441 struct afb_apiset *declare_set,
1442 struct afb_apiset *call_set,
1444 int (*creator)(void*, struct afb_api_x3*),
1447 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1449 afb_export_logmask_set(export, logmask);
1450 set_interfaces(export);
1451 if (creator && creator(closure, to_api_x3(export)) < 0) {
1452 afb_export_unref(export);
1459 #if WITH_LEGACY_BINDING_V1
1460 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1461 struct afb_apiset *call_set,
1462 const char *apiname,
1463 int (*init)(struct afb_service_x1),
1464 void (*onevent)(const char*, struct json_object*),
1467 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1469 export->init.v1 = init;
1470 export->on_any_event_v12 = onevent;
1471 export->export.v1.mode = AFB_MODE_LOCAL;
1472 export->export.v1.daemon.closure = to_api_x3(export);
1473 afb_export_logmask_set(export, logmask);
1474 set_interfaces(export);
1480 #if WITH_LEGACY_BINDING_V2
1481 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1482 struct afb_apiset *call_set,
1483 const char *apiname,
1484 const struct afb_binding_v2 *binding,
1485 struct afb_binding_data_v2 *data,
1487 void (*onevent)(const char*, struct json_object*),
1490 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1492 export->init.v2 = init;
1493 export->on_any_event_v12 = onevent;
1494 export->desc.v2 = binding;
1495 export->export.v2 = data;
1496 data->daemon.closure = to_api_x3(export);
1497 data->service.closure = to_api_x3(export);
1498 afb_export_logmask_set(export, logmask);
1499 set_interfaces(export);
1505 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1506 struct afb_apiset *call_set,
1507 const char *apiname,
1508 struct afb_api_v3 *apiv3,
1509 struct afb_export* creator,
1512 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1514 export->unsealed = 1;
1515 export->desc.v3 = apiv3;
1516 export->creator = afb_export_addref(creator);
1517 afb_export_logmask_set(export, logmask);
1518 set_interfaces(export);
1523 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1525 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1528 int afb_export_rename(struct afb_export *export, const char *apiname)
1532 if (export->declared) {
1537 /* copy the name locally */
1538 name = strdup(apiname);
1544 if (export->api.apiname != export->name)
1545 free((void*)export->api.apiname);
1546 export->api.apiname = name;
1548 set_interfaces(export);
1552 const char *afb_export_apiname(const struct afb_export *export)
1554 return export->api.apiname;
1557 int afb_export_unshare_session(struct afb_export *export)
1559 if (export->session == common_session) {
1560 export->session = afb_session_create (0);
1561 if (export->session)
1562 afb_session_unref(common_session);
1564 export->session = common_session;
1571 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
1572 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1575 switch (export->version) {
1576 #if WITH_LEGACY_BINDING_V1
1579 #if WITH_LEGACY_BINDING_V2
1584 ERROR("invalid version 12 for API %s", export->api.apiname);
1589 export->on_any_event_v12 = on_event;
1590 return ensure_listener(export);
1594 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))
1597 switch (export->version) {
1598 case Api_Version_3: break;
1600 ERROR("invalid version Dyn for API %s", export->api.apiname);
1605 export->on_any_event_v3 = on_event;
1606 return ensure_listener(export);
1609 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1611 if (export->state != Api_State_Pre_Init) {
1612 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1617 export->init.v3 = oninit;
1621 #if WITH_LEGACY_BINDING_V1
1623 * Starts a new service (v1)
1625 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1627 return export->desc.v1 = regfun(&export->export.v1);
1631 int afb_export_preinit_x3(
1632 struct afb_export *export,
1633 int (*preinit)(void*, struct afb_api_x3*),
1636 return preinit(closure, to_api_x3(export));
1639 int afb_export_logmask_get(const struct afb_export *export)
1641 return export->api.logmask;
1644 void afb_export_logmask_set(struct afb_export *export, int mask)
1646 export->api.logmask = mask;
1647 switch (export->version) {
1648 #if WITH_LEGACY_BINDING_V1
1649 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1651 #if WITH_LEGACY_BINDING_V2
1652 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1657 void *afb_export_userdata_get(const struct afb_export *export)
1659 return export->api.userdata;
1662 void afb_export_userdata_set(struct afb_export *export, void *data)
1664 export->api.userdata = data;
1667 /******************************************************************************
1668 ******************************************************************************
1669 ******************************************************************************
1670 ******************************************************************************
1672 ******************************************************************************
1673 ******************************************************************************
1674 ******************************************************************************
1675 ******************************************************************************/
1680 struct afb_export *export;
1683 static void do_init(int sig, void *closure)
1686 struct init *init = closure;
1687 struct afb_export *export;
1692 export = init->export;
1693 switch (export->version) {
1694 #if WITH_LEGACY_BINDING_V1
1696 rc = export->init.v1 ? export->init.v1(
1697 (struct afb_service_x1){
1699 .itf = &hooked_service_itf,
1701 .itf = &service_itf,
1703 .closure = to_api_x3(export) }) : 0;
1706 #if WITH_LEGACY_BINDING_V2
1708 rc = export->init.v2 ? export->init.v2() : 0;
1712 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1719 init->return_code = rc;
1723 int afb_export_start(struct afb_export *export)
1729 switch (export->state) {
1733 case Api_State_Init:
1734 /* starting in progress: it is an error */
1735 ERROR("Service of API %s required started while starting", export->api.apiname);
1742 /* set event handling */
1743 #if WITH_LEGACY_BINDING_V1 || WITH_LEGACY_BINDING_V2
1744 switch (export->version) {
1745 #if WITH_LEGACY_BINDING_V1
1748 #if WITH_LEGACY_BINDING_V2
1751 if (export->on_any_event_v12) {
1752 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1761 ERROR("Can't set event handler for %s", export->api.apiname);
1767 /* Starts the service */
1768 if (export->hooksvc & afb_hook_flag_api_start)
1769 afb_hook_api_start_before(export);
1772 export->state = Api_State_Init;
1773 init.export = export;
1774 sig_monitor(0, do_init, &init);
1775 rc = init.return_code;
1776 export->state = Api_State_Run;
1779 if (export->hooksvc & afb_hook_flag_api_start)
1780 afb_hook_api_start_after(export, rc);
1784 /* initialisation error */
1785 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1792 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1794 struct afb_export *export = closure;
1796 xreq->request.api = to_api_x3(export);
1798 switch (export->version) {
1799 #if WITH_LEGACY_BINDING_V1
1801 afb_api_so_v1_process_call(export->desc.v1, xreq);
1804 #if WITH_LEGACY_BINDING_V2
1806 afb_api_so_v2_process_call(export->desc.v2, xreq);
1810 afb_api_v3_process_call(export->desc.v3, xreq);
1813 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1818 static struct json_object *api_describe_cb(void *closure)
1820 struct afb_export *export = closure;
1821 struct json_object *result;
1823 switch (export->version) {
1824 #if WITH_LEGACY_BINDING_V1
1826 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1829 #if WITH_LEGACY_BINDING_V2
1831 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1835 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1844 static int api_service_start_cb(void *closure)
1846 struct afb_export *export = closure;
1848 return afb_export_start(export);
1852 static void api_update_hooks_cb(void *closure)
1853 __attribute__((alias("set_interfaces")));
1855 void afb_export_update_hooks(struct afb_export *export)
1856 __attribute__((alias("set_interfaces")));
1859 static int api_get_logmask_cb(void *closure)
1861 struct afb_export *export = closure;
1863 return afb_export_logmask_get(export);
1866 static void api_set_logmask_cb(void *closure, int level)
1868 struct afb_export *export = closure;
1870 afb_export_logmask_set(export, level);
1873 static void api_unref_cb(void *closure)
1875 struct afb_export *export = closure;
1877 afb_export_unref(export);
1880 static struct afb_api_itf export_api_itf =
1882 .call = api_call_cb,
1883 .service_start = api_service_start_cb,
1885 .update_hooks = api_update_hooks_cb,
1887 .get_logmask = api_get_logmask_cb,
1888 .set_logmask = api_set_logmask_cb,
1889 .describe = api_describe_cb,
1890 .unref = api_unref_cb
1893 int afb_export_declare(struct afb_export *export,
1897 struct afb_api_item afb_api;
1899 if (export->declared)
1902 /* init the record structure */
1903 afb_api.closure = afb_export_addref(export);
1904 afb_api.itf = &export_api_itf;
1905 afb_api.group = noconcurrency ? export : NULL;
1907 /* records the binding */
1908 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1910 export->declared = 1;
1912 ERROR("can't declare export %s to set %s, ABORTING it!",
1913 export->api.apiname,
1914 afb_apiset_name(export->declare_set));
1915 afb_export_unref(export);
1922 void afb_export_undeclare(struct afb_export *export)
1924 if (export->declared) {
1925 export->declared = 0;
1926 afb_apiset_del(export->declare_set, export->api.apiname);
1930 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1932 return afb_evt_event_x2_add_watch(export->listener, event);
1935 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1937 return afb_evt_event_x2_remove_watch(export->listener, event);
1940 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1942 afb_xreq_process(xreq, export->call_set);
1945 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1947 afb_context_init(context, export->session, NULL);
1948 context->validated = 1;