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"
42 #include "afb-systemd.h"
45 #include "afb-export.h"
47 #include "afb-msg-json.h"
48 #include "afb-session.h"
50 #include "afb-calls.h"
54 #include "sig-monitor.h"
55 #include "wrap-json.h"
57 /*************************************************************************
59 ************************************************************************/
62 * Actually supported versions
67 #if defined(WITH_LEGACY_BINDING_V1)
75 * The states of exported APIs
85 * structure of the exported API
90 struct afb_api_x3 api;
95 /* version of the api */
102 unsigned declared: 1;
105 unsigned unsealed: 1;
111 /* session for service */
112 struct afb_session *session;
114 /* apiset the API is declared in */
115 struct afb_apiset *declare_set;
117 /* apiset for calls */
118 struct afb_apiset *call_set;
120 /* event listener for service or NULL */
121 struct afb_evt_listener *listener;
123 /* event handler list */
124 struct globset *event_handlers;
127 struct afb_export *creator;
129 /* path indication if any */
133 struct json_object *settings;
135 /* internal descriptors */
137 #if defined(WITH_LEGACY_BINDING_V1)
138 struct afb_binding_v1 *v1;
140 const struct afb_binding_v2 *v2;
141 struct afb_api_v3 *v3;
146 #if defined(WITH_LEGACY_BINDING_V1)
147 int (*v1)(struct afb_service_x1);
150 int (*v3)(struct afb_api_x3 *api);
154 void (*on_any_event_v12)(const char *event, struct json_object *object);
155 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
159 #if defined(WITH_LEGACY_BINDING_V1)
160 struct afb_binding_interface_v1 v1;
162 struct afb_binding_data_v2 *v2;
169 /*****************************************************************************/
171 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
173 return (struct afb_api_x3*)export;
176 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
178 return (struct afb_export*)api;
181 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
183 return from_api_x3(api);
186 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
188 return to_api_x3(export);
191 /******************************************************************************
192 ******************************************************************************
193 ******************************************************************************
194 ******************************************************************************
196 ******************************************************************************
197 ******************************************************************************
198 ******************************************************************************
199 ******************************************************************************/
201 static struct json_object *configuration;
203 void afb_export_set_config(struct json_object *config)
205 struct json_object *save = configuration;
206 configuration = json_object_get(config);
207 json_object_put(save);
210 static struct json_object *make_settings(struct afb_export *export)
212 struct json_object *result;
213 struct json_object *obj;
214 struct afb_export *iter;
217 /* clone the globals */
218 if (json_object_object_get_ex(configuration, "*", &obj))
219 result = wrap_json_clone(obj);
221 result = json_object_new_object();
224 if (json_object_object_get_ex(configuration, export->name, &obj))
225 wrap_json_object_add(result, obj);
227 /* add library path */
228 for (iter = export ; iter && !iter->path ; iter = iter->creator);
230 path = realpath(iter->path, NULL);
231 json_object_object_add(result, "binding-path", json_object_new_string(path));
235 export->settings = result;
239 /******************************************************************************
240 ******************************************************************************
241 ******************************************************************************
242 ******************************************************************************
244 ******************************************************************************
245 ******************************************************************************
246 ******************************************************************************
247 ******************************************************************************/
249 /**********************************************
251 **********************************************/
252 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)
255 struct afb_export *export = from_api_x3(closure);
257 if (!fmt || vasprintf(&p, fmt, args) < 0)
258 vverbose(level, file, line, function, fmt, args);
260 verbose(level, file, line, function, (verbose_is_colorized() == 0 ? "[API %s] %s" : COLOR_API "[API %s]" COLOR_DEFAULT " %s"), export->api.apiname, p);
265 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
267 vverbose_cb(closure, level, file, line, NULL, fmt, args);
270 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
272 struct afb_export *export = from_api_x3(closure);
274 /* check daemon state */
275 if (export->state == Api_State_Pre_Init) {
276 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
281 /* create the event */
282 return afb_evt_event_x2_create2(export->api.apiname, name);
285 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
287 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
288 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
291 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
295 struct afb_export *export = from_api_x3(closure);
297 /* check daemon state */
298 if (export->state == Api_State_Pre_Init) {
299 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
300 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
305 /* makes the event name */
306 plen = strlen(export->api.apiname);
308 event = alloca(nlen + plen + 2);
309 memcpy(event, export->api.apiname, plen);
311 memcpy(event + plen + 1, name, nlen + 1);
313 /* broadcast the event */
314 return afb_evt_broadcast(event, object);
317 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
319 return afb_common_rootdir_open_locale(filename, flags, locale);
322 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
324 return jobs_queue(group, timeout, callback, argument);
327 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
329 return afb_xreq_unstore(sreq);
332 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
334 struct afb_export *export = from_api_x3(closure);
336 char *iter, *end, save;
338 /* emit a warning about unexpected require in preinit */
339 if (export->state == Api_State_Pre_Init)
340 WARNING("[API %s] requiring apis in pre-init may lead to unexpected result (requires%s: %s)",
341 export->api.apiname, initialized ? " initialized" : "", name);
343 /* scan the names in a local copy */
345 iter = strdupa(name);
351 if (!save) /* at end? */
354 /* search for the end */
356 while (save && !isspace(save))
360 /* check the required api */
361 if (export->state == Api_State_Pre_Init)
362 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
364 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
373 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
375 struct afb_export *export = from_api_x3(closure);
376 if (!afb_api_is_valid_name(aliasname)) {
377 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
381 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
382 afb_export_add_alias(export, apiname, aliasname);
386 static struct afb_api_x3 *api_new_api_cb(
387 struct afb_api_x3 *closure,
391 int (*preinit)(void*, struct afb_api_x3 *),
392 void *preinit_closure)
394 struct afb_export *export = from_api_x3(closure);
395 struct afb_api_v3 *apiv3 = afb_api_v3_create(
396 export->declare_set, export->call_set,
397 api, info, noconcurrency,
398 preinit, preinit_closure, 1,
400 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
403 /**********************************************
405 **********************************************/
406 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)
408 struct afb_export *export = from_api_x3(closure);
411 vverbose_cb(closure, level, file, line, function, fmt, args);
412 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
416 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)
418 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
421 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
423 struct afb_export *export = from_api_x3(closure);
424 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
425 afb_hook_api_event_make(export, name, r);
429 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
431 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
432 struct afb_event_x1 e;
434 e.itf = event ? event->itf : NULL;
438 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
441 struct afb_export *export = from_api_x3(closure);
442 json_object_get(object);
443 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
444 r = event_broadcast_cb(closure, name, object);
445 afb_hook_api_event_broadcast_after(export, name, object, r);
446 json_object_put(object);
450 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
452 struct afb_export *export = from_api_x3(closure);
453 struct sd_event *r = afb_systemd_get_event_loop();
454 return afb_hook_api_get_event_loop(export, r);
457 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
459 struct afb_export *export = from_api_x3(closure);
460 struct sd_bus *r = afb_systemd_get_user_bus();
461 return afb_hook_api_get_user_bus(export, r);
464 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
466 struct afb_export *export = from_api_x3(closure);
467 struct sd_bus *r = afb_systemd_get_system_bus();
468 return afb_hook_api_get_system_bus(export, r);
471 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
473 struct afb_export *export = from_api_x3(closure);
474 int r = afb_common_rootdir_get_fd();
475 return afb_hook_api_rootdir_get_fd(export, r);
478 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
480 struct afb_export *export = from_api_x3(closure);
481 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
482 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
485 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
487 struct afb_export *export = from_api_x3(closure);
488 int r = queue_job_cb(closure, callback, argument, group, timeout);
489 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
492 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
494 struct afb_export *export = from_api_x3(closure);
495 afb_hook_api_legacy_unstore_req(export, sreq);
496 return legacy_unstore_req_cb(closure, sreq);
499 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
502 struct afb_export *export = from_api_x3(closure);
503 afb_hook_api_require_api(export, name, initialized);
504 result = require_api_cb(closure, name, initialized);
505 return afb_hook_api_require_api_result(export, name, initialized, result);
508 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
510 struct afb_export *export = from_api_x3(closure);
511 int result = add_alias_cb(closure, apiname, aliasname);
512 return afb_hook_api_add_alias(export, apiname, aliasname, result);
515 static struct afb_api_x3 *hooked_api_new_api_cb(
516 struct afb_api_x3 *closure,
520 int (*preinit)(void*, struct afb_api_x3 *),
521 void *preinit_closure)
523 struct afb_api_x3 *result;
524 struct afb_export *export = from_api_x3(closure);
525 afb_hook_api_new_api_before(export, api, info, noconcurrency);
526 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
527 afb_hook_api_new_api_after(export, -!result, api);
531 /**********************************************
533 **********************************************/
534 static const struct afb_daemon_itf_x1 daemon_itf = {
535 .vverbose_v1 = legacy_vverbose_v1_cb,
536 .vverbose_v2 = vverbose_cb,
537 .event_make = legacy_event_x1_make_cb,
538 .event_broadcast = event_broadcast_cb,
539 .get_event_loop = afb_systemd_get_event_loop,
540 .get_user_bus = afb_systemd_get_user_bus,
541 .get_system_bus = afb_systemd_get_system_bus,
542 .rootdir_get_fd = afb_common_rootdir_get_fd,
543 .rootdir_open_locale = rootdir_open_locale_cb,
544 .queue_job = queue_job_cb,
545 .unstore_req = legacy_unstore_req_cb,
546 .require_api = require_api_cb,
547 .add_alias = add_alias_cb,
548 .new_api = api_new_api_cb,
551 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
552 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
553 .vverbose_v2 = hooked_vverbose_cb,
554 .event_make = legacy_hooked_event_x1_make_cb,
555 .event_broadcast = hooked_event_broadcast_cb,
556 .get_event_loop = hooked_get_event_loop,
557 .get_user_bus = hooked_get_user_bus,
558 .get_system_bus = hooked_get_system_bus,
559 .rootdir_get_fd = hooked_rootdir_get_fd,
560 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
561 .queue_job = hooked_queue_job_cb,
562 .unstore_req = legacy_hooked_unstore_req_cb,
563 .require_api = hooked_require_api_cb,
564 .add_alias = hooked_add_alias_cb,
565 .new_api = hooked_api_new_api_cb,
568 /******************************************************************************
569 ******************************************************************************
570 ******************************************************************************
571 ******************************************************************************
573 ******************************************************************************
574 ******************************************************************************
575 ******************************************************************************
576 ******************************************************************************/
578 /* the common session for services sharing their session */
579 static struct afb_session *common_session;
581 /******************************************************************************
582 ******************************************************************************
583 ******************************************************************************
584 ******************************************************************************
586 ******************************************************************************
587 ******************************************************************************
588 ******************************************************************************
589 ******************************************************************************/
592 struct afb_api_x3 *apix3,
595 struct json_object *args,
596 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
599 struct afb_export *export = from_api_x3(apix3);
600 return afb_calls_call(export, api, verb, args, callback, closure);
603 static int call_sync_x3(
604 struct afb_api_x3 *apix3,
607 struct json_object *args,
608 struct json_object **object,
612 struct afb_export *export = from_api_x3(apix3);
613 return afb_calls_call_sync(export, api, verb, args, object, error, info);
616 static void legacy_call_v12(
617 struct afb_api_x3 *apix3,
620 struct json_object *args,
621 void (*callback)(void*, int, struct json_object*),
624 struct afb_export *export = from_api_x3(apix3);
625 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
628 static void legacy_call_x3(
629 struct afb_api_x3 *apix3,
632 struct json_object *args,
633 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
636 struct afb_export *export = from_api_x3(apix3);
637 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
640 static int legacy_call_sync(
641 struct afb_api_x3 *apix3,
644 struct json_object *args,
645 struct json_object **result)
647 struct afb_export *export = from_api_x3(apix3);
648 return afb_calls_legacy_call_sync(export, api, verb, args, result);
651 static void hooked_call_x3(
652 struct afb_api_x3 *apix3,
655 struct json_object *args,
656 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
659 struct afb_export *export = from_api_x3(apix3);
660 afb_calls_hooked_call(export, api, verb, args, callback, closure);
663 static int hooked_call_sync_x3(
664 struct afb_api_x3 *apix3,
667 struct json_object *args,
668 struct json_object **object,
672 struct afb_export *export = from_api_x3(apix3);
673 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
676 static void legacy_hooked_call_v12(
677 struct afb_api_x3 *apix3,
680 struct json_object *args,
681 void (*callback)(void*, int, struct json_object*),
684 struct afb_export *export = from_api_x3(apix3);
685 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
688 static void legacy_hooked_call_x3(
689 struct afb_api_x3 *apix3,
692 struct json_object *args,
693 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
696 struct afb_export *export = from_api_x3(apix3);
697 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
700 static int legacy_hooked_call_sync(
701 struct afb_api_x3 *apix3,
704 struct json_object *args,
705 struct json_object **result)
707 struct afb_export *export = from_api_x3(apix3);
708 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
711 /* the interface for services */
712 static const struct afb_service_itf_x1 service_itf = {
713 .call = legacy_call_v12,
714 .call_sync = legacy_call_sync
717 /* the interface for services */
718 static const struct afb_service_itf_x1 hooked_service_itf = {
719 .call = legacy_hooked_call_v12,
720 .call_sync = legacy_hooked_call_sync
723 /******************************************************************************
724 ******************************************************************************
725 ******************************************************************************
726 ******************************************************************************
728 ******************************************************************************
729 ******************************************************************************
730 ******************************************************************************
731 ******************************************************************************/
733 static int api_set_verbs_v2_cb(
734 struct afb_api_x3 *api,
735 const struct afb_verb_v2 *verbs)
737 struct afb_export *export = from_api_x3(api);
739 if (export->unsealed) {
740 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
748 static int api_set_verbs_v3_cb(
749 struct afb_api_x3 *api,
750 const struct afb_verb_v3 *verbs)
752 struct afb_export *export = from_api_x3(api);
754 if (!export->unsealed) {
759 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
763 static int api_add_verb_cb(
764 struct afb_api_x3 *api,
767 void (*callback)(struct afb_req_x2 *req),
769 const struct afb_auth *auth,
773 struct afb_export *export = from_api_x3(api);
775 if (!export->unsealed) {
780 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
783 static int api_del_verb_cb(
784 struct afb_api_x3 *api,
788 struct afb_export *export = from_api_x3(api);
790 if (!export->unsealed) {
795 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
798 static int api_set_on_event_cb(
799 struct afb_api_x3 *api,
800 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
802 struct afb_export *export = from_api_x3(api);
803 return afb_export_handle_events_v3(export, onevent);
806 static int api_set_on_init_cb(
807 struct afb_api_x3 *api,
808 int (*oninit)(struct afb_api_x3 *api))
810 struct afb_export *export = from_api_x3(api);
812 return afb_export_handle_init_v3(export, oninit);
815 static void api_seal_cb(
816 struct afb_api_x3 *api)
818 struct afb_export *export = from_api_x3(api);
820 export->unsealed = 0;
823 static int event_handler_add_cb(
824 struct afb_api_x3 *api,
826 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
829 struct afb_export *export = from_api_x3(api);
831 return afb_export_event_handler_add(export, pattern, callback, closure);
834 static int event_handler_del_cb(
835 struct afb_api_x3 *api,
839 struct afb_export *export = from_api_x3(api);
841 return afb_export_event_handler_del(export, pattern, closure);
844 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
846 struct afb_export *export = from_api_x3(api);
849 char *iter, *end, save;
851 iter = strdupa(name);
857 if (!save) /* at end? */
860 /* search for the end */
862 while (save && !isspace(save))
866 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
875 static int class_require_cb(struct afb_api_x3 *api, const char *name)
877 struct afb_export *export = from_api_x3(api);
880 char *iter, *end, save;
882 iter = strdupa(name);
888 if (!save) /* at end? */
891 /* search for the end */
893 while (save && !isspace(save))
897 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
906 static int delete_api_cb(struct afb_api_x3 *api)
908 struct afb_export *export = from_api_x3(api);
910 if (!export->unsealed) {
915 afb_export_undeclare(export);
916 afb_export_unref(export);
920 static struct json_object *settings_cb(struct afb_api_x3 *api)
922 struct afb_export *export = from_api_x3(api);
923 struct json_object *result = export->settings;
925 result = make_settings(export);
929 static int hooked_api_set_verbs_v2_cb(
930 struct afb_api_x3 *api,
931 const struct afb_verb_v2 *verbs)
933 struct afb_export *export = from_api_x3(api);
934 int result = api_set_verbs_v2_cb(api, verbs);
935 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
938 static int hooked_api_set_verbs_v3_cb(
939 struct afb_api_x3 *api,
940 const struct afb_verb_v3 *verbs)
942 struct afb_export *export = from_api_x3(api);
943 int result = api_set_verbs_v3_cb(api, verbs);
944 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
947 static int hooked_api_add_verb_cb(
948 struct afb_api_x3 *api,
951 void (*callback)(struct afb_req_x2 *req),
953 const struct afb_auth *auth,
957 struct afb_export *export = from_api_x3(api);
958 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
959 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
962 static int hooked_api_del_verb_cb(
963 struct afb_api_x3 *api,
967 struct afb_export *export = from_api_x3(api);
968 int result = api_del_verb_cb(api, verb, vcbdata);
969 return afb_hook_api_api_del_verb(export, result, verb);
972 static int hooked_api_set_on_event_cb(
973 struct afb_api_x3 *api,
974 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
976 struct afb_export *export = from_api_x3(api);
977 int result = api_set_on_event_cb(api, onevent);
978 return afb_hook_api_api_set_on_event(export, result);
981 static int hooked_api_set_on_init_cb(
982 struct afb_api_x3 *api,
983 int (*oninit)(struct afb_api_x3 *api))
985 struct afb_export *export = from_api_x3(api);
986 int result = api_set_on_init_cb(api, oninit);
987 return afb_hook_api_api_set_on_init(export, result);
990 static void hooked_api_seal_cb(
991 struct afb_api_x3 *api)
993 struct afb_export *export = from_api_x3(api);
994 afb_hook_api_api_seal(export);
998 static int hooked_event_handler_add_cb(
999 struct afb_api_x3 *api,
1000 const char *pattern,
1001 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1004 struct afb_export *export = from_api_x3(api);
1005 int result = event_handler_add_cb(api, pattern, callback, closure);
1006 return afb_hook_api_event_handler_add(export, result, pattern);
1009 static int hooked_event_handler_del_cb(
1010 struct afb_api_x3 *api,
1011 const char *pattern,
1014 struct afb_export *export = from_api_x3(api);
1015 int result = event_handler_del_cb(api, pattern, closure);
1016 return afb_hook_api_event_handler_del(export, result, pattern);
1019 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1021 struct afb_export *export = from_api_x3(api);
1022 int result = class_provide_cb(api, name);
1023 return afb_hook_api_class_provide(export, result, name);
1026 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1028 struct afb_export *export = from_api_x3(api);
1029 int result = class_require_cb(api, name);
1030 return afb_hook_api_class_require(export, result, name);
1033 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1035 struct afb_export *export = afb_export_addref(from_api_x3(api));
1036 int result = delete_api_cb(api);
1037 result = afb_hook_api_delete_api(export, result);
1038 afb_export_unref(export);
1042 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1044 struct afb_export *export = from_api_x3(api);
1045 struct json_object *result = settings_cb(api);
1046 result = afb_hook_api_settings(export, result);
1050 static const struct afb_api_x3_itf api_x3_itf = {
1052 .vverbose = (void*)vverbose_cb,
1054 .get_event_loop = afb_systemd_get_event_loop,
1055 .get_user_bus = afb_systemd_get_user_bus,
1056 .get_system_bus = afb_systemd_get_system_bus,
1057 .rootdir_get_fd = afb_common_rootdir_get_fd,
1058 .rootdir_open_locale = rootdir_open_locale_cb,
1059 .queue_job = queue_job_cb,
1061 .require_api = require_api_cb,
1062 .add_alias = add_alias_cb,
1064 .event_broadcast = event_broadcast_cb,
1065 .event_make = event_x2_make_cb,
1067 .legacy_call = legacy_call_x3,
1068 .legacy_call_sync = legacy_call_sync,
1070 .api_new_api = api_new_api_cb,
1071 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1072 .api_add_verb = api_add_verb_cb,
1073 .api_del_verb = api_del_verb_cb,
1074 .api_set_on_event = api_set_on_event_cb,
1075 .api_set_on_init = api_set_on_init_cb,
1076 .api_seal = api_seal_cb,
1077 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1078 .event_handler_add = event_handler_add_cb,
1079 .event_handler_del = event_handler_del_cb,
1082 .call_sync = call_sync_x3,
1084 .class_provide = class_provide_cb,
1085 .class_require = class_require_cb,
1087 .delete_api = delete_api_cb,
1088 .settings = settings_cb,
1091 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1093 .vverbose = hooked_vverbose_cb,
1095 .get_event_loop = hooked_get_event_loop,
1096 .get_user_bus = hooked_get_user_bus,
1097 .get_system_bus = hooked_get_system_bus,
1098 .rootdir_get_fd = hooked_rootdir_get_fd,
1099 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1100 .queue_job = hooked_queue_job_cb,
1102 .require_api = hooked_require_api_cb,
1103 .add_alias = hooked_add_alias_cb,
1105 .event_broadcast = hooked_event_broadcast_cb,
1106 .event_make = hooked_event_x2_make_cb,
1108 .legacy_call = legacy_hooked_call_x3,
1109 .legacy_call_sync = legacy_hooked_call_sync,
1111 .api_new_api = hooked_api_new_api_cb,
1112 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1113 .api_add_verb = hooked_api_add_verb_cb,
1114 .api_del_verb = hooked_api_del_verb_cb,
1115 .api_set_on_event = hooked_api_set_on_event_cb,
1116 .api_set_on_init = hooked_api_set_on_init_cb,
1117 .api_seal = hooked_api_seal_cb,
1118 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1119 .event_handler_add = hooked_event_handler_add_cb,
1120 .event_handler_del = hooked_event_handler_del_cb,
1122 .call = hooked_call_x3,
1123 .call_sync = hooked_call_sync_x3,
1125 .class_provide = hooked_class_provide_cb,
1126 .class_require = hooked_class_require_cb,
1128 .delete_api = hooked_delete_api_cb,
1129 .settings = hooked_settings_cb,
1132 /******************************************************************************
1133 ******************************************************************************
1134 ******************************************************************************
1135 ******************************************************************************
1137 ******************************************************************************
1138 ******************************************************************************
1139 ******************************************************************************
1140 ******************************************************************************/
1143 * Propagates the event to the service
1145 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1147 const struct globset_handler *handler;
1148 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
1149 struct afb_export *export = from_api_x3(closure);
1151 /* hook the event before */
1152 if (export->hooksvc & afb_hook_flag_api_on_event)
1153 afb_hook_api_on_event_before(export, event, eventid, object);
1155 /* transmit to specific handlers */
1156 /* search the handler */
1157 handler = export->event_handlers ? globset_match(export->event_handlers, event) : NULL;
1159 callback = handler->callback;
1160 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1161 callback(handler->closure, event, object, to_api_x3(export));
1163 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1164 callback(handler->closure, event, object, to_api_x3(export));
1165 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1168 /* transmit to default handler */
1169 if (export->on_any_event_v3)
1170 export->on_any_event_v3(to_api_x3(export), event, object);
1171 else if (export->on_any_event_v12)
1172 export->on_any_event_v12(event, object);
1175 /* hook the event after */
1176 if (export->hooksvc & afb_hook_flag_api_on_event)
1177 afb_hook_api_on_event_after(export, event, eventid, object);
1178 json_object_put(object);
1181 /* the interface for events */
1182 static const struct afb_evt_itf evt_itf = {
1183 .broadcast = listener_of_events,
1184 .push = listener_of_events
1187 /* ensure an existing listener */
1188 static int ensure_listener(struct afb_export *export)
1190 if (!export->listener) {
1191 export->listener = afb_evt_listener_create(&evt_itf, export);
1192 if (export->listener == NULL)
1198 int afb_export_event_handler_add(
1199 struct afb_export *export,
1200 const char *pattern,
1201 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1206 /* ensure the listener */
1207 rc = ensure_listener(export);
1211 /* ensure the globset for event handling */
1212 if (!export->event_handlers) {
1213 export->event_handlers = globset_create();
1214 if (!export->event_handlers)
1218 /* add the handler */
1219 rc = globset_add(export->event_handlers, pattern, callback, closure);
1223 if (errno == EEXIST) {
1224 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1229 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1233 int afb_export_event_handler_del(
1234 struct afb_export *export,
1235 const char *pattern,
1238 if (export->event_handlers
1239 && !globset_del(export->event_handlers, pattern, closure))
1242 ERROR("[API %s] event handler %s not found", export->api.apiname, pattern);
1247 /******************************************************************************
1248 ******************************************************************************
1249 ******************************************************************************
1250 ******************************************************************************
1252 ******************************************************************************
1253 ******************************************************************************
1254 ******************************************************************************
1255 ******************************************************************************/
1257 static struct afb_export *create(
1258 struct afb_apiset *declare_set,
1259 struct afb_apiset *call_set,
1260 const char *apiname,
1262 enum afb_api_version version)
1264 struct afb_export *export;
1267 /* session shared with other exports */
1268 if (common_session == NULL) {
1269 common_session = afb_session_create (0);
1270 if (common_session == NULL)
1273 lenapi = strlen(apiname);
1274 export = calloc(1, sizeof *export + lenapi + (path == apiname || !path ? 0 : strlen(path)));
1278 export->refcount = 1;
1279 strcpy(export->name, apiname);
1280 export->api.apiname = export->name;
1281 if (path == apiname)
1282 export->path = export->name;
1284 export->path = strcpy(&export->name[lenapi + 1], path);
1285 export->version = version;
1286 export->state = Api_State_Pre_Init;
1287 export->session = afb_session_addref(common_session);
1288 export->declare_set = afb_apiset_addref(declare_set);
1289 export->call_set = afb_apiset_addref(call_set);
1294 struct afb_export *afb_export_addref(struct afb_export *export)
1297 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1301 void afb_export_unref(struct afb_export *export)
1303 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1304 afb_export_destroy(export);
1307 void afb_export_destroy(struct afb_export *export)
1310 if (export->event_handlers)
1311 globset_destroy(export->event_handlers);
1312 if (export->listener != NULL)
1313 afb_evt_listener_unref(export->listener);
1314 afb_session_unref(export->session);
1315 afb_apiset_unref(export->declare_set);
1316 afb_apiset_unref(export->call_set);
1317 json_object_put(export->settings);
1318 afb_export_unref(export->creator);
1319 if (export->api.apiname != export->name)
1320 free((void*)export->api.apiname);
1325 struct afb_export *afb_export_create_none_for_path(
1326 struct afb_apiset *declare_set,
1327 struct afb_apiset *call_set,
1329 int (*creator)(void*, struct afb_api_x3*),
1332 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1334 afb_export_logmask_set(export, logmask);
1335 afb_export_update_hooks(export);
1336 if (creator && creator(closure, to_api_x3(export)) < 0) {
1337 afb_export_unref(export);
1344 #if defined(WITH_LEGACY_BINDING_V1)
1345 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1346 struct afb_apiset *call_set,
1347 const char *apiname,
1348 int (*init)(struct afb_service_x1),
1349 void (*onevent)(const char*, struct json_object*),
1352 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1354 export->init.v1 = init;
1355 export->on_any_event_v12 = onevent;
1356 export->export.v1.mode = AFB_MODE_LOCAL;
1357 export->export.v1.daemon.closure = to_api_x3(export);
1358 afb_export_logmask_set(export, logmask);
1359 afb_export_update_hooks(export);
1365 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1366 struct afb_apiset *call_set,
1367 const char *apiname,
1368 const struct afb_binding_v2 *binding,
1369 struct afb_binding_data_v2 *data,
1371 void (*onevent)(const char*, struct json_object*),
1374 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1376 export->init.v2 = init;
1377 export->on_any_event_v12 = onevent;
1378 export->desc.v2 = binding;
1379 export->export.v2 = data;
1380 data->daemon.closure = to_api_x3(export);
1381 data->service.closure = to_api_x3(export);
1382 afb_export_logmask_set(export, logmask);
1383 afb_export_update_hooks(export);
1388 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1389 struct afb_apiset *call_set,
1390 const char *apiname,
1391 struct afb_api_v3 *apiv3,
1392 struct afb_export* creator,
1395 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1397 export->unsealed = 1;
1398 export->desc.v3 = apiv3;
1399 export->creator = afb_export_addref(creator);
1400 afb_export_logmask_set(export, logmask);
1401 afb_export_update_hooks(export);
1406 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1408 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1411 int afb_export_rename(struct afb_export *export, const char *apiname)
1415 if (export->declared) {
1420 /* copy the name locally */
1421 name = strdup(apiname);
1427 if (export->api.apiname != export->name)
1428 free((void*)export->api.apiname);
1429 export->api.apiname = name;
1431 afb_export_update_hooks(export);
1435 const char *afb_export_apiname(const struct afb_export *export)
1437 return export->api.apiname;
1440 void afb_export_update_hooks(struct afb_export *export)
1442 export->hookditf = afb_hook_flags_api(export->api.apiname);
1443 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1444 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1446 switch (export->version) {
1447 #if defined(WITH_LEGACY_BINDING_V1)
1449 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1453 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1454 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1459 int afb_export_unshare_session(struct afb_export *export)
1461 if (export->session == common_session) {
1462 export->session = afb_session_create (0);
1463 if (export->session)
1464 afb_session_unref(common_session);
1466 export->session = common_session;
1473 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1476 switch (export->version) {
1477 #if defined(WITH_LEGACY_BINDING_V1)
1483 ERROR("invalid version 12 for API %s", export->api.apiname);
1488 export->on_any_event_v12 = on_event;
1489 return ensure_listener(export);
1492 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))
1495 switch (export->version) {
1496 case Api_Version_3: break;
1498 ERROR("invalid version Dyn for API %s", export->api.apiname);
1503 export->on_any_event_v3 = on_event;
1504 return ensure_listener(export);
1507 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1509 if (export->state != Api_State_Pre_Init) {
1510 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1515 export->init.v3 = oninit;
1519 #if defined(WITH_LEGACY_BINDING_V1)
1521 * Starts a new service (v1)
1523 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1525 return export->desc.v1 = regfun(&export->export.v1);
1529 int afb_export_preinit_x3(
1530 struct afb_export *export,
1531 int (*preinit)(void*, struct afb_api_x3*),
1534 return preinit(closure, to_api_x3(export));
1537 int afb_export_logmask_get(const struct afb_export *export)
1539 return export->api.logmask;
1542 void afb_export_logmask_set(struct afb_export *export, int mask)
1544 export->api.logmask = mask;
1545 switch (export->version) {
1546 #if defined(WITH_LEGACY_BINDING_V1)
1547 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1549 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1553 void *afb_export_userdata_get(const struct afb_export *export)
1555 return export->api.userdata;
1558 void afb_export_userdata_set(struct afb_export *export, void *data)
1560 export->api.userdata = data;
1563 /******************************************************************************
1564 ******************************************************************************
1565 ******************************************************************************
1566 ******************************************************************************
1568 ******************************************************************************
1569 ******************************************************************************
1570 ******************************************************************************
1571 ******************************************************************************/
1576 struct afb_export *export;
1579 static void do_init(int sig, void *closure)
1582 struct init *init = closure;
1583 struct afb_export *export;
1588 export = init->export;
1589 switch (export->version) {
1590 #if defined(WITH_LEGACY_BINDING_V1)
1592 rc = export->init.v1 ? export->init.v1(
1593 (struct afb_service_x1){
1594 .itf = &hooked_service_itf,
1595 .closure = to_api_x3(export) }) : 0;
1599 rc = export->init.v2 ? export->init.v2() : 0;
1602 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1609 init->return_code = rc;
1613 int afb_export_start(struct afb_export *export)
1619 switch (export->state) {
1623 case Api_State_Init:
1624 /* starting in progress: it is an error */
1625 ERROR("Service of API %s required started while starting", export->api.apiname);
1632 /* set event handling */
1633 switch (export->version) {
1634 #if defined(WITH_LEGACY_BINDING_V1)
1638 if (export->on_any_event_v12) {
1639 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1648 ERROR("Can't set event handler for %s", export->api.apiname);
1652 /* Starts the service */
1653 if (export->hooksvc & afb_hook_flag_api_start)
1654 afb_hook_api_start_before(export);
1656 export->state = Api_State_Init;
1657 init.export = export;
1658 sig_monitor(0, do_init, &init);
1659 rc = init.return_code;
1660 export->state = Api_State_Run;
1662 if (export->hooksvc & afb_hook_flag_api_start)
1663 afb_hook_api_start_after(export, rc);
1666 /* initialisation error */
1667 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1674 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1676 struct afb_export *export = closure;
1678 xreq->request.api = to_api_x3(export);
1680 switch (export->version) {
1681 #if defined(WITH_LEGACY_BINDING_V1)
1683 afb_api_so_v1_process_call(export->desc.v1, xreq);
1687 afb_api_so_v2_process_call(export->desc.v2, xreq);
1690 afb_api_v3_process_call(export->desc.v3, xreq);
1693 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1698 static struct json_object *api_describe_cb(void *closure)
1700 struct afb_export *export = closure;
1701 struct json_object *result;
1703 switch (export->version) {
1704 #if defined(WITH_LEGACY_BINDING_V1)
1706 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1710 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1713 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1722 static int api_service_start_cb(void *closure)
1724 struct afb_export *export = closure;
1726 return afb_export_start(export);
1729 static void api_update_hooks_cb(void *closure)
1731 struct afb_export *export = closure;
1733 afb_export_update_hooks(export);
1736 static int api_get_logmask_cb(void *closure)
1738 struct afb_export *export = closure;
1740 return afb_export_logmask_get(export);
1743 static void api_set_logmask_cb(void *closure, int level)
1745 struct afb_export *export = closure;
1747 afb_export_logmask_set(export, level);
1750 static void api_unref_cb(void *closure)
1752 struct afb_export *export = closure;
1754 afb_export_unref(export);
1757 static struct afb_api_itf export_api_itf =
1759 .call = api_call_cb,
1760 .service_start = api_service_start_cb,
1761 .update_hooks = api_update_hooks_cb,
1762 .get_logmask = api_get_logmask_cb,
1763 .set_logmask = api_set_logmask_cb,
1764 .describe = api_describe_cb,
1765 .unref = api_unref_cb
1768 int afb_export_declare(struct afb_export *export,
1772 struct afb_api_item afb_api;
1774 if (export->declared)
1777 /* init the record structure */
1778 afb_api.closure = afb_export_addref(export);
1779 afb_api.itf = &export_api_itf;
1780 afb_api.group = noconcurrency ? export : NULL;
1782 /* records the binding */
1783 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1785 export->declared = 1;
1787 ERROR("can't declare export %s to set %s, ABORTING it!",
1788 export->api.apiname,
1789 afb_apiset_name(export->declare_set));
1790 afb_export_unref(export);
1797 void afb_export_undeclare(struct afb_export *export)
1799 if (export->declared) {
1800 export->declared = 0;
1801 afb_apiset_del(export->declare_set, export->api.apiname);
1805 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1807 return afb_evt_event_x2_add_watch(export->listener, event);
1810 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1812 return afb_evt_event_x2_remove_watch(export->listener, event);
1815 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1817 afb_xreq_process(xreq, export->call_set);
1820 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1822 afb_context_init(context, export->session, NULL);
1823 context->validated = 1;