2 * Copyright (C) 2016, 2017, 2018 "IoT.bzh"
3 * Author: José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
26 #include <json-c/json.h>
27 #if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
28 #define JSON_C_TO_STRING_NOSLASHESCAPE 0
31 #define AFB_BINDING_VERSION 0
32 #include <afb/afb-binding.h>
35 #include "afb-apiset.h"
36 #if defined(WITH_LEGACY_BINDING_V1)
37 #include "afb-api-so-v1.h"
39 #include "afb-api-so-v2.h"
40 #include "afb-api-v3.h"
41 #include "afb-common.h"
42 #include "afb-systemd.h"
45 #include "afb-export.h"
47 #include "afb-msg-json.h"
48 #include "afb-session.h"
50 #include "afb-calls.h"
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 static void listener_of_pushed_events(void *closure, const char *event, int eventid, struct json_object *object)
1183 listener_of_events(closure, event, eventid, object);
1186 static void listener_of_broadcasted_events(void *closure, const char *event, struct json_object *object, const uuid_binary_t uuid, uint8_t hop)
1188 listener_of_events(closure, event, 0, object);
1191 /* the interface for events */
1192 static const struct afb_evt_itf evt_itf = {
1193 .broadcast = listener_of_broadcasted_events,
1194 .push = listener_of_pushed_events
1197 /* ensure an existing listener */
1198 static int ensure_listener(struct afb_export *export)
1200 if (!export->listener) {
1201 export->listener = afb_evt_listener_create(&evt_itf, export);
1202 if (export->listener == NULL)
1208 int afb_export_event_handler_add(
1209 struct afb_export *export,
1210 const char *pattern,
1211 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1216 /* ensure the listener */
1217 rc = ensure_listener(export);
1221 /* ensure the globset for event handling */
1222 if (!export->event_handlers) {
1223 export->event_handlers = globset_create();
1224 if (!export->event_handlers)
1228 /* add the handler */
1229 rc = globset_add(export->event_handlers, pattern, callback, closure);
1233 if (errno == EEXIST) {
1234 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1239 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1243 int afb_export_event_handler_del(
1244 struct afb_export *export,
1245 const char *pattern,
1248 if (export->event_handlers
1249 && !globset_del(export->event_handlers, pattern, closure))
1252 ERROR("[API %s] event handler %s not found", export->api.apiname, pattern);
1257 /******************************************************************************
1258 ******************************************************************************
1259 ******************************************************************************
1260 ******************************************************************************
1262 ******************************************************************************
1263 ******************************************************************************
1264 ******************************************************************************
1265 ******************************************************************************/
1267 static struct afb_export *create(
1268 struct afb_apiset *declare_set,
1269 struct afb_apiset *call_set,
1270 const char *apiname,
1272 enum afb_api_version version)
1274 struct afb_export *export;
1277 /* session shared with other exports */
1278 if (common_session == NULL) {
1279 common_session = afb_session_create (0);
1280 if (common_session == NULL)
1283 lenapi = strlen(apiname);
1284 export = calloc(1, sizeof *export + 1 + lenapi + (path == apiname || !path ? 0 : 1 + strlen(path)));
1288 export->refcount = 1;
1289 strcpy(export->name, apiname);
1290 export->api.apiname = export->name;
1291 if (path == apiname)
1292 export->path = export->name;
1294 export->path = strcpy(&export->name[lenapi + 1], path);
1295 export->version = version;
1296 export->state = Api_State_Pre_Init;
1297 export->session = afb_session_addref(common_session);
1298 export->declare_set = afb_apiset_addref(declare_set);
1299 export->call_set = afb_apiset_addref(call_set);
1304 struct afb_export *afb_export_addref(struct afb_export *export)
1307 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1311 void afb_export_unref(struct afb_export *export)
1313 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1314 afb_export_destroy(export);
1317 void afb_export_destroy(struct afb_export *export)
1320 if (export->event_handlers)
1321 globset_destroy(export->event_handlers);
1322 if (export->listener != NULL)
1323 afb_evt_listener_unref(export->listener);
1324 afb_session_unref(export->session);
1325 afb_apiset_unref(export->declare_set);
1326 afb_apiset_unref(export->call_set);
1327 json_object_put(export->settings);
1328 afb_export_unref(export->creator);
1329 if (export->api.apiname != export->name)
1330 free((void*)export->api.apiname);
1335 struct afb_export *afb_export_create_none_for_path(
1336 struct afb_apiset *declare_set,
1337 struct afb_apiset *call_set,
1339 int (*creator)(void*, struct afb_api_x3*),
1342 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1344 afb_export_logmask_set(export, logmask);
1345 afb_export_update_hooks(export);
1346 if (creator && creator(closure, to_api_x3(export)) < 0) {
1347 afb_export_unref(export);
1354 #if defined(WITH_LEGACY_BINDING_V1)
1355 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1356 struct afb_apiset *call_set,
1357 const char *apiname,
1358 int (*init)(struct afb_service_x1),
1359 void (*onevent)(const char*, struct json_object*),
1362 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1364 export->init.v1 = init;
1365 export->on_any_event_v12 = onevent;
1366 export->export.v1.mode = AFB_MODE_LOCAL;
1367 export->export.v1.daemon.closure = to_api_x3(export);
1368 afb_export_logmask_set(export, logmask);
1369 afb_export_update_hooks(export);
1375 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1376 struct afb_apiset *call_set,
1377 const char *apiname,
1378 const struct afb_binding_v2 *binding,
1379 struct afb_binding_data_v2 *data,
1381 void (*onevent)(const char*, struct json_object*),
1384 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1386 export->init.v2 = init;
1387 export->on_any_event_v12 = onevent;
1388 export->desc.v2 = binding;
1389 export->export.v2 = data;
1390 data->daemon.closure = to_api_x3(export);
1391 data->service.closure = to_api_x3(export);
1392 afb_export_logmask_set(export, logmask);
1393 afb_export_update_hooks(export);
1398 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1399 struct afb_apiset *call_set,
1400 const char *apiname,
1401 struct afb_api_v3 *apiv3,
1402 struct afb_export* creator,
1405 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1407 export->unsealed = 1;
1408 export->desc.v3 = apiv3;
1409 export->creator = afb_export_addref(creator);
1410 afb_export_logmask_set(export, logmask);
1411 afb_export_update_hooks(export);
1416 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1418 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1421 int afb_export_rename(struct afb_export *export, const char *apiname)
1425 if (export->declared) {
1430 /* copy the name locally */
1431 name = strdup(apiname);
1437 if (export->api.apiname != export->name)
1438 free((void*)export->api.apiname);
1439 export->api.apiname = name;
1441 afb_export_update_hooks(export);
1445 const char *afb_export_apiname(const struct afb_export *export)
1447 return export->api.apiname;
1450 void afb_export_update_hooks(struct afb_export *export)
1452 export->hookditf = afb_hook_flags_api(export->api.apiname);
1453 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1454 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1456 switch (export->version) {
1457 #if defined(WITH_LEGACY_BINDING_V1)
1459 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1463 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1464 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1469 int afb_export_unshare_session(struct afb_export *export)
1471 if (export->session == common_session) {
1472 export->session = afb_session_create (0);
1473 if (export->session)
1474 afb_session_unref(common_session);
1476 export->session = common_session;
1483 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1486 switch (export->version) {
1487 #if defined(WITH_LEGACY_BINDING_V1)
1493 ERROR("invalid version 12 for API %s", export->api.apiname);
1498 export->on_any_event_v12 = on_event;
1499 return ensure_listener(export);
1502 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))
1505 switch (export->version) {
1506 case Api_Version_3: break;
1508 ERROR("invalid version Dyn for API %s", export->api.apiname);
1513 export->on_any_event_v3 = on_event;
1514 return ensure_listener(export);
1517 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1519 if (export->state != Api_State_Pre_Init) {
1520 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1525 export->init.v3 = oninit;
1529 #if defined(WITH_LEGACY_BINDING_V1)
1531 * Starts a new service (v1)
1533 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1535 return export->desc.v1 = regfun(&export->export.v1);
1539 int afb_export_preinit_x3(
1540 struct afb_export *export,
1541 int (*preinit)(void*, struct afb_api_x3*),
1544 return preinit(closure, to_api_x3(export));
1547 int afb_export_logmask_get(const struct afb_export *export)
1549 return export->api.logmask;
1552 void afb_export_logmask_set(struct afb_export *export, int mask)
1554 export->api.logmask = mask;
1555 switch (export->version) {
1556 #if defined(WITH_LEGACY_BINDING_V1)
1557 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1559 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1563 void *afb_export_userdata_get(const struct afb_export *export)
1565 return export->api.userdata;
1568 void afb_export_userdata_set(struct afb_export *export, void *data)
1570 export->api.userdata = data;
1573 /******************************************************************************
1574 ******************************************************************************
1575 ******************************************************************************
1576 ******************************************************************************
1578 ******************************************************************************
1579 ******************************************************************************
1580 ******************************************************************************
1581 ******************************************************************************/
1586 struct afb_export *export;
1589 static void do_init(int sig, void *closure)
1592 struct init *init = closure;
1593 struct afb_export *export;
1598 export = init->export;
1599 switch (export->version) {
1600 #if defined(WITH_LEGACY_BINDING_V1)
1602 rc = export->init.v1 ? export->init.v1(
1603 (struct afb_service_x1){
1604 .itf = &hooked_service_itf,
1605 .closure = to_api_x3(export) }) : 0;
1609 rc = export->init.v2 ? export->init.v2() : 0;
1612 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1619 init->return_code = rc;
1623 int afb_export_start(struct afb_export *export)
1629 switch (export->state) {
1633 case Api_State_Init:
1634 /* starting in progress: it is an error */
1635 ERROR("Service of API %s required started while starting", export->api.apiname);
1642 /* set event handling */
1643 switch (export->version) {
1644 #if defined(WITH_LEGACY_BINDING_V1)
1648 if (export->on_any_event_v12) {
1649 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1658 ERROR("Can't set event handler for %s", export->api.apiname);
1662 /* Starts the service */
1663 if (export->hooksvc & afb_hook_flag_api_start)
1664 afb_hook_api_start_before(export);
1666 export->state = Api_State_Init;
1667 init.export = export;
1668 sig_monitor(0, do_init, &init);
1669 rc = init.return_code;
1670 export->state = Api_State_Run;
1672 if (export->hooksvc & afb_hook_flag_api_start)
1673 afb_hook_api_start_after(export, rc);
1676 /* initialisation error */
1677 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1684 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1686 struct afb_export *export = closure;
1688 xreq->request.api = to_api_x3(export);
1690 switch (export->version) {
1691 #if defined(WITH_LEGACY_BINDING_V1)
1693 afb_api_so_v1_process_call(export->desc.v1, xreq);
1697 afb_api_so_v2_process_call(export->desc.v2, xreq);
1700 afb_api_v3_process_call(export->desc.v3, xreq);
1703 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1708 static struct json_object *api_describe_cb(void *closure)
1710 struct afb_export *export = closure;
1711 struct json_object *result;
1713 switch (export->version) {
1714 #if defined(WITH_LEGACY_BINDING_V1)
1716 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1720 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1723 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1732 static int api_service_start_cb(void *closure)
1734 struct afb_export *export = closure;
1736 return afb_export_start(export);
1739 static void api_update_hooks_cb(void *closure)
1741 struct afb_export *export = closure;
1743 afb_export_update_hooks(export);
1746 static int api_get_logmask_cb(void *closure)
1748 struct afb_export *export = closure;
1750 return afb_export_logmask_get(export);
1753 static void api_set_logmask_cb(void *closure, int level)
1755 struct afb_export *export = closure;
1757 afb_export_logmask_set(export, level);
1760 static void api_unref_cb(void *closure)
1762 struct afb_export *export = closure;
1764 afb_export_unref(export);
1767 static struct afb_api_itf export_api_itf =
1769 .call = api_call_cb,
1770 .service_start = api_service_start_cb,
1771 .update_hooks = api_update_hooks_cb,
1772 .get_logmask = api_get_logmask_cb,
1773 .set_logmask = api_set_logmask_cb,
1774 .describe = api_describe_cb,
1775 .unref = api_unref_cb
1778 int afb_export_declare(struct afb_export *export,
1782 struct afb_api_item afb_api;
1784 if (export->declared)
1787 /* init the record structure */
1788 afb_api.closure = afb_export_addref(export);
1789 afb_api.itf = &export_api_itf;
1790 afb_api.group = noconcurrency ? export : NULL;
1792 /* records the binding */
1793 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1795 export->declared = 1;
1797 ERROR("can't declare export %s to set %s, ABORTING it!",
1798 export->api.apiname,
1799 afb_apiset_name(export->declare_set));
1800 afb_export_unref(export);
1807 void afb_export_undeclare(struct afb_export *export)
1809 if (export->declared) {
1810 export->declared = 0;
1811 afb_apiset_del(export->declare_set, export->api.apiname);
1815 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1817 return afb_evt_event_x2_add_watch(export->listener, event);
1820 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1822 return afb_evt_event_x2_remove_watch(export->listener, event);
1825 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1827 afb_xreq_process(xreq, export->call_set);
1830 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1832 afb_context_init(context, export->session, NULL);
1833 context->validated = 1;