2 * Copyright (C) 2016, 2017, 2018 "IoT.bzh"
3 * Author: José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
26 #include <json-c/json.h>
27 #if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
28 #define JSON_C_TO_STRING_NOSLASHESCAPE 0
31 #define AFB_BINDING_VERSION 0
32 #include <afb/afb-binding.h>
35 #include "afb-apiset.h"
36 #if defined(WITH_LEGACY_BINDING_V1)
37 #include "afb-api-so-v1.h"
39 #include "afb-api-so-v2.h"
40 #include "afb-api-v3.h"
41 #include "afb-common.h"
42 #include "afb-systemd.h"
45 #include "afb-export.h"
47 #include "afb-msg-json.h"
48 #include "afb-session.h"
50 #include "afb-calls.h"
53 #include "sig-monitor.h"
54 #include "wrap-json.h"
56 /*************************************************************************
58 ************************************************************************/
61 * structure for handling events
65 /* link to the next event handler of the list */
66 struct event_handler *next;
68 /* function to call on the case of the event */
69 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
71 /* closure for the callback */
74 /* the handled pattern */
79 * Actually supported versions
84 #if defined(WITH_LEGACY_BINDING_V1)
92 * The states of exported APIs
102 * structure of the exported API
107 struct afb_api_x3 api;
109 /* reference count */
112 /* version of the api */
119 unsigned declared: 1;
122 unsigned unsealed: 1;
128 /* session for service */
129 struct afb_session *session;
131 /* apiset the API is declared in */
132 struct afb_apiset *declare_set;
134 /* apiset for calls */
135 struct afb_apiset *call_set;
137 /* event listener for service or NULL */
138 struct afb_evt_listener *listener;
140 /* event handler list */
141 struct event_handler *event_handlers;
144 struct json_object *settings;
146 /* internal descriptors */
148 #if defined(WITH_LEGACY_BINDING_V1)
149 struct afb_binding_v1 *v1;
151 const struct afb_binding_v2 *v2;
152 struct afb_api_v3 *v3;
157 #if defined(WITH_LEGACY_BINDING_V1)
158 int (*v1)(struct afb_service_x1);
161 int (*v3)(struct afb_api_x3 *api);
165 void (*on_any_event_v12)(const char *event, struct json_object *object);
166 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
170 #if defined(WITH_LEGACY_BINDING_V1)
171 struct afb_binding_interface_v1 v1;
173 struct afb_binding_data_v2 *v2;
180 /*****************************************************************************/
182 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
184 return (struct afb_api_x3*)export;
187 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
189 return (struct afb_export*)api;
192 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
194 return from_api_x3(api);
197 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
199 return to_api_x3(export);
202 /******************************************************************************
203 ******************************************************************************
204 ******************************************************************************
205 ******************************************************************************
207 ******************************************************************************
208 ******************************************************************************
209 ******************************************************************************
210 ******************************************************************************/
212 static struct json_object *configuration;
214 void afb_export_set_config(struct json_object *config)
216 struct json_object *save = configuration;
217 configuration = json_object_get(config);
218 json_object_put(save);
221 static struct json_object *get_settings(const char *name)
223 struct json_object *result;
224 struct json_object *obj;
226 if (json_object_object_get_ex(configuration, "*", &obj))
227 result = wrap_json_clone(obj);
229 result = json_object_new_object();
231 if (json_object_object_get_ex(configuration, name, &obj))
232 wrap_json_object_add(result, obj);
237 /******************************************************************************
238 ******************************************************************************
239 ******************************************************************************
240 ******************************************************************************
242 ******************************************************************************
243 ******************************************************************************
244 ******************************************************************************
245 ******************************************************************************/
247 /**********************************************
249 **********************************************/
250 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)
253 struct afb_export *export = from_api_x3(closure);
255 if (!fmt || vasprintf(&p, fmt, args) < 0)
256 vverbose(level, file, line, function, fmt, args);
258 verbose(level, file, line, function, "[API %s] %s", export->api.apiname, p);
263 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
265 vverbose_cb(closure, level, file, line, NULL, fmt, args);
268 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
270 struct afb_export *export = from_api_x3(closure);
272 /* check daemon state */
273 if (export->state == Api_State_Pre_Init) {
274 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
279 /* create the event */
280 return afb_evt_event_x2_create2(export->api.apiname, name);
283 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
285 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
286 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
289 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
293 struct afb_export *export = from_api_x3(closure);
295 /* check daemon state */
296 if (export->state == Api_State_Pre_Init) {
297 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
298 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
303 /* makes the event name */
304 plen = strlen(export->api.apiname);
306 event = alloca(nlen + plen + 2);
307 memcpy(event, export->api.apiname, plen);
309 memcpy(event + plen + 1, name, nlen + 1);
311 /* broadcast the event */
312 return afb_evt_broadcast(event, object);
315 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
317 return afb_common_rootdir_open_locale(filename, flags, locale);
320 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
322 return jobs_queue(group, timeout, callback, argument);
325 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
327 return afb_xreq_unstore(sreq);
330 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
332 struct afb_export *export = from_api_x3(closure);
334 char *iter, *end, save;
336 /* scan the names in a local copy */
338 iter = strdupa(name);
344 if (!save) /* at end? */
347 /* search for the end */
349 while (save && !isspace(save))
353 /* check the required api */
354 if (export->state == Api_State_Pre_Init)
355 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
357 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
366 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
368 struct afb_export *export = from_api_x3(closure);
369 if (!afb_api_is_valid_name(aliasname)) {
370 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
374 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
375 afb_export_add_alias(export, apiname, aliasname);
379 static struct afb_api_x3 *api_new_api_cb(
380 struct afb_api_x3 *closure,
384 int (*preinit)(void*, struct afb_api_x3 *),
385 void *preinit_closure)
387 struct afb_export *export = from_api_x3(closure);
388 struct afb_api_v3 *apiv3 = afb_api_v3_create(export->declare_set, export->call_set, api, info, noconcurrency, preinit, preinit_closure, 1);
389 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
392 /**********************************************
394 **********************************************/
395 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)
397 struct afb_export *export = from_api_x3(closure);
400 vverbose_cb(closure, level, file, line, function, fmt, args);
401 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
405 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)
407 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
410 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
412 struct afb_export *export = from_api_x3(closure);
413 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
414 afb_hook_api_event_make(export, name, r);
418 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
420 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
421 struct afb_event_x1 e;
423 e.itf = event ? event->itf : NULL;
427 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
430 struct afb_export *export = from_api_x3(closure);
431 json_object_get(object);
432 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
433 r = event_broadcast_cb(closure, name, object);
434 afb_hook_api_event_broadcast_after(export, name, object, r);
435 json_object_put(object);
439 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
441 struct afb_export *export = from_api_x3(closure);
442 struct sd_event *r = afb_systemd_get_event_loop();
443 return afb_hook_api_get_event_loop(export, r);
446 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
448 struct afb_export *export = from_api_x3(closure);
449 struct sd_bus *r = afb_systemd_get_user_bus();
450 return afb_hook_api_get_user_bus(export, r);
453 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
455 struct afb_export *export = from_api_x3(closure);
456 struct sd_bus *r = afb_systemd_get_system_bus();
457 return afb_hook_api_get_system_bus(export, r);
460 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
462 struct afb_export *export = from_api_x3(closure);
463 int r = afb_common_rootdir_get_fd();
464 return afb_hook_api_rootdir_get_fd(export, r);
467 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
469 struct afb_export *export = from_api_x3(closure);
470 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
471 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
474 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
476 struct afb_export *export = from_api_x3(closure);
477 int r = queue_job_cb(closure, callback, argument, group, timeout);
478 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
481 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
483 struct afb_export *export = from_api_x3(closure);
484 afb_hook_api_legacy_unstore_req(export, sreq);
485 return legacy_unstore_req_cb(closure, sreq);
488 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
491 struct afb_export *export = from_api_x3(closure);
492 afb_hook_api_require_api(export, name, initialized);
493 result = require_api_cb(closure, name, initialized);
494 return afb_hook_api_require_api_result(export, name, initialized, result);
497 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
499 struct afb_export *export = from_api_x3(closure);
500 int result = add_alias_cb(closure, apiname, aliasname);
501 return afb_hook_api_add_alias(export, apiname, aliasname, result);
504 static struct afb_api_x3 *hooked_api_new_api_cb(
505 struct afb_api_x3 *closure,
509 int (*preinit)(void*, struct afb_api_x3 *),
510 void *preinit_closure)
512 struct afb_api_x3 *result;
513 struct afb_export *export = from_api_x3(closure);
514 afb_hook_api_new_api_before(export, api, info, noconcurrency);
515 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
516 afb_hook_api_new_api_after(export, -!result, api);
520 /**********************************************
522 **********************************************/
523 static const struct afb_daemon_itf_x1 daemon_itf = {
524 .vverbose_v1 = legacy_vverbose_v1_cb,
525 .vverbose_v2 = vverbose_cb,
526 .event_make = legacy_event_x1_make_cb,
527 .event_broadcast = event_broadcast_cb,
528 .get_event_loop = afb_systemd_get_event_loop,
529 .get_user_bus = afb_systemd_get_user_bus,
530 .get_system_bus = afb_systemd_get_system_bus,
531 .rootdir_get_fd = afb_common_rootdir_get_fd,
532 .rootdir_open_locale = rootdir_open_locale_cb,
533 .queue_job = queue_job_cb,
534 .unstore_req = legacy_unstore_req_cb,
535 .require_api = require_api_cb,
536 .add_alias = add_alias_cb,
537 .new_api = api_new_api_cb,
540 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
541 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
542 .vverbose_v2 = hooked_vverbose_cb,
543 .event_make = legacy_hooked_event_x1_make_cb,
544 .event_broadcast = hooked_event_broadcast_cb,
545 .get_event_loop = hooked_get_event_loop,
546 .get_user_bus = hooked_get_user_bus,
547 .get_system_bus = hooked_get_system_bus,
548 .rootdir_get_fd = hooked_rootdir_get_fd,
549 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
550 .queue_job = hooked_queue_job_cb,
551 .unstore_req = legacy_hooked_unstore_req_cb,
552 .require_api = hooked_require_api_cb,
553 .add_alias = hooked_add_alias_cb,
554 .new_api = hooked_api_new_api_cb,
557 /******************************************************************************
558 ******************************************************************************
559 ******************************************************************************
560 ******************************************************************************
562 ******************************************************************************
563 ******************************************************************************
564 ******************************************************************************
565 ******************************************************************************/
567 /* the common session for services sharing their session */
568 static struct afb_session *common_session;
570 /******************************************************************************
571 ******************************************************************************
572 ******************************************************************************
573 ******************************************************************************
575 ******************************************************************************
576 ******************************************************************************
577 ******************************************************************************
578 ******************************************************************************/
581 struct afb_api_x3 *apix3,
584 struct json_object *args,
585 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
588 struct afb_export *export = from_api_x3(apix3);
589 return afb_calls_call(export, api, verb, args, callback, closure);
592 static int call_sync_x3(
593 struct afb_api_x3 *apix3,
596 struct json_object *args,
597 struct json_object **object,
601 struct afb_export *export = from_api_x3(apix3);
602 return afb_calls_call_sync(export, api, verb, args, object, error, info);
605 static void legacy_call_v12(
606 struct afb_api_x3 *apix3,
609 struct json_object *args,
610 void (*callback)(void*, int, struct json_object*),
613 struct afb_export *export = from_api_x3(apix3);
614 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
617 static void legacy_call_x3(
618 struct afb_api_x3 *apix3,
621 struct json_object *args,
622 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
625 struct afb_export *export = from_api_x3(apix3);
626 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
629 static int legacy_call_sync(
630 struct afb_api_x3 *apix3,
633 struct json_object *args,
634 struct json_object **result)
636 struct afb_export *export = from_api_x3(apix3);
637 return afb_calls_legacy_call_sync(export, api, verb, args, result);
640 static void hooked_call_x3(
641 struct afb_api_x3 *apix3,
644 struct json_object *args,
645 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
648 struct afb_export *export = from_api_x3(apix3);
649 afb_calls_hooked_call(export, api, verb, args, callback, closure);
652 static int hooked_call_sync_x3(
653 struct afb_api_x3 *apix3,
656 struct json_object *args,
657 struct json_object **object,
661 struct afb_export *export = from_api_x3(apix3);
662 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
665 static void legacy_hooked_call_v12(
666 struct afb_api_x3 *apix3,
669 struct json_object *args,
670 void (*callback)(void*, int, struct json_object*),
673 struct afb_export *export = from_api_x3(apix3);
674 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
677 static void legacy_hooked_call_x3(
678 struct afb_api_x3 *apix3,
681 struct json_object *args,
682 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
685 struct afb_export *export = from_api_x3(apix3);
686 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
689 static int legacy_hooked_call_sync(
690 struct afb_api_x3 *apix3,
693 struct json_object *args,
694 struct json_object **result)
696 struct afb_export *export = from_api_x3(apix3);
697 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
700 /* the interface for services */
701 static const struct afb_service_itf_x1 service_itf = {
702 .call = legacy_call_v12,
703 .call_sync = legacy_call_sync
706 /* the interface for services */
707 static const struct afb_service_itf_x1 hooked_service_itf = {
708 .call = legacy_hooked_call_v12,
709 .call_sync = legacy_hooked_call_sync
712 /******************************************************************************
713 ******************************************************************************
714 ******************************************************************************
715 ******************************************************************************
717 ******************************************************************************
718 ******************************************************************************
719 ******************************************************************************
720 ******************************************************************************/
722 static int api_set_verbs_v2_cb(
723 struct afb_api_x3 *api,
724 const struct afb_verb_v2 *verbs)
726 struct afb_export *export = from_api_x3(api);
728 if (export->unsealed) {
729 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
737 static int api_set_verbs_v3_cb(
738 struct afb_api_x3 *api,
739 const struct afb_verb_v3 *verbs)
741 struct afb_export *export = from_api_x3(api);
743 if (!export->unsealed) {
748 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
752 static int api_add_verb_cb(
753 struct afb_api_x3 *api,
756 void (*callback)(struct afb_req_x2 *req),
758 const struct afb_auth *auth,
762 struct afb_export *export = from_api_x3(api);
764 if (!export->unsealed) {
769 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
772 static int api_del_verb_cb(
773 struct afb_api_x3 *api,
777 struct afb_export *export = from_api_x3(api);
779 if (!export->unsealed) {
784 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
787 static int api_set_on_event_cb(
788 struct afb_api_x3 *api,
789 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
791 struct afb_export *export = from_api_x3(api);
792 return afb_export_handle_events_v3(export, onevent);
795 static int api_set_on_init_cb(
796 struct afb_api_x3 *api,
797 int (*oninit)(struct afb_api_x3 *api))
799 struct afb_export *export = from_api_x3(api);
801 return afb_export_handle_init_v3(export, oninit);
804 static void api_seal_cb(
805 struct afb_api_x3 *api)
807 struct afb_export *export = from_api_x3(api);
809 export->unsealed = 0;
812 static int event_handler_add_cb(
813 struct afb_api_x3 *api,
815 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
818 struct afb_export *export = from_api_x3(api);
820 return afb_export_event_handler_add(export, pattern, callback, closure);
823 static int event_handler_del_cb(
824 struct afb_api_x3 *api,
828 struct afb_export *export = from_api_x3(api);
830 return afb_export_event_handler_del(export, pattern, closure);
833 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
835 struct afb_export *export = from_api_x3(api);
838 char *iter, *end, save;
840 iter = strdupa(name);
846 if (!save) /* at end? */
849 /* search for the end */
851 while (save && !isspace(save))
855 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
864 static int class_require_cb(struct afb_api_x3 *api, const char *name)
866 struct afb_export *export = from_api_x3(api);
869 char *iter, *end, save;
871 iter = strdupa(name);
877 if (!save) /* at end? */
880 /* search for the end */
882 while (save && !isspace(save))
886 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
895 static int delete_api_cb(struct afb_api_x3 *api)
897 struct afb_export *export = from_api_x3(api);
899 if (!export->unsealed) {
904 afb_export_undeclare(export);
905 afb_export_unref(export);
909 static struct json_object *settings_cb(struct afb_api_x3 *api)
911 struct afb_export *export = from_api_x3(api);
912 struct json_object *result = export->settings;
914 result = get_settings(export->name);
915 export->settings = result;
920 static int hooked_api_set_verbs_v2_cb(
921 struct afb_api_x3 *api,
922 const struct afb_verb_v2 *verbs)
924 struct afb_export *export = from_api_x3(api);
925 int result = api_set_verbs_v2_cb(api, verbs);
926 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
929 static int hooked_api_set_verbs_v3_cb(
930 struct afb_api_x3 *api,
931 const struct afb_verb_v3 *verbs)
933 struct afb_export *export = from_api_x3(api);
934 int result = api_set_verbs_v3_cb(api, verbs);
935 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
938 static int hooked_api_add_verb_cb(
939 struct afb_api_x3 *api,
942 void (*callback)(struct afb_req_x2 *req),
944 const struct afb_auth *auth,
948 struct afb_export *export = from_api_x3(api);
949 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
950 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
953 static int hooked_api_del_verb_cb(
954 struct afb_api_x3 *api,
958 struct afb_export *export = from_api_x3(api);
959 int result = api_del_verb_cb(api, verb, vcbdata);
960 return afb_hook_api_api_del_verb(export, result, verb);
963 static int hooked_api_set_on_event_cb(
964 struct afb_api_x3 *api,
965 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
967 struct afb_export *export = from_api_x3(api);
968 int result = api_set_on_event_cb(api, onevent);
969 return afb_hook_api_api_set_on_event(export, result);
972 static int hooked_api_set_on_init_cb(
973 struct afb_api_x3 *api,
974 int (*oninit)(struct afb_api_x3 *api))
976 struct afb_export *export = from_api_x3(api);
977 int result = api_set_on_init_cb(api, oninit);
978 return afb_hook_api_api_set_on_init(export, result);
981 static void hooked_api_seal_cb(
982 struct afb_api_x3 *api)
984 struct afb_export *export = from_api_x3(api);
985 afb_hook_api_api_seal(export);
989 static int hooked_event_handler_add_cb(
990 struct afb_api_x3 *api,
992 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
995 struct afb_export *export = from_api_x3(api);
996 int result = event_handler_add_cb(api, pattern, callback, closure);
997 return afb_hook_api_event_handler_add(export, result, pattern);
1000 static int hooked_event_handler_del_cb(
1001 struct afb_api_x3 *api,
1002 const char *pattern,
1005 struct afb_export *export = from_api_x3(api);
1006 int result = event_handler_del_cb(api, pattern, closure);
1007 return afb_hook_api_event_handler_del(export, result, pattern);
1010 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1012 struct afb_export *export = from_api_x3(api);
1013 int result = class_provide_cb(api, name);
1014 return afb_hook_api_class_provide(export, result, name);
1017 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1019 struct afb_export *export = from_api_x3(api);
1020 int result = class_require_cb(api, name);
1021 return afb_hook_api_class_require(export, result, name);
1024 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1026 struct afb_export *export = afb_export_addref(from_api_x3(api));
1027 int result = delete_api_cb(api);
1028 result = afb_hook_api_delete_api(export, result);
1029 afb_export_unref(export);
1033 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1035 struct afb_export *export = from_api_x3(api);
1036 struct json_object *result = settings_cb(api);
1037 result = afb_hook_api_settings(export, result);
1041 static const struct afb_api_x3_itf api_x3_itf = {
1043 .vverbose = (void*)vverbose_cb,
1045 .get_event_loop = afb_systemd_get_event_loop,
1046 .get_user_bus = afb_systemd_get_user_bus,
1047 .get_system_bus = afb_systemd_get_system_bus,
1048 .rootdir_get_fd = afb_common_rootdir_get_fd,
1049 .rootdir_open_locale = rootdir_open_locale_cb,
1050 .queue_job = queue_job_cb,
1052 .require_api = require_api_cb,
1053 .add_alias = add_alias_cb,
1055 .event_broadcast = event_broadcast_cb,
1056 .event_make = event_x2_make_cb,
1058 .legacy_call = legacy_call_x3,
1059 .legacy_call_sync = legacy_call_sync,
1061 .api_new_api = api_new_api_cb,
1062 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1063 .api_add_verb = api_add_verb_cb,
1064 .api_del_verb = api_del_verb_cb,
1065 .api_set_on_event = api_set_on_event_cb,
1066 .api_set_on_init = api_set_on_init_cb,
1067 .api_seal = api_seal_cb,
1068 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1069 .event_handler_add = event_handler_add_cb,
1070 .event_handler_del = event_handler_del_cb,
1073 .call_sync = call_sync_x3,
1075 .class_provide = class_provide_cb,
1076 .class_require = class_require_cb,
1078 .delete_api = delete_api_cb,
1079 .settings = settings_cb,
1082 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1084 .vverbose = hooked_vverbose_cb,
1086 .get_event_loop = hooked_get_event_loop,
1087 .get_user_bus = hooked_get_user_bus,
1088 .get_system_bus = hooked_get_system_bus,
1089 .rootdir_get_fd = hooked_rootdir_get_fd,
1090 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1091 .queue_job = hooked_queue_job_cb,
1093 .require_api = hooked_require_api_cb,
1094 .add_alias = hooked_add_alias_cb,
1096 .event_broadcast = hooked_event_broadcast_cb,
1097 .event_make = hooked_event_x2_make_cb,
1099 .legacy_call = legacy_hooked_call_x3,
1100 .legacy_call_sync = legacy_hooked_call_sync,
1102 .api_new_api = hooked_api_new_api_cb,
1103 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1104 .api_add_verb = hooked_api_add_verb_cb,
1105 .api_del_verb = hooked_api_del_verb_cb,
1106 .api_set_on_event = hooked_api_set_on_event_cb,
1107 .api_set_on_init = hooked_api_set_on_init_cb,
1108 .api_seal = hooked_api_seal_cb,
1109 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1110 .event_handler_add = hooked_event_handler_add_cb,
1111 .event_handler_del = hooked_event_handler_del_cb,
1113 .call = hooked_call_x3,
1114 .call_sync = hooked_call_sync_x3,
1116 .class_provide = hooked_class_provide_cb,
1117 .class_require = hooked_class_require_cb,
1119 .delete_api = hooked_delete_api_cb,
1120 .settings = hooked_settings_cb,
1123 /******************************************************************************
1124 ******************************************************************************
1125 ******************************************************************************
1126 ******************************************************************************
1128 ******************************************************************************
1129 ******************************************************************************
1130 ******************************************************************************
1131 ******************************************************************************/
1134 * Propagates the event to the service
1136 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1138 struct event_handler *handler;
1139 struct afb_export *export = from_api_x3(closure);
1141 /* hook the event before */
1142 if (export->hooksvc & afb_hook_flag_api_on_event)
1143 afb_hook_api_on_event_before(export, event, eventid, object);
1145 /* transmit to specific handlers */
1146 /* search the handler */
1147 handler = export->event_handlers;
1149 if (fnmatch(handler->pattern, event, 0)) {
1150 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1151 handler->callback(handler->closure, event, object, to_api_x3(export));
1153 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1154 handler->callback(handler->closure, event, object, to_api_x3(export));
1155 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1158 handler = handler->next;
1161 /* transmit to default handler */
1162 if (export->on_any_event_v3)
1163 export->on_any_event_v3(to_api_x3(export), event, object);
1164 else if (export->on_any_event_v12)
1165 export->on_any_event_v12(event, object);
1167 /* hook the event after */
1168 if (export->hooksvc & afb_hook_flag_api_on_event)
1169 afb_hook_api_on_event_after(export, event, eventid, object);
1170 json_object_put(object);
1173 /* the interface for events */
1174 static const struct afb_evt_itf evt_itf = {
1175 .broadcast = listener_of_events,
1176 .push = listener_of_events
1179 /* ensure an existing listener */
1180 static int ensure_listener(struct afb_export *export)
1182 if (!export->listener) {
1183 export->listener = afb_evt_listener_create(&evt_itf, export);
1184 if (export->listener == NULL)
1190 int afb_export_event_handler_add(
1191 struct afb_export *export,
1192 const char *pattern,
1193 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1197 struct event_handler *handler, **previous;
1199 rc = ensure_listener(export);
1203 /* search the handler */
1204 previous = &export->event_handlers;
1205 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1206 previous = &handler->next;
1208 /* error if found */
1210 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1215 /* create the event */
1216 handler = malloc(strlen(pattern) + sizeof * handler);
1218 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1223 /* init and record */
1224 handler->next = NULL;
1225 handler->callback = callback;
1226 handler->closure = closure;
1227 strcpy(handler->pattern, pattern);
1228 *previous = handler;
1233 int afb_export_event_handler_del(
1234 struct afb_export *export,
1235 const char *pattern,
1238 struct event_handler *handler, **previous;
1240 /* search the handler */
1241 previous = &export->event_handlers;
1242 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1243 previous = &handler->next;
1245 /* error if found */
1247 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1252 /* remove the found event */
1254 *closure = handler->closure;
1256 *previous = handler->next;
1261 /******************************************************************************
1262 ******************************************************************************
1263 ******************************************************************************
1264 ******************************************************************************
1266 ******************************************************************************
1267 ******************************************************************************
1268 ******************************************************************************
1269 ******************************************************************************/
1271 static struct afb_export *create(
1272 struct afb_apiset *declare_set,
1273 struct afb_apiset *call_set,
1274 const char *apiname,
1275 enum afb_api_version version)
1277 struct afb_export *export;
1279 /* session shared with other exports */
1280 if (common_session == NULL) {
1281 common_session = afb_session_create (0);
1282 if (common_session == NULL)
1285 export = calloc(1, sizeof *export + strlen(apiname));
1289 export->refcount = 1;
1290 strcpy(export->name, apiname);
1291 export->api.apiname = export->name;
1292 export->version = version;
1293 export->state = Api_State_Pre_Init;
1294 export->session = afb_session_addref(common_session);
1295 export->declare_set = afb_apiset_addref(declare_set);
1296 export->call_set = afb_apiset_addref(call_set);
1301 struct afb_export *afb_export_addref(struct afb_export *export)
1304 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1308 void afb_export_unref(struct afb_export *export)
1310 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1311 afb_export_destroy(export);
1314 void afb_export_destroy(struct afb_export *export)
1316 struct event_handler *handler;
1319 while ((handler = export->event_handlers)) {
1320 export->event_handlers = handler->next;
1323 if (export->listener != NULL)
1324 afb_evt_listener_unref(export->listener);
1325 afb_session_unref(export->session);
1326 afb_apiset_unref(export->declare_set);
1327 afb_apiset_unref(export->call_set);
1328 if (export->api.apiname != export->name)
1329 free((void*)export->api.apiname);
1330 json_object_put(export->settings);
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, 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(
1356 struct afb_apiset *declare_set,
1357 struct afb_apiset *call_set,
1358 const char *apiname,
1359 int (*init)(struct afb_service_x1),
1360 void (*onevent)(const char*, struct json_object*))
1362 struct afb_export *export = create(declare_set, call_set, apiname, 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(
1376 struct afb_apiset *declare_set,
1377 struct afb_apiset *call_set,
1378 const char *apiname,
1379 const struct afb_binding_v2 *binding,
1380 struct afb_binding_data_v2 *data,
1382 void (*onevent)(const char*, struct json_object*))
1384 struct afb_export *export = create(declare_set, call_set, apiname, 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)
1403 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_3);
1405 export->unsealed = 1;
1406 export->desc.v3 = apiv3;
1407 afb_export_logmask_set(export, logmask);
1408 afb_export_update_hooks(export);
1413 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1415 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1418 int afb_export_rename(struct afb_export *export, const char *apiname)
1422 if (export->declared) {
1427 /* copy the name locally */
1428 name = strdup(apiname);
1434 if (export->api.apiname != export->name)
1435 free((void*)export->api.apiname);
1436 export->api.apiname = name;
1438 afb_export_update_hooks(export);
1442 const char *afb_export_apiname(const struct afb_export *export)
1444 return export->api.apiname;
1447 void afb_export_update_hooks(struct afb_export *export)
1449 export->hookditf = afb_hook_flags_api(export->api.apiname);
1450 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1451 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1453 switch (export->version) {
1454 #if defined(WITH_LEGACY_BINDING_V1)
1456 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1460 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1461 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1466 int afb_export_unshare_session(struct afb_export *export)
1468 if (export->session == common_session) {
1469 export->session = afb_session_create (0);
1470 if (export->session)
1471 afb_session_unref(common_session);
1473 export->session = common_session;
1480 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1483 switch (export->version) {
1484 #if defined(WITH_LEGACY_BINDING_V1)
1490 ERROR("invalid version 12 for API %s", export->api.apiname);
1495 export->on_any_event_v12 = on_event;
1496 return ensure_listener(export);
1499 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))
1502 switch (export->version) {
1503 case Api_Version_3: break;
1505 ERROR("invalid version Dyn for API %s", export->api.apiname);
1510 export->on_any_event_v3 = on_event;
1511 return ensure_listener(export);
1514 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1516 if (export->state != Api_State_Pre_Init) {
1517 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1522 export->init.v3 = oninit;
1526 #if defined(WITH_LEGACY_BINDING_V1)
1528 * Starts a new service (v1)
1530 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1532 return export->desc.v1 = regfun(&export->export.v1);
1536 int afb_export_preinit_x3(
1537 struct afb_export *export,
1538 int (*preinit)(void*, struct afb_api_x3*),
1541 return preinit(closure, to_api_x3(export));
1544 int afb_export_logmask_get(const struct afb_export *export)
1546 return export->api.logmask;
1549 void afb_export_logmask_set(struct afb_export *export, int mask)
1551 export->api.logmask = mask;
1552 switch (export->version) {
1553 #if defined(WITH_LEGACY_BINDING_V1)
1554 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1556 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1560 void *afb_export_userdata_get(const struct afb_export *export)
1562 return export->api.userdata;
1565 void afb_export_userdata_set(struct afb_export *export, void *data)
1567 export->api.userdata = data;
1570 /******************************************************************************
1571 ******************************************************************************
1572 ******************************************************************************
1573 ******************************************************************************
1575 ******************************************************************************
1576 ******************************************************************************
1577 ******************************************************************************
1578 ******************************************************************************/
1583 struct afb_export *export;
1586 static void do_init(int sig, void *closure)
1589 struct init *init = closure;
1590 struct afb_export *export;
1595 export = init->export;
1596 switch (export->version) {
1597 #if defined(WITH_LEGACY_BINDING_V1)
1599 rc = export->init.v1 ? export->init.v1(
1600 (struct afb_service_x1){
1601 .itf = &hooked_service_itf,
1602 .closure = to_api_x3(export) }) : 0;
1606 rc = export->init.v2 ? export->init.v2() : 0;
1609 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1616 init->return_code = rc;
1620 int afb_export_start(struct afb_export *export)
1626 switch (export->state) {
1630 case Api_State_Init:
1631 /* starting in progress: it is an error */
1632 ERROR("Service of API %s required started while starting", export->api.apiname);
1639 /* set event handling */
1640 switch (export->version) {
1641 #if defined(WITH_LEGACY_BINDING_V1)
1645 if (export->on_any_event_v12) {
1646 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1655 ERROR("Can't set event handler for %s", export->api.apiname);
1659 /* Starts the service */
1660 if (export->hooksvc & afb_hook_flag_api_start)
1661 afb_hook_api_start_before(export);
1663 export->state = Api_State_Init;
1664 init.export = export;
1665 sig_monitor(0, do_init, &init);
1666 rc = init.return_code;
1667 export->state = Api_State_Run;
1669 if (export->hooksvc & afb_hook_flag_api_start)
1670 afb_hook_api_start_after(export, rc);
1673 /* initialisation error */
1674 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1681 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1683 struct afb_export *export = closure;
1685 xreq->request.api = to_api_x3(export);
1687 switch (export->version) {
1688 #if defined(WITH_LEGACY_BINDING_V1)
1690 afb_api_so_v1_process_call(export->desc.v1, xreq);
1694 afb_api_so_v2_process_call(export->desc.v2, xreq);
1697 afb_api_v3_process_call(export->desc.v3, xreq);
1700 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1705 static struct json_object *api_describe_cb(void *closure)
1707 struct afb_export *export = closure;
1708 struct json_object *result;
1710 switch (export->version) {
1711 #if defined(WITH_LEGACY_BINDING_V1)
1713 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1717 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1720 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1729 static int api_service_start_cb(void *closure)
1731 struct afb_export *export = closure;
1733 return afb_export_start(export);
1736 static void api_update_hooks_cb(void *closure)
1738 struct afb_export *export = closure;
1740 afb_export_update_hooks(export);
1743 static int api_get_logmask_cb(void *closure)
1745 struct afb_export *export = closure;
1747 return afb_export_logmask_get(export);
1750 static void api_set_logmask_cb(void *closure, int level)
1752 struct afb_export *export = closure;
1754 afb_export_logmask_set(export, level);
1757 static void api_unref_cb(void *closure)
1759 struct afb_export *export = closure;
1761 afb_export_unref(export);
1764 static struct afb_api_itf export_api_itf =
1766 .call = api_call_cb,
1767 .service_start = api_service_start_cb,
1768 .update_hooks = api_update_hooks_cb,
1769 .get_logmask = api_get_logmask_cb,
1770 .set_logmask = api_set_logmask_cb,
1771 .describe = api_describe_cb,
1772 .unref = api_unref_cb
1775 int afb_export_declare(struct afb_export *export,
1779 struct afb_api_item afb_api;
1781 if (export->declared)
1784 /* init the record structure */
1785 afb_api.closure = afb_export_addref(export);
1786 afb_api.itf = &export_api_itf;
1787 afb_api.group = noconcurrency ? export : NULL;
1789 /* records the binding */
1790 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1792 export->declared = 1;
1794 ERROR("can't declare export %s to set %s, ABORTING it!",
1795 export->api.apiname,
1796 afb_apiset_name(export->declare_set));
1797 afb_export_addref(export);
1804 void afb_export_undeclare(struct afb_export *export)
1806 if (export->declared) {
1807 export->declared = 0;
1808 afb_apiset_del(export->declare_set, export->api.apiname);
1812 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1814 return afb_evt_event_x2_add_watch(export->listener, event);
1817 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1819 return afb_evt_event_x2_remove_watch(export->listener, event);
1822 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1824 afb_xreq_process(xreq, export->call_set);
1827 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1829 afb_context_init(context, export->session, NULL);
1830 context->validated = 1;