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 afb_export *creator;
146 /* path indication if any */
150 struct json_object *settings;
152 /* internal descriptors */
154 #if defined(WITH_LEGACY_BINDING_V1)
155 struct afb_binding_v1 *v1;
157 const struct afb_binding_v2 *v2;
158 struct afb_api_v3 *v3;
163 #if defined(WITH_LEGACY_BINDING_V1)
164 int (*v1)(struct afb_service_x1);
167 int (*v3)(struct afb_api_x3 *api);
171 void (*on_any_event_v12)(const char *event, struct json_object *object);
172 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
176 #if defined(WITH_LEGACY_BINDING_V1)
177 struct afb_binding_interface_v1 v1;
179 struct afb_binding_data_v2 *v2;
186 /*****************************************************************************/
188 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
190 return (struct afb_api_x3*)export;
193 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
195 return (struct afb_export*)api;
198 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
200 return from_api_x3(api);
203 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
205 return to_api_x3(export);
208 /******************************************************************************
209 ******************************************************************************
210 ******************************************************************************
211 ******************************************************************************
213 ******************************************************************************
214 ******************************************************************************
215 ******************************************************************************
216 ******************************************************************************/
218 static struct json_object *configuration;
220 void afb_export_set_config(struct json_object *config)
222 struct json_object *save = configuration;
223 configuration = json_object_get(config);
224 json_object_put(save);
227 static struct json_object *make_settings(struct afb_export *export)
229 struct json_object *result;
230 struct json_object *obj;
231 struct afb_export *iter;
234 /* clone the globals */
235 if (json_object_object_get_ex(configuration, "*", &obj))
236 result = wrap_json_clone(obj);
238 result = json_object_new_object();
241 if (json_object_object_get_ex(configuration, export->name, &obj))
242 wrap_json_object_add(result, obj);
244 /* add library path */
245 for (iter = export ; iter && !iter->path ; iter = iter->creator);
247 path = realpath(iter->path, NULL);
248 json_object_object_add(result, "binding-path", json_object_new_string(path));
252 export->settings = result;
256 /******************************************************************************
257 ******************************************************************************
258 ******************************************************************************
259 ******************************************************************************
261 ******************************************************************************
262 ******************************************************************************
263 ******************************************************************************
264 ******************************************************************************/
266 /**********************************************
268 **********************************************/
269 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)
272 struct afb_export *export = from_api_x3(closure);
274 if (!fmt || vasprintf(&p, fmt, args) < 0)
275 vverbose(level, file, line, function, fmt, args);
277 verbose(level, file, line, function, "[API %s] %s", export->api.apiname, p);
282 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
284 vverbose_cb(closure, level, file, line, NULL, fmt, args);
287 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
289 struct afb_export *export = from_api_x3(closure);
291 /* check daemon state */
292 if (export->state == Api_State_Pre_Init) {
293 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
298 /* create the event */
299 return afb_evt_event_x2_create2(export->api.apiname, name);
302 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
304 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
305 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
308 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
312 struct afb_export *export = from_api_x3(closure);
314 /* check daemon state */
315 if (export->state == Api_State_Pre_Init) {
316 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
317 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
322 /* makes the event name */
323 plen = strlen(export->api.apiname);
325 event = alloca(nlen + plen + 2);
326 memcpy(event, export->api.apiname, plen);
328 memcpy(event + plen + 1, name, nlen + 1);
330 /* broadcast the event */
331 return afb_evt_broadcast(event, object);
334 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
336 return afb_common_rootdir_open_locale(filename, flags, locale);
339 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
341 return jobs_queue(group, timeout, callback, argument);
344 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
346 return afb_xreq_unstore(sreq);
349 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
351 struct afb_export *export = from_api_x3(closure);
353 char *iter, *end, save;
355 /* emit a warning about unexpected require in preinit */
356 if (export->state == Api_State_Pre_Init)
357 WARNING("[API %s] requiring apis in pre-init may lead to unexpected result (requires%s: %s)",
358 export->api.apiname, initialized ? " initialized" : "", name);
360 /* scan the names in a local copy */
362 iter = strdupa(name);
368 if (!save) /* at end? */
371 /* search for the end */
373 while (save && !isspace(save))
377 /* check the required api */
378 if (export->state == Api_State_Pre_Init)
379 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
381 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
390 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
392 struct afb_export *export = from_api_x3(closure);
393 if (!afb_api_is_valid_name(aliasname)) {
394 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
398 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
399 afb_export_add_alias(export, apiname, aliasname);
403 static struct afb_api_x3 *api_new_api_cb(
404 struct afb_api_x3 *closure,
408 int (*preinit)(void*, struct afb_api_x3 *),
409 void *preinit_closure)
411 struct afb_export *export = from_api_x3(closure);
412 struct afb_api_v3 *apiv3 = afb_api_v3_create(
413 export->declare_set, export->call_set,
414 api, info, noconcurrency,
415 preinit, preinit_closure, 1,
417 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
420 /**********************************************
422 **********************************************/
423 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)
425 struct afb_export *export = from_api_x3(closure);
428 vverbose_cb(closure, level, file, line, function, fmt, args);
429 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
433 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)
435 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
438 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
440 struct afb_export *export = from_api_x3(closure);
441 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
442 afb_hook_api_event_make(export, name, r);
446 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
448 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
449 struct afb_event_x1 e;
451 e.itf = event ? event->itf : NULL;
455 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
458 struct afb_export *export = from_api_x3(closure);
459 json_object_get(object);
460 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
461 r = event_broadcast_cb(closure, name, object);
462 afb_hook_api_event_broadcast_after(export, name, object, r);
463 json_object_put(object);
467 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
469 struct afb_export *export = from_api_x3(closure);
470 struct sd_event *r = afb_systemd_get_event_loop();
471 return afb_hook_api_get_event_loop(export, r);
474 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
476 struct afb_export *export = from_api_x3(closure);
477 struct sd_bus *r = afb_systemd_get_user_bus();
478 return afb_hook_api_get_user_bus(export, r);
481 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
483 struct afb_export *export = from_api_x3(closure);
484 struct sd_bus *r = afb_systemd_get_system_bus();
485 return afb_hook_api_get_system_bus(export, r);
488 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
490 struct afb_export *export = from_api_x3(closure);
491 int r = afb_common_rootdir_get_fd();
492 return afb_hook_api_rootdir_get_fd(export, r);
495 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
497 struct afb_export *export = from_api_x3(closure);
498 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
499 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
502 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
504 struct afb_export *export = from_api_x3(closure);
505 int r = queue_job_cb(closure, callback, argument, group, timeout);
506 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
509 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
511 struct afb_export *export = from_api_x3(closure);
512 afb_hook_api_legacy_unstore_req(export, sreq);
513 return legacy_unstore_req_cb(closure, sreq);
516 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
519 struct afb_export *export = from_api_x3(closure);
520 afb_hook_api_require_api(export, name, initialized);
521 result = require_api_cb(closure, name, initialized);
522 return afb_hook_api_require_api_result(export, name, initialized, result);
525 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
527 struct afb_export *export = from_api_x3(closure);
528 int result = add_alias_cb(closure, apiname, aliasname);
529 return afb_hook_api_add_alias(export, apiname, aliasname, result);
532 static struct afb_api_x3 *hooked_api_new_api_cb(
533 struct afb_api_x3 *closure,
537 int (*preinit)(void*, struct afb_api_x3 *),
538 void *preinit_closure)
540 struct afb_api_x3 *result;
541 struct afb_export *export = from_api_x3(closure);
542 afb_hook_api_new_api_before(export, api, info, noconcurrency);
543 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
544 afb_hook_api_new_api_after(export, -!result, api);
548 /**********************************************
550 **********************************************/
551 static const struct afb_daemon_itf_x1 daemon_itf = {
552 .vverbose_v1 = legacy_vverbose_v1_cb,
553 .vverbose_v2 = vverbose_cb,
554 .event_make = legacy_event_x1_make_cb,
555 .event_broadcast = event_broadcast_cb,
556 .get_event_loop = afb_systemd_get_event_loop,
557 .get_user_bus = afb_systemd_get_user_bus,
558 .get_system_bus = afb_systemd_get_system_bus,
559 .rootdir_get_fd = afb_common_rootdir_get_fd,
560 .rootdir_open_locale = rootdir_open_locale_cb,
561 .queue_job = queue_job_cb,
562 .unstore_req = legacy_unstore_req_cb,
563 .require_api = require_api_cb,
564 .add_alias = add_alias_cb,
565 .new_api = api_new_api_cb,
568 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
569 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
570 .vverbose_v2 = hooked_vverbose_cb,
571 .event_make = legacy_hooked_event_x1_make_cb,
572 .event_broadcast = hooked_event_broadcast_cb,
573 .get_event_loop = hooked_get_event_loop,
574 .get_user_bus = hooked_get_user_bus,
575 .get_system_bus = hooked_get_system_bus,
576 .rootdir_get_fd = hooked_rootdir_get_fd,
577 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
578 .queue_job = hooked_queue_job_cb,
579 .unstore_req = legacy_hooked_unstore_req_cb,
580 .require_api = hooked_require_api_cb,
581 .add_alias = hooked_add_alias_cb,
582 .new_api = hooked_api_new_api_cb,
585 /******************************************************************************
586 ******************************************************************************
587 ******************************************************************************
588 ******************************************************************************
590 ******************************************************************************
591 ******************************************************************************
592 ******************************************************************************
593 ******************************************************************************/
595 /* the common session for services sharing their session */
596 static struct afb_session *common_session;
598 /******************************************************************************
599 ******************************************************************************
600 ******************************************************************************
601 ******************************************************************************
603 ******************************************************************************
604 ******************************************************************************
605 ******************************************************************************
606 ******************************************************************************/
609 struct afb_api_x3 *apix3,
612 struct json_object *args,
613 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
616 struct afb_export *export = from_api_x3(apix3);
617 return afb_calls_call(export, api, verb, args, callback, closure);
620 static int call_sync_x3(
621 struct afb_api_x3 *apix3,
624 struct json_object *args,
625 struct json_object **object,
629 struct afb_export *export = from_api_x3(apix3);
630 return afb_calls_call_sync(export, api, verb, args, object, error, info);
633 static void legacy_call_v12(
634 struct afb_api_x3 *apix3,
637 struct json_object *args,
638 void (*callback)(void*, int, struct json_object*),
641 struct afb_export *export = from_api_x3(apix3);
642 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
645 static void legacy_call_x3(
646 struct afb_api_x3 *apix3,
649 struct json_object *args,
650 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
653 struct afb_export *export = from_api_x3(apix3);
654 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
657 static int legacy_call_sync(
658 struct afb_api_x3 *apix3,
661 struct json_object *args,
662 struct json_object **result)
664 struct afb_export *export = from_api_x3(apix3);
665 return afb_calls_legacy_call_sync(export, api, verb, args, result);
668 static void hooked_call_x3(
669 struct afb_api_x3 *apix3,
672 struct json_object *args,
673 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
676 struct afb_export *export = from_api_x3(apix3);
677 afb_calls_hooked_call(export, api, verb, args, callback, closure);
680 static int hooked_call_sync_x3(
681 struct afb_api_x3 *apix3,
684 struct json_object *args,
685 struct json_object **object,
689 struct afb_export *export = from_api_x3(apix3);
690 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
693 static void legacy_hooked_call_v12(
694 struct afb_api_x3 *apix3,
697 struct json_object *args,
698 void (*callback)(void*, int, struct json_object*),
701 struct afb_export *export = from_api_x3(apix3);
702 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
705 static void legacy_hooked_call_x3(
706 struct afb_api_x3 *apix3,
709 struct json_object *args,
710 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
713 struct afb_export *export = from_api_x3(apix3);
714 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
717 static int legacy_hooked_call_sync(
718 struct afb_api_x3 *apix3,
721 struct json_object *args,
722 struct json_object **result)
724 struct afb_export *export = from_api_x3(apix3);
725 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
728 /* the interface for services */
729 static const struct afb_service_itf_x1 service_itf = {
730 .call = legacy_call_v12,
731 .call_sync = legacy_call_sync
734 /* the interface for services */
735 static const struct afb_service_itf_x1 hooked_service_itf = {
736 .call = legacy_hooked_call_v12,
737 .call_sync = legacy_hooked_call_sync
740 /******************************************************************************
741 ******************************************************************************
742 ******************************************************************************
743 ******************************************************************************
745 ******************************************************************************
746 ******************************************************************************
747 ******************************************************************************
748 ******************************************************************************/
750 static int api_set_verbs_v2_cb(
751 struct afb_api_x3 *api,
752 const struct afb_verb_v2 *verbs)
754 struct afb_export *export = from_api_x3(api);
756 if (export->unsealed) {
757 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
765 static int api_set_verbs_v3_cb(
766 struct afb_api_x3 *api,
767 const struct afb_verb_v3 *verbs)
769 struct afb_export *export = from_api_x3(api);
771 if (!export->unsealed) {
776 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
780 static int api_add_verb_cb(
781 struct afb_api_x3 *api,
784 void (*callback)(struct afb_req_x2 *req),
786 const struct afb_auth *auth,
790 struct afb_export *export = from_api_x3(api);
792 if (!export->unsealed) {
797 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
800 static int api_del_verb_cb(
801 struct afb_api_x3 *api,
805 struct afb_export *export = from_api_x3(api);
807 if (!export->unsealed) {
812 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
815 static int api_set_on_event_cb(
816 struct afb_api_x3 *api,
817 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
819 struct afb_export *export = from_api_x3(api);
820 return afb_export_handle_events_v3(export, onevent);
823 static int api_set_on_init_cb(
824 struct afb_api_x3 *api,
825 int (*oninit)(struct afb_api_x3 *api))
827 struct afb_export *export = from_api_x3(api);
829 return afb_export_handle_init_v3(export, oninit);
832 static void api_seal_cb(
833 struct afb_api_x3 *api)
835 struct afb_export *export = from_api_x3(api);
837 export->unsealed = 0;
840 static int event_handler_add_cb(
841 struct afb_api_x3 *api,
843 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
846 struct afb_export *export = from_api_x3(api);
848 return afb_export_event_handler_add(export, pattern, callback, closure);
851 static int event_handler_del_cb(
852 struct afb_api_x3 *api,
856 struct afb_export *export = from_api_x3(api);
858 return afb_export_event_handler_del(export, pattern, closure);
861 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
863 struct afb_export *export = from_api_x3(api);
866 char *iter, *end, save;
868 iter = strdupa(name);
874 if (!save) /* at end? */
877 /* search for the end */
879 while (save && !isspace(save))
883 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
892 static int class_require_cb(struct afb_api_x3 *api, const char *name)
894 struct afb_export *export = from_api_x3(api);
897 char *iter, *end, save;
899 iter = strdupa(name);
905 if (!save) /* at end? */
908 /* search for the end */
910 while (save && !isspace(save))
914 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
923 static int delete_api_cb(struct afb_api_x3 *api)
925 struct afb_export *export = from_api_x3(api);
927 if (!export->unsealed) {
932 afb_export_undeclare(export);
933 afb_export_unref(export);
937 static struct json_object *settings_cb(struct afb_api_x3 *api)
939 struct afb_export *export = from_api_x3(api);
940 struct json_object *result = export->settings;
942 result = make_settings(export);
946 static int hooked_api_set_verbs_v2_cb(
947 struct afb_api_x3 *api,
948 const struct afb_verb_v2 *verbs)
950 struct afb_export *export = from_api_x3(api);
951 int result = api_set_verbs_v2_cb(api, verbs);
952 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
955 static int hooked_api_set_verbs_v3_cb(
956 struct afb_api_x3 *api,
957 const struct afb_verb_v3 *verbs)
959 struct afb_export *export = from_api_x3(api);
960 int result = api_set_verbs_v3_cb(api, verbs);
961 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
964 static int hooked_api_add_verb_cb(
965 struct afb_api_x3 *api,
968 void (*callback)(struct afb_req_x2 *req),
970 const struct afb_auth *auth,
974 struct afb_export *export = from_api_x3(api);
975 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
976 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
979 static int hooked_api_del_verb_cb(
980 struct afb_api_x3 *api,
984 struct afb_export *export = from_api_x3(api);
985 int result = api_del_verb_cb(api, verb, vcbdata);
986 return afb_hook_api_api_del_verb(export, result, verb);
989 static int hooked_api_set_on_event_cb(
990 struct afb_api_x3 *api,
991 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
993 struct afb_export *export = from_api_x3(api);
994 int result = api_set_on_event_cb(api, onevent);
995 return afb_hook_api_api_set_on_event(export, result);
998 static int hooked_api_set_on_init_cb(
999 struct afb_api_x3 *api,
1000 int (*oninit)(struct afb_api_x3 *api))
1002 struct afb_export *export = from_api_x3(api);
1003 int result = api_set_on_init_cb(api, oninit);
1004 return afb_hook_api_api_set_on_init(export, result);
1007 static void hooked_api_seal_cb(
1008 struct afb_api_x3 *api)
1010 struct afb_export *export = from_api_x3(api);
1011 afb_hook_api_api_seal(export);
1015 static int hooked_event_handler_add_cb(
1016 struct afb_api_x3 *api,
1017 const char *pattern,
1018 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1021 struct afb_export *export = from_api_x3(api);
1022 int result = event_handler_add_cb(api, pattern, callback, closure);
1023 return afb_hook_api_event_handler_add(export, result, pattern);
1026 static int hooked_event_handler_del_cb(
1027 struct afb_api_x3 *api,
1028 const char *pattern,
1031 struct afb_export *export = from_api_x3(api);
1032 int result = event_handler_del_cb(api, pattern, closure);
1033 return afb_hook_api_event_handler_del(export, result, pattern);
1036 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1038 struct afb_export *export = from_api_x3(api);
1039 int result = class_provide_cb(api, name);
1040 return afb_hook_api_class_provide(export, result, name);
1043 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1045 struct afb_export *export = from_api_x3(api);
1046 int result = class_require_cb(api, name);
1047 return afb_hook_api_class_require(export, result, name);
1050 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1052 struct afb_export *export = afb_export_addref(from_api_x3(api));
1053 int result = delete_api_cb(api);
1054 result = afb_hook_api_delete_api(export, result);
1055 afb_export_unref(export);
1059 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1061 struct afb_export *export = from_api_x3(api);
1062 struct json_object *result = settings_cb(api);
1063 result = afb_hook_api_settings(export, result);
1067 static const struct afb_api_x3_itf api_x3_itf = {
1069 .vverbose = (void*)vverbose_cb,
1071 .get_event_loop = afb_systemd_get_event_loop,
1072 .get_user_bus = afb_systemd_get_user_bus,
1073 .get_system_bus = afb_systemd_get_system_bus,
1074 .rootdir_get_fd = afb_common_rootdir_get_fd,
1075 .rootdir_open_locale = rootdir_open_locale_cb,
1076 .queue_job = queue_job_cb,
1078 .require_api = require_api_cb,
1079 .add_alias = add_alias_cb,
1081 .event_broadcast = event_broadcast_cb,
1082 .event_make = event_x2_make_cb,
1084 .legacy_call = legacy_call_x3,
1085 .legacy_call_sync = legacy_call_sync,
1087 .api_new_api = api_new_api_cb,
1088 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1089 .api_add_verb = api_add_verb_cb,
1090 .api_del_verb = api_del_verb_cb,
1091 .api_set_on_event = api_set_on_event_cb,
1092 .api_set_on_init = api_set_on_init_cb,
1093 .api_seal = api_seal_cb,
1094 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1095 .event_handler_add = event_handler_add_cb,
1096 .event_handler_del = event_handler_del_cb,
1099 .call_sync = call_sync_x3,
1101 .class_provide = class_provide_cb,
1102 .class_require = class_require_cb,
1104 .delete_api = delete_api_cb,
1105 .settings = settings_cb,
1108 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1110 .vverbose = hooked_vverbose_cb,
1112 .get_event_loop = hooked_get_event_loop,
1113 .get_user_bus = hooked_get_user_bus,
1114 .get_system_bus = hooked_get_system_bus,
1115 .rootdir_get_fd = hooked_rootdir_get_fd,
1116 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1117 .queue_job = hooked_queue_job_cb,
1119 .require_api = hooked_require_api_cb,
1120 .add_alias = hooked_add_alias_cb,
1122 .event_broadcast = hooked_event_broadcast_cb,
1123 .event_make = hooked_event_x2_make_cb,
1125 .legacy_call = legacy_hooked_call_x3,
1126 .legacy_call_sync = legacy_hooked_call_sync,
1128 .api_new_api = hooked_api_new_api_cb,
1129 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1130 .api_add_verb = hooked_api_add_verb_cb,
1131 .api_del_verb = hooked_api_del_verb_cb,
1132 .api_set_on_event = hooked_api_set_on_event_cb,
1133 .api_set_on_init = hooked_api_set_on_init_cb,
1134 .api_seal = hooked_api_seal_cb,
1135 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1136 .event_handler_add = hooked_event_handler_add_cb,
1137 .event_handler_del = hooked_event_handler_del_cb,
1139 .call = hooked_call_x3,
1140 .call_sync = hooked_call_sync_x3,
1142 .class_provide = hooked_class_provide_cb,
1143 .class_require = hooked_class_require_cb,
1145 .delete_api = hooked_delete_api_cb,
1146 .settings = hooked_settings_cb,
1149 /******************************************************************************
1150 ******************************************************************************
1151 ******************************************************************************
1152 ******************************************************************************
1154 ******************************************************************************
1155 ******************************************************************************
1156 ******************************************************************************
1157 ******************************************************************************/
1160 * Propagates the event to the service
1162 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1164 struct event_handler *handler;
1165 struct afb_export *export = from_api_x3(closure);
1167 /* hook the event before */
1168 if (export->hooksvc & afb_hook_flag_api_on_event)
1169 afb_hook_api_on_event_before(export, event, eventid, object);
1171 /* transmit to specific handlers */
1172 /* search the handler */
1173 handler = export->event_handlers;
1175 if (fnmatch(handler->pattern, event, 0)) {
1176 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1177 handler->callback(handler->closure, event, object, to_api_x3(export));
1179 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1180 handler->callback(handler->closure, event, object, to_api_x3(export));
1181 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1184 handler = handler->next;
1187 /* transmit to default handler */
1188 if (export->on_any_event_v3)
1189 export->on_any_event_v3(to_api_x3(export), event, object);
1190 else if (export->on_any_event_v12)
1191 export->on_any_event_v12(event, object);
1193 /* hook the event after */
1194 if (export->hooksvc & afb_hook_flag_api_on_event)
1195 afb_hook_api_on_event_after(export, event, eventid, object);
1196 json_object_put(object);
1199 /* the interface for events */
1200 static const struct afb_evt_itf evt_itf = {
1201 .broadcast = listener_of_events,
1202 .push = listener_of_events
1205 /* ensure an existing listener */
1206 static int ensure_listener(struct afb_export *export)
1208 if (!export->listener) {
1209 export->listener = afb_evt_listener_create(&evt_itf, export);
1210 if (export->listener == NULL)
1216 int afb_export_event_handler_add(
1217 struct afb_export *export,
1218 const char *pattern,
1219 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1223 struct event_handler *handler, **previous;
1225 rc = ensure_listener(export);
1229 /* search the handler */
1230 previous = &export->event_handlers;
1231 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1232 previous = &handler->next;
1234 /* error if found */
1236 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1241 /* create the event */
1242 handler = malloc(strlen(pattern) + sizeof * handler);
1244 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1249 /* init and record */
1250 handler->next = NULL;
1251 handler->callback = callback;
1252 handler->closure = closure;
1253 strcpy(handler->pattern, pattern);
1254 *previous = handler;
1259 int afb_export_event_handler_del(
1260 struct afb_export *export,
1261 const char *pattern,
1264 struct event_handler *handler, **previous;
1266 /* search the handler */
1267 previous = &export->event_handlers;
1268 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1269 previous = &handler->next;
1271 /* error if found */
1273 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1278 /* remove the found event */
1280 *closure = handler->closure;
1282 *previous = handler->next;
1287 /******************************************************************************
1288 ******************************************************************************
1289 ******************************************************************************
1290 ******************************************************************************
1292 ******************************************************************************
1293 ******************************************************************************
1294 ******************************************************************************
1295 ******************************************************************************/
1297 static struct afb_export *create(
1298 struct afb_apiset *declare_set,
1299 struct afb_apiset *call_set,
1300 const char *apiname,
1302 enum afb_api_version version)
1304 struct afb_export *export;
1307 /* session shared with other exports */
1308 if (common_session == NULL) {
1309 common_session = afb_session_create (0);
1310 if (common_session == NULL)
1313 lenapi = strlen(apiname);
1314 export = calloc(1, sizeof *export + lenapi + (path == apiname || !path ? 0 : strlen(path)));
1318 export->refcount = 1;
1319 strcpy(export->name, apiname);
1320 export->api.apiname = export->name;
1321 if (path == apiname)
1322 export->path = export->name;
1324 export->path = strcpy(&export->name[lenapi + 1], path);
1325 export->version = version;
1326 export->state = Api_State_Pre_Init;
1327 export->session = afb_session_addref(common_session);
1328 export->declare_set = afb_apiset_addref(declare_set);
1329 export->call_set = afb_apiset_addref(call_set);
1334 struct afb_export *afb_export_addref(struct afb_export *export)
1337 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1341 void afb_export_unref(struct afb_export *export)
1343 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1344 afb_export_destroy(export);
1347 void afb_export_destroy(struct afb_export *export)
1349 struct event_handler *handler;
1352 while ((handler = export->event_handlers)) {
1353 export->event_handlers = handler->next;
1356 if (export->listener != NULL)
1357 afb_evt_listener_unref(export->listener);
1358 afb_session_unref(export->session);
1359 afb_apiset_unref(export->declare_set);
1360 afb_apiset_unref(export->call_set);
1361 json_object_put(export->settings);
1362 afb_export_unref(export->creator);
1363 if (export->api.apiname != export->name)
1364 free((void*)export->api.apiname);
1369 struct afb_export *afb_export_create_none_for_path(
1370 struct afb_apiset *declare_set,
1371 struct afb_apiset *call_set,
1373 int (*creator)(void*, struct afb_api_x3*),
1376 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1378 afb_export_logmask_set(export, logmask);
1379 afb_export_update_hooks(export);
1380 if (creator && creator(closure, to_api_x3(export)) < 0) {
1381 afb_export_unref(export);
1388 #if defined(WITH_LEGACY_BINDING_V1)
1389 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1390 struct afb_apiset *call_set,
1391 const char *apiname,
1392 int (*init)(struct afb_service_x1),
1393 void (*onevent)(const char*, struct json_object*),
1396 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1398 export->init.v1 = init;
1399 export->on_any_event_v12 = onevent;
1400 export->export.v1.mode = AFB_MODE_LOCAL;
1401 export->export.v1.daemon.closure = to_api_x3(export);
1402 afb_export_logmask_set(export, logmask);
1403 afb_export_update_hooks(export);
1409 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1410 struct afb_apiset *call_set,
1411 const char *apiname,
1412 const struct afb_binding_v2 *binding,
1413 struct afb_binding_data_v2 *data,
1415 void (*onevent)(const char*, struct json_object*),
1418 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1420 export->init.v2 = init;
1421 export->on_any_event_v12 = onevent;
1422 export->desc.v2 = binding;
1423 export->export.v2 = data;
1424 data->daemon.closure = to_api_x3(export);
1425 data->service.closure = to_api_x3(export);
1426 afb_export_logmask_set(export, logmask);
1427 afb_export_update_hooks(export);
1432 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1433 struct afb_apiset *call_set,
1434 const char *apiname,
1435 struct afb_api_v3 *apiv3,
1436 struct afb_export* creator,
1439 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1441 export->unsealed = 1;
1442 export->desc.v3 = apiv3;
1443 export->creator = afb_export_addref(creator);
1444 afb_export_logmask_set(export, logmask);
1445 afb_export_update_hooks(export);
1450 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1452 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1455 int afb_export_rename(struct afb_export *export, const char *apiname)
1459 if (export->declared) {
1464 /* copy the name locally */
1465 name = strdup(apiname);
1471 if (export->api.apiname != export->name)
1472 free((void*)export->api.apiname);
1473 export->api.apiname = name;
1475 afb_export_update_hooks(export);
1479 const char *afb_export_apiname(const struct afb_export *export)
1481 return export->api.apiname;
1484 void afb_export_update_hooks(struct afb_export *export)
1486 export->hookditf = afb_hook_flags_api(export->api.apiname);
1487 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1488 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1490 switch (export->version) {
1491 #if defined(WITH_LEGACY_BINDING_V1)
1493 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1497 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1498 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1503 int afb_export_unshare_session(struct afb_export *export)
1505 if (export->session == common_session) {
1506 export->session = afb_session_create (0);
1507 if (export->session)
1508 afb_session_unref(common_session);
1510 export->session = common_session;
1517 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1520 switch (export->version) {
1521 #if defined(WITH_LEGACY_BINDING_V1)
1527 ERROR("invalid version 12 for API %s", export->api.apiname);
1532 export->on_any_event_v12 = on_event;
1533 return ensure_listener(export);
1536 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))
1539 switch (export->version) {
1540 case Api_Version_3: break;
1542 ERROR("invalid version Dyn for API %s", export->api.apiname);
1547 export->on_any_event_v3 = on_event;
1548 return ensure_listener(export);
1551 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1553 if (export->state != Api_State_Pre_Init) {
1554 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1559 export->init.v3 = oninit;
1563 #if defined(WITH_LEGACY_BINDING_V1)
1565 * Starts a new service (v1)
1567 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1569 return export->desc.v1 = regfun(&export->export.v1);
1573 int afb_export_preinit_x3(
1574 struct afb_export *export,
1575 int (*preinit)(void*, struct afb_api_x3*),
1578 return preinit(closure, to_api_x3(export));
1581 int afb_export_logmask_get(const struct afb_export *export)
1583 return export->api.logmask;
1586 void afb_export_logmask_set(struct afb_export *export, int mask)
1588 export->api.logmask = mask;
1589 switch (export->version) {
1590 #if defined(WITH_LEGACY_BINDING_V1)
1591 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1593 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1597 void *afb_export_userdata_get(const struct afb_export *export)
1599 return export->api.userdata;
1602 void afb_export_userdata_set(struct afb_export *export, void *data)
1604 export->api.userdata = data;
1607 /******************************************************************************
1608 ******************************************************************************
1609 ******************************************************************************
1610 ******************************************************************************
1612 ******************************************************************************
1613 ******************************************************************************
1614 ******************************************************************************
1615 ******************************************************************************/
1620 struct afb_export *export;
1623 static void do_init(int sig, void *closure)
1626 struct init *init = closure;
1627 struct afb_export *export;
1632 export = init->export;
1633 switch (export->version) {
1634 #if defined(WITH_LEGACY_BINDING_V1)
1636 rc = export->init.v1 ? export->init.v1(
1637 (struct afb_service_x1){
1638 .itf = &hooked_service_itf,
1639 .closure = to_api_x3(export) }) : 0;
1643 rc = export->init.v2 ? export->init.v2() : 0;
1646 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1653 init->return_code = rc;
1657 int afb_export_start(struct afb_export *export)
1663 switch (export->state) {
1667 case Api_State_Init:
1668 /* starting in progress: it is an error */
1669 ERROR("Service of API %s required started while starting", export->api.apiname);
1676 /* set event handling */
1677 switch (export->version) {
1678 #if defined(WITH_LEGACY_BINDING_V1)
1682 if (export->on_any_event_v12) {
1683 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1692 ERROR("Can't set event handler for %s", export->api.apiname);
1696 /* Starts the service */
1697 if (export->hooksvc & afb_hook_flag_api_start)
1698 afb_hook_api_start_before(export);
1700 export->state = Api_State_Init;
1701 init.export = export;
1702 sig_monitor(0, do_init, &init);
1703 rc = init.return_code;
1704 export->state = Api_State_Run;
1706 if (export->hooksvc & afb_hook_flag_api_start)
1707 afb_hook_api_start_after(export, rc);
1710 /* initialisation error */
1711 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1718 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1720 struct afb_export *export = closure;
1722 xreq->request.api = to_api_x3(export);
1724 switch (export->version) {
1725 #if defined(WITH_LEGACY_BINDING_V1)
1727 afb_api_so_v1_process_call(export->desc.v1, xreq);
1731 afb_api_so_v2_process_call(export->desc.v2, xreq);
1734 afb_api_v3_process_call(export->desc.v3, xreq);
1737 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1742 static struct json_object *api_describe_cb(void *closure)
1744 struct afb_export *export = closure;
1745 struct json_object *result;
1747 switch (export->version) {
1748 #if defined(WITH_LEGACY_BINDING_V1)
1750 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1754 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1757 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1766 static int api_service_start_cb(void *closure)
1768 struct afb_export *export = closure;
1770 return afb_export_start(export);
1773 static void api_update_hooks_cb(void *closure)
1775 struct afb_export *export = closure;
1777 afb_export_update_hooks(export);
1780 static int api_get_logmask_cb(void *closure)
1782 struct afb_export *export = closure;
1784 return afb_export_logmask_get(export);
1787 static void api_set_logmask_cb(void *closure, int level)
1789 struct afb_export *export = closure;
1791 afb_export_logmask_set(export, level);
1794 static void api_unref_cb(void *closure)
1796 struct afb_export *export = closure;
1798 afb_export_unref(export);
1801 static struct afb_api_itf export_api_itf =
1803 .call = api_call_cb,
1804 .service_start = api_service_start_cb,
1805 .update_hooks = api_update_hooks_cb,
1806 .get_logmask = api_get_logmask_cb,
1807 .set_logmask = api_set_logmask_cb,
1808 .describe = api_describe_cb,
1809 .unref = api_unref_cb
1812 int afb_export_declare(struct afb_export *export,
1816 struct afb_api_item afb_api;
1818 if (export->declared)
1821 /* init the record structure */
1822 afb_api.closure = afb_export_addref(export);
1823 afb_api.itf = &export_api_itf;
1824 afb_api.group = noconcurrency ? export : NULL;
1826 /* records the binding */
1827 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1829 export->declared = 1;
1831 ERROR("can't declare export %s to set %s, ABORTING it!",
1832 export->api.apiname,
1833 afb_apiset_name(export->declare_set));
1834 afb_export_unref(export);
1841 void afb_export_undeclare(struct afb_export *export)
1843 if (export->declared) {
1844 export->declared = 0;
1845 afb_apiset_del(export->declare_set, export->api.apiname);
1849 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1851 return afb_evt_event_x2_add_watch(export->listener, event);
1854 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1856 return afb_evt_event_x2_remove_watch(export->listener, event);
1859 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1861 afb_xreq_process(xreq, export->call_set);
1864 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1866 afb_context_init(context, export->session, NULL);
1867 context->validated = 1;