2 * Copyright (C) 2016-2019 "IoT.bzh"
3 * Author: José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
26 #include <json-c/json.h>
27 #if !defined(JSON_C_TO_STRING_NOSLASHESCAPE)
28 #define JSON_C_TO_STRING_NOSLASHESCAPE 0
31 #define AFB_BINDING_VERSION 0
32 #include <afb/afb-binding.h>
35 #include "afb-apiset.h"
36 #if defined(WITH_LEGACY_BINDING_V1)
37 #include "afb-api-so-v1.h"
39 #include "afb-api-so-v2.h"
40 #include "afb-api-v3.h"
41 #include "afb-common.h"
44 #include "afb-export.h"
46 #include "afb-msg-json.h"
47 #include "afb-session.h"
49 #include "afb-calls.h"
55 #include "sig-monitor.h"
56 #include "wrap-json.h"
58 /*************************************************************************
60 ************************************************************************/
63 * Actually supported versions
68 #if defined(WITH_LEGACY_BINDING_V1)
76 * The states of exported APIs
86 * structure of the exported API
91 struct afb_api_x3 api;
96 /* version of the api */
103 unsigned declared: 1;
106 unsigned unsealed: 1;
114 /* session for service */
115 struct afb_session *session;
117 /* apiset the API is declared in */
118 struct afb_apiset *declare_set;
120 /* apiset for calls */
121 struct afb_apiset *call_set;
123 /* event listener for service or NULL */
124 struct afb_evt_listener *listener;
126 /* event handler list */
127 struct globset *event_handlers;
130 struct afb_export *creator;
132 /* path indication if any */
136 struct json_object *settings;
138 /* internal descriptors */
140 #if defined(WITH_LEGACY_BINDING_V1)
141 struct afb_binding_v1 *v1;
143 const struct afb_binding_v2 *v2;
144 struct afb_api_v3 *v3;
149 #if defined(WITH_LEGACY_BINDING_V1)
150 int (*v1)(struct afb_service_x1);
153 int (*v3)(struct afb_api_x3 *api);
157 void (*on_any_event_v12)(const char *event, struct json_object *object);
158 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
162 #if defined(WITH_LEGACY_BINDING_V1)
163 struct afb_binding_interface_v1 v1;
165 struct afb_binding_data_v2 *v2;
172 /*****************************************************************************/
174 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
176 return (struct afb_api_x3*)export;
179 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
181 return (struct afb_export*)api;
184 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
186 return from_api_x3(api);
189 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
191 return to_api_x3(export);
194 /******************************************************************************
195 ******************************************************************************
196 ******************************************************************************
197 ******************************************************************************
199 ******************************************************************************
200 ******************************************************************************
201 ******************************************************************************
202 ******************************************************************************/
204 static struct json_object *configuration;
206 void afb_export_set_config(struct json_object *config)
208 struct json_object *save = configuration;
209 configuration = json_object_get(config);
210 json_object_put(save);
213 static struct json_object *make_settings(struct afb_export *export)
215 struct json_object *result;
216 struct json_object *obj;
217 struct afb_export *iter;
220 /* clone the globals */
221 if (json_object_object_get_ex(configuration, "*", &obj))
222 result = wrap_json_clone(obj);
224 result = json_object_new_object();
227 if (json_object_object_get_ex(configuration, export->name, &obj))
228 wrap_json_object_add(result, obj);
230 /* add library path */
231 for (iter = export ; iter && !iter->path ; iter = iter->creator);
233 path = realpath(iter->path, NULL);
234 json_object_object_add(result, "binding-path", json_object_new_string(path));
238 export->settings = result;
242 /******************************************************************************
243 ******************************************************************************
244 ******************************************************************************
245 ******************************************************************************
247 ******************************************************************************
248 ******************************************************************************
249 ******************************************************************************
250 ******************************************************************************/
252 /**********************************************
254 **********************************************/
255 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)
258 struct afb_export *export = from_api_x3(closure);
260 if (!fmt || vasprintf(&p, fmt, args) < 0)
261 vverbose(level, file, line, function, fmt, args);
263 verbose(level, file, line, function, (verbose_is_colorized() == 0 ? "[API %s] %s" : COLOR_API "[API %s]" COLOR_DEFAULT " %s"), export->api.apiname, p);
268 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
270 vverbose_cb(closure, level, file, line, NULL, fmt, args);
273 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
275 struct afb_export *export = from_api_x3(closure);
277 /* check daemon state */
278 if (export->state == Api_State_Pre_Init) {
279 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
284 /* create the event */
285 return afb_evt_event_x2_create2(export->api.apiname, name);
288 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
290 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
291 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
294 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
298 struct afb_export *export = from_api_x3(closure);
300 /* check daemon state */
301 if (export->state == Api_State_Pre_Init) {
302 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
303 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
308 /* makes the event name */
309 plen = strlen(export->api.apiname);
311 event = alloca(nlen + plen + 2);
312 memcpy(event, export->api.apiname, plen);
314 memcpy(event + plen + 1, name, nlen + 1);
316 /* broadcast the event */
317 return afb_evt_broadcast(event, object);
320 static struct sd_event *get_event_loop(struct afb_api_x3 *closure)
322 jobs_acquire_event_manager();
323 return systemd_get_event_loop();
326 static struct sd_bus *get_user_bus(struct afb_api_x3 *closure)
328 jobs_acquire_event_manager();
329 return systemd_get_user_bus();
332 static struct sd_bus *get_system_bus(struct afb_api_x3 *closure)
334 jobs_acquire_event_manager();
335 return systemd_get_system_bus();
338 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
340 return afb_common_rootdir_open_locale(filename, flags, locale);
343 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
345 return jobs_queue(group, timeout, callback, argument);
348 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
350 return afb_xreq_unstore(sreq);
353 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
355 struct afb_export *export = from_api_x3(closure);
357 char *iter, *end, save;
359 /* emit a warning about unexpected require in preinit */
360 if (export->state == Api_State_Pre_Init)
361 WARNING("[API %s] requiring apis in pre-init may lead to unexpected result (requires%s: %s)",
362 export->api.apiname, initialized ? " initialized" : "", name);
364 /* scan the names in a local copy */
366 iter = strdupa(name);
372 if (!save) /* at end? */
375 /* search for the end */
377 while (save && !isspace(save))
381 /* check the required api */
382 if (export->state == Api_State_Pre_Init)
383 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
385 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
394 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
396 struct afb_export *export = from_api_x3(closure);
397 if (!afb_api_is_valid_name(aliasname)) {
398 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
402 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
403 afb_export_add_alias(export, apiname, aliasname);
407 static struct afb_api_x3 *api_new_api_cb(
408 struct afb_api_x3 *closure,
412 int (*preinit)(void*, struct afb_api_x3 *),
413 void *preinit_closure)
415 struct afb_export *export = from_api_x3(closure);
416 struct afb_api_v3 *apiv3 = afb_api_v3_create(
417 export->declare_set, export->call_set,
418 api, info, noconcurrency,
419 preinit, preinit_closure, 1,
421 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
424 static const struct afb_daemon_itf_x1 daemon_itf = {
425 .vverbose_v1 = legacy_vverbose_v1_cb,
426 .vverbose_v2 = vverbose_cb,
427 .event_make = legacy_event_x1_make_cb,
428 .event_broadcast = event_broadcast_cb,
429 .get_event_loop = get_event_loop,
430 .get_user_bus = get_user_bus,
431 .get_system_bus = get_system_bus,
432 .rootdir_get_fd = afb_common_rootdir_get_fd,
433 .rootdir_open_locale = rootdir_open_locale_cb,
434 .queue_job = queue_job_cb,
435 .unstore_req = legacy_unstore_req_cb,
436 .require_api = require_api_cb,
437 .add_alias = add_alias_cb,
438 .new_api = api_new_api_cb,
442 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)
444 struct afb_export *export = from_api_x3(closure);
447 vverbose_cb(closure, level, file, line, function, fmt, args);
448 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
452 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)
454 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
457 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
459 struct afb_export *export = from_api_x3(closure);
460 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
461 afb_hook_api_event_make(export, name, r);
465 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
467 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
468 struct afb_event_x1 e;
470 e.itf = event ? event->itf : NULL;
474 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
477 struct afb_export *export = from_api_x3(closure);
478 json_object_get(object);
479 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
480 r = event_broadcast_cb(closure, name, object);
481 afb_hook_api_event_broadcast_after(export, name, object, r);
482 json_object_put(object);
486 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
488 struct afb_export *export = from_api_x3(closure);
491 jobs_acquire_event_manager();
492 r = get_event_loop(closure);
493 return afb_hook_api_get_event_loop(export, r);
496 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
498 struct afb_export *export = from_api_x3(closure);
501 jobs_acquire_event_manager();
502 r = get_user_bus(closure);
503 return afb_hook_api_get_user_bus(export, r);
506 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
508 struct afb_export *export = from_api_x3(closure);
511 jobs_acquire_event_manager();
512 r = get_system_bus(closure);
513 return afb_hook_api_get_system_bus(export, r);
516 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
518 struct afb_export *export = from_api_x3(closure);
519 int r = afb_common_rootdir_get_fd();
520 return afb_hook_api_rootdir_get_fd(export, r);
523 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
525 struct afb_export *export = from_api_x3(closure);
526 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
527 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
530 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
532 struct afb_export *export = from_api_x3(closure);
533 int r = queue_job_cb(closure, callback, argument, group, timeout);
534 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
537 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
539 struct afb_export *export = from_api_x3(closure);
540 afb_hook_api_legacy_unstore_req(export, sreq);
541 return legacy_unstore_req_cb(closure, sreq);
544 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
547 struct afb_export *export = from_api_x3(closure);
548 afb_hook_api_require_api(export, name, initialized);
549 result = require_api_cb(closure, name, initialized);
550 return afb_hook_api_require_api_result(export, name, initialized, result);
553 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
555 struct afb_export *export = from_api_x3(closure);
556 int result = add_alias_cb(closure, apiname, aliasname);
557 return afb_hook_api_add_alias(export, apiname, aliasname, result);
560 static struct afb_api_x3 *hooked_api_new_api_cb(
561 struct afb_api_x3 *closure,
565 int (*preinit)(void*, struct afb_api_x3 *),
566 void *preinit_closure)
568 struct afb_api_x3 *result;
569 struct afb_export *export = from_api_x3(closure);
570 afb_hook_api_new_api_before(export, api, info, noconcurrency);
571 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
572 afb_hook_api_new_api_after(export, -!result, api);
576 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
577 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
578 .vverbose_v2 = hooked_vverbose_cb,
579 .event_make = legacy_hooked_event_x1_make_cb,
580 .event_broadcast = hooked_event_broadcast_cb,
581 .get_event_loop = hooked_get_event_loop,
582 .get_user_bus = hooked_get_user_bus,
583 .get_system_bus = hooked_get_system_bus,
584 .rootdir_get_fd = hooked_rootdir_get_fd,
585 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
586 .queue_job = hooked_queue_job_cb,
587 .unstore_req = legacy_hooked_unstore_req_cb,
588 .require_api = hooked_require_api_cb,
589 .add_alias = hooked_add_alias_cb,
590 .new_api = hooked_api_new_api_cb,
594 /******************************************************************************
595 ******************************************************************************
596 ******************************************************************************
597 ******************************************************************************
599 ******************************************************************************
600 ******************************************************************************
601 ******************************************************************************
602 ******************************************************************************/
604 /* the common session for services sharing their session */
605 static struct afb_session *common_session;
607 /******************************************************************************
608 ******************************************************************************
609 ******************************************************************************
610 ******************************************************************************
612 ******************************************************************************
613 ******************************************************************************
614 ******************************************************************************
615 ******************************************************************************/
618 struct afb_api_x3 *apix3,
621 struct json_object *args,
622 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
625 struct afb_export *export = from_api_x3(apix3);
626 return afb_calls_call(export, api, verb, args, callback, closure);
629 static int call_sync_x3(
630 struct afb_api_x3 *apix3,
633 struct json_object *args,
634 struct json_object **object,
638 struct afb_export *export = from_api_x3(apix3);
639 return afb_calls_call_sync(export, api, verb, args, object, error, info);
642 static void legacy_call_v12(
643 struct afb_api_x3 *apix3,
646 struct json_object *args,
647 void (*callback)(void*, int, struct json_object*),
650 struct afb_export *export = from_api_x3(apix3);
651 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
654 static void legacy_call_x3(
655 struct afb_api_x3 *apix3,
658 struct json_object *args,
659 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
662 struct afb_export *export = from_api_x3(apix3);
663 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
666 static int legacy_call_sync(
667 struct afb_api_x3 *apix3,
670 struct json_object *args,
671 struct json_object **result)
673 struct afb_export *export = from_api_x3(apix3);
674 return afb_calls_legacy_call_sync(export, api, verb, args, result);
677 /* the interface for services */
678 static const struct afb_service_itf_x1 service_itf = {
679 .call = legacy_call_v12,
680 .call_sync = legacy_call_sync
684 static void hooked_call_x3(
685 struct afb_api_x3 *apix3,
688 struct json_object *args,
689 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
692 struct afb_export *export = from_api_x3(apix3);
693 afb_calls_hooked_call(export, api, verb, args, callback, closure);
696 static int hooked_call_sync_x3(
697 struct afb_api_x3 *apix3,
700 struct json_object *args,
701 struct json_object **object,
705 struct afb_export *export = from_api_x3(apix3);
706 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
709 static void legacy_hooked_call_v12(
710 struct afb_api_x3 *apix3,
713 struct json_object *args,
714 void (*callback)(void*, int, struct json_object*),
717 struct afb_export *export = from_api_x3(apix3);
718 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
721 static void legacy_hooked_call_x3(
722 struct afb_api_x3 *apix3,
725 struct json_object *args,
726 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
729 struct afb_export *export = from_api_x3(apix3);
730 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
733 static int legacy_hooked_call_sync(
734 struct afb_api_x3 *apix3,
737 struct json_object *args,
738 struct json_object **result)
740 struct afb_export *export = from_api_x3(apix3);
741 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
744 /* the interface for services */
745 static const struct afb_service_itf_x1 hooked_service_itf = {
746 .call = legacy_hooked_call_v12,
747 .call_sync = legacy_hooked_call_sync
751 /******************************************************************************
752 ******************************************************************************
753 ******************************************************************************
754 ******************************************************************************
756 ******************************************************************************
757 ******************************************************************************
758 ******************************************************************************
759 ******************************************************************************/
761 static int api_set_verbs_v2_cb(
762 struct afb_api_x3 *api,
763 const struct afb_verb_v2 *verbs)
765 struct afb_export *export = from_api_x3(api);
767 if (export->unsealed) {
768 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
776 static int api_set_verbs_v3_cb(
777 struct afb_api_x3 *api,
778 const struct afb_verb_v3 *verbs)
780 struct afb_export *export = from_api_x3(api);
782 if (!export->unsealed) {
787 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
791 static int api_add_verb_cb(
792 struct afb_api_x3 *api,
795 void (*callback)(struct afb_req_x2 *req),
797 const struct afb_auth *auth,
801 struct afb_export *export = from_api_x3(api);
803 if (!export->unsealed) {
808 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
811 static int api_del_verb_cb(
812 struct afb_api_x3 *api,
816 struct afb_export *export = from_api_x3(api);
818 if (!export->unsealed) {
823 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
826 static int api_set_on_event_cb(
827 struct afb_api_x3 *api,
828 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
830 struct afb_export *export = from_api_x3(api);
831 return afb_export_handle_events_v3(export, onevent);
834 static int api_set_on_init_cb(
835 struct afb_api_x3 *api,
836 int (*oninit)(struct afb_api_x3 *api))
838 struct afb_export *export = from_api_x3(api);
840 return afb_export_handle_init_v3(export, oninit);
843 static void api_seal_cb(
844 struct afb_api_x3 *api)
846 struct afb_export *export = from_api_x3(api);
848 export->unsealed = 0;
851 static int event_handler_add_cb(
852 struct afb_api_x3 *api,
854 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
857 struct afb_export *export = from_api_x3(api);
859 return afb_export_event_handler_add(export, pattern, callback, closure);
862 static int event_handler_del_cb(
863 struct afb_api_x3 *api,
867 struct afb_export *export = from_api_x3(api);
869 return afb_export_event_handler_del(export, pattern, closure);
872 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
874 struct afb_export *export = from_api_x3(api);
877 char *iter, *end, save;
879 iter = strdupa(name);
885 if (!save) /* at end? */
888 /* search for the end */
890 while (save && !isspace(save))
894 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
903 static int class_require_cb(struct afb_api_x3 *api, const char *name)
905 struct afb_export *export = from_api_x3(api);
908 char *iter, *end, save;
910 iter = strdupa(name);
916 if (!save) /* at end? */
919 /* search for the end */
921 while (save && !isspace(save))
925 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
934 static int delete_api_cb(struct afb_api_x3 *api)
936 struct afb_export *export = from_api_x3(api);
938 if (!export->unsealed) {
943 afb_export_undeclare(export);
944 afb_export_unref(export);
948 static struct json_object *settings_cb(struct afb_api_x3 *api)
950 struct afb_export *export = from_api_x3(api);
951 struct json_object *result = export->settings;
953 result = make_settings(export);
957 static const struct afb_api_x3_itf api_x3_itf = {
959 .vverbose = (void*)vverbose_cb,
961 .get_event_loop = get_event_loop,
962 .get_user_bus = get_user_bus,
963 .get_system_bus = get_system_bus,
964 .rootdir_get_fd = afb_common_rootdir_get_fd,
965 .rootdir_open_locale = rootdir_open_locale_cb,
966 .queue_job = queue_job_cb,
968 .require_api = require_api_cb,
969 .add_alias = add_alias_cb,
971 .event_broadcast = event_broadcast_cb,
972 .event_make = event_x2_make_cb,
974 .legacy_call = legacy_call_x3,
975 .legacy_call_sync = legacy_call_sync,
977 .api_new_api = api_new_api_cb,
978 .api_set_verbs_v2 = api_set_verbs_v2_cb,
979 .api_add_verb = api_add_verb_cb,
980 .api_del_verb = api_del_verb_cb,
981 .api_set_on_event = api_set_on_event_cb,
982 .api_set_on_init = api_set_on_init_cb,
983 .api_seal = api_seal_cb,
984 .api_set_verbs_v3 = api_set_verbs_v3_cb,
985 .event_handler_add = event_handler_add_cb,
986 .event_handler_del = event_handler_del_cb,
989 .call_sync = call_sync_x3,
991 .class_provide = class_provide_cb,
992 .class_require = class_require_cb,
994 .delete_api = delete_api_cb,
995 .settings = settings_cb,
999 static int hooked_api_set_verbs_v2_cb(
1000 struct afb_api_x3 *api,
1001 const struct afb_verb_v2 *verbs)
1003 struct afb_export *export = from_api_x3(api);
1004 int result = api_set_verbs_v2_cb(api, verbs);
1005 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
1008 static int hooked_api_set_verbs_v3_cb(
1009 struct afb_api_x3 *api,
1010 const struct afb_verb_v3 *verbs)
1012 struct afb_export *export = from_api_x3(api);
1013 int result = api_set_verbs_v3_cb(api, verbs);
1014 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
1017 static int hooked_api_add_verb_cb(
1018 struct afb_api_x3 *api,
1021 void (*callback)(struct afb_req_x2 *req),
1023 const struct afb_auth *auth,
1027 struct afb_export *export = from_api_x3(api);
1028 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
1029 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
1032 static int hooked_api_del_verb_cb(
1033 struct afb_api_x3 *api,
1037 struct afb_export *export = from_api_x3(api);
1038 int result = api_del_verb_cb(api, verb, vcbdata);
1039 return afb_hook_api_api_del_verb(export, result, verb);
1042 static int hooked_api_set_on_event_cb(
1043 struct afb_api_x3 *api,
1044 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
1046 struct afb_export *export = from_api_x3(api);
1047 int result = api_set_on_event_cb(api, onevent);
1048 return afb_hook_api_api_set_on_event(export, result);
1051 static int hooked_api_set_on_init_cb(
1052 struct afb_api_x3 *api,
1053 int (*oninit)(struct afb_api_x3 *api))
1055 struct afb_export *export = from_api_x3(api);
1056 int result = api_set_on_init_cb(api, oninit);
1057 return afb_hook_api_api_set_on_init(export, result);
1060 static void hooked_api_seal_cb(
1061 struct afb_api_x3 *api)
1063 struct afb_export *export = from_api_x3(api);
1064 afb_hook_api_api_seal(export);
1068 static int hooked_event_handler_add_cb(
1069 struct afb_api_x3 *api,
1070 const char *pattern,
1071 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1074 struct afb_export *export = from_api_x3(api);
1075 int result = event_handler_add_cb(api, pattern, callback, closure);
1076 return afb_hook_api_event_handler_add(export, result, pattern);
1079 static int hooked_event_handler_del_cb(
1080 struct afb_api_x3 *api,
1081 const char *pattern,
1084 struct afb_export *export = from_api_x3(api);
1085 int result = event_handler_del_cb(api, pattern, closure);
1086 return afb_hook_api_event_handler_del(export, result, pattern);
1089 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1091 struct afb_export *export = from_api_x3(api);
1092 int result = class_provide_cb(api, name);
1093 return afb_hook_api_class_provide(export, result, name);
1096 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1098 struct afb_export *export = from_api_x3(api);
1099 int result = class_require_cb(api, name);
1100 return afb_hook_api_class_require(export, result, name);
1103 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1105 struct afb_export *export = afb_export_addref(from_api_x3(api));
1106 int result = delete_api_cb(api);
1107 result = afb_hook_api_delete_api(export, result);
1108 afb_export_unref(export);
1112 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1114 struct afb_export *export = from_api_x3(api);
1115 struct json_object *result = settings_cb(api);
1116 result = afb_hook_api_settings(export, result);
1120 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1122 .vverbose = hooked_vverbose_cb,
1124 .get_event_loop = hooked_get_event_loop,
1125 .get_user_bus = hooked_get_user_bus,
1126 .get_system_bus = hooked_get_system_bus,
1127 .rootdir_get_fd = hooked_rootdir_get_fd,
1128 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1129 .queue_job = hooked_queue_job_cb,
1131 .require_api = hooked_require_api_cb,
1132 .add_alias = hooked_add_alias_cb,
1134 .event_broadcast = hooked_event_broadcast_cb,
1135 .event_make = hooked_event_x2_make_cb,
1137 .legacy_call = legacy_hooked_call_x3,
1138 .legacy_call_sync = legacy_hooked_call_sync,
1140 .api_new_api = hooked_api_new_api_cb,
1141 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1142 .api_add_verb = hooked_api_add_verb_cb,
1143 .api_del_verb = hooked_api_del_verb_cb,
1144 .api_set_on_event = hooked_api_set_on_event_cb,
1145 .api_set_on_init = hooked_api_set_on_init_cb,
1146 .api_seal = hooked_api_seal_cb,
1147 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1148 .event_handler_add = hooked_event_handler_add_cb,
1149 .event_handler_del = hooked_event_handler_del_cb,
1151 .call = hooked_call_x3,
1152 .call_sync = hooked_call_sync_x3,
1154 .class_provide = hooked_class_provide_cb,
1155 .class_require = hooked_class_require_cb,
1157 .delete_api = hooked_delete_api_cb,
1158 .settings = hooked_settings_cb,
1162 /******************************************************************************
1163 ******************************************************************************
1164 ******************************************************************************
1165 ******************************************************************************
1167 ******************************************************************************
1168 ******************************************************************************
1169 ******************************************************************************
1170 ******************************************************************************/
1173 * Propagates the event to the service
1175 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1177 const struct globset_handler *handler;
1178 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
1179 struct afb_export *export = from_api_x3(closure);
1182 /* hook the event before */
1183 if (export->hooksvc & afb_hook_flag_api_on_event)
1184 afb_hook_api_on_event_before(export, event, eventid, object);
1187 /* transmit to specific handlers */
1188 /* search the handler */
1189 handler = export->event_handlers ? globset_match(export->event_handlers, event) : NULL;
1191 callback = handler->callback;
1193 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1195 callback(handler->closure, event, object, to_api_x3(export));
1198 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1199 callback(handler->closure, event, object, to_api_x3(export));
1200 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1204 /* transmit to default handler */
1205 if (export->on_any_event_v3)
1206 export->on_any_event_v3(to_api_x3(export), event, object);
1207 else if (export->on_any_event_v12)
1208 export->on_any_event_v12(event, object);
1212 /* hook the event after */
1213 if (export->hooksvc & afb_hook_flag_api_on_event)
1214 afb_hook_api_on_event_after(export, event, eventid, object);
1216 json_object_put(object);
1219 /* the interface for events */
1220 static const struct afb_evt_itf evt_itf = {
1221 .broadcast = listener_of_events,
1222 .push = listener_of_events
1225 /* ensure an existing listener */
1226 static int ensure_listener(struct afb_export *export)
1228 if (!export->listener) {
1229 export->listener = afb_evt_listener_create(&evt_itf, export);
1230 if (export->listener == NULL)
1236 int afb_export_event_handler_add(
1237 struct afb_export *export,
1238 const char *pattern,
1239 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1244 /* ensure the listener */
1245 rc = ensure_listener(export);
1249 /* ensure the globset for event handling */
1250 if (!export->event_handlers) {
1251 export->event_handlers = globset_create();
1252 if (!export->event_handlers)
1256 /* add the handler */
1257 rc = globset_add(export->event_handlers, pattern, callback, closure);
1261 if (errno == EEXIST) {
1262 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1267 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1271 int afb_export_event_handler_del(
1272 struct afb_export *export,
1273 const char *pattern,
1276 if (export->event_handlers
1277 && !globset_del(export->event_handlers, pattern, closure))
1280 ERROR("[API %s] event handler %s not found", export->api.apiname, pattern);
1285 /******************************************************************************
1286 ******************************************************************************
1287 ******************************************************************************
1288 ******************************************************************************
1290 ******************************************************************************
1291 ******************************************************************************
1292 ******************************************************************************
1293 ******************************************************************************/
1295 static void set_interfaces(struct afb_export *export)
1298 export->hookditf = afb_hook_flags_api(export->api.apiname);
1299 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1300 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1302 switch (export->version) {
1303 #if defined(WITH_LEGACY_BINDING_V1)
1305 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1309 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1310 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1315 export->api.itf = &api_x3_itf;
1317 switch (export->version) {
1318 #if defined(WITH_LEGACY_BINDING_V1)
1320 export->export.v1.daemon.itf = &daemon_itf;
1324 export->export.v2->daemon.itf = &daemon_itf;
1325 export->export.v2->service.itf = &service_itf;
1332 static struct afb_export *create(
1333 struct afb_apiset *declare_set,
1334 struct afb_apiset *call_set,
1335 const char *apiname,
1337 enum afb_api_version version)
1339 struct afb_export *export;
1342 /* session shared with other exports */
1343 if (common_session == NULL) {
1344 common_session = afb_session_create (0);
1345 if (common_session == NULL)
1348 lenapi = strlen(apiname);
1349 export = calloc(1, sizeof *export + lenapi + (path == apiname || !path ? 0 : strlen(path)));
1353 export->refcount = 1;
1354 strcpy(export->name, apiname);
1355 export->api.apiname = export->name;
1356 if (path == apiname)
1357 export->path = export->name;
1359 export->path = strcpy(&export->name[lenapi + 1], path);
1360 export->version = version;
1361 export->state = Api_State_Pre_Init;
1362 export->session = afb_session_addref(common_session);
1363 export->declare_set = afb_apiset_addref(declare_set);
1364 export->call_set = afb_apiset_addref(call_set);
1369 struct afb_export *afb_export_addref(struct afb_export *export)
1372 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1376 void afb_export_unref(struct afb_export *export)
1378 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1379 afb_export_destroy(export);
1382 void afb_export_destroy(struct afb_export *export)
1385 if (export->event_handlers)
1386 globset_destroy(export->event_handlers);
1387 if (export->listener != NULL)
1388 afb_evt_listener_unref(export->listener);
1389 afb_session_unref(export->session);
1390 afb_apiset_unref(export->declare_set);
1391 afb_apiset_unref(export->call_set);
1392 json_object_put(export->settings);
1393 afb_export_unref(export->creator);
1394 if (export->api.apiname != export->name)
1395 free((void*)export->api.apiname);
1400 struct afb_export *afb_export_create_none_for_path(
1401 struct afb_apiset *declare_set,
1402 struct afb_apiset *call_set,
1404 int (*creator)(void*, struct afb_api_x3*),
1407 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1409 afb_export_logmask_set(export, logmask);
1410 set_interfaces(export);
1411 if (creator && creator(closure, to_api_x3(export)) < 0) {
1412 afb_export_unref(export);
1419 #if defined(WITH_LEGACY_BINDING_V1)
1420 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1421 struct afb_apiset *call_set,
1422 const char *apiname,
1423 int (*init)(struct afb_service_x1),
1424 void (*onevent)(const char*, struct json_object*),
1427 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1429 export->init.v1 = init;
1430 export->on_any_event_v12 = onevent;
1431 export->export.v1.mode = AFB_MODE_LOCAL;
1432 export->export.v1.daemon.closure = to_api_x3(export);
1433 afb_export_logmask_set(export, logmask);
1434 set_interfaces(export);
1440 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1441 struct afb_apiset *call_set,
1442 const char *apiname,
1443 const struct afb_binding_v2 *binding,
1444 struct afb_binding_data_v2 *data,
1446 void (*onevent)(const char*, struct json_object*),
1449 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1451 export->init.v2 = init;
1452 export->on_any_event_v12 = onevent;
1453 export->desc.v2 = binding;
1454 export->export.v2 = data;
1455 data->daemon.closure = to_api_x3(export);
1456 data->service.closure = to_api_x3(export);
1457 afb_export_logmask_set(export, logmask);
1458 set_interfaces(export);
1463 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1464 struct afb_apiset *call_set,
1465 const char *apiname,
1466 struct afb_api_v3 *apiv3,
1467 struct afb_export* creator,
1470 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1472 export->unsealed = 1;
1473 export->desc.v3 = apiv3;
1474 export->creator = afb_export_addref(creator);
1475 afb_export_logmask_set(export, logmask);
1476 set_interfaces(export);
1481 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1483 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1486 int afb_export_rename(struct afb_export *export, const char *apiname)
1490 if (export->declared) {
1495 /* copy the name locally */
1496 name = strdup(apiname);
1502 if (export->api.apiname != export->name)
1503 free((void*)export->api.apiname);
1504 export->api.apiname = name;
1506 set_interfaces(export);
1510 const char *afb_export_apiname(const struct afb_export *export)
1512 return export->api.apiname;
1515 int afb_export_unshare_session(struct afb_export *export)
1517 if (export->session == common_session) {
1518 export->session = afb_session_create (0);
1519 if (export->session)
1520 afb_session_unref(common_session);
1522 export->session = common_session;
1529 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1532 switch (export->version) {
1533 #if defined(WITH_LEGACY_BINDING_V1)
1539 ERROR("invalid version 12 for API %s", export->api.apiname);
1544 export->on_any_event_v12 = on_event;
1545 return ensure_listener(export);
1548 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))
1551 switch (export->version) {
1552 case Api_Version_3: break;
1554 ERROR("invalid version Dyn for API %s", export->api.apiname);
1559 export->on_any_event_v3 = on_event;
1560 return ensure_listener(export);
1563 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1565 if (export->state != Api_State_Pre_Init) {
1566 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1571 export->init.v3 = oninit;
1575 #if defined(WITH_LEGACY_BINDING_V1)
1577 * Starts a new service (v1)
1579 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1581 return export->desc.v1 = regfun(&export->export.v1);
1585 int afb_export_preinit_x3(
1586 struct afb_export *export,
1587 int (*preinit)(void*, struct afb_api_x3*),
1590 return preinit(closure, to_api_x3(export));
1593 int afb_export_logmask_get(const struct afb_export *export)
1595 return export->api.logmask;
1598 void afb_export_logmask_set(struct afb_export *export, int mask)
1600 export->api.logmask = mask;
1601 switch (export->version) {
1602 #if defined(WITH_LEGACY_BINDING_V1)
1603 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1605 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1609 void *afb_export_userdata_get(const struct afb_export *export)
1611 return export->api.userdata;
1614 void afb_export_userdata_set(struct afb_export *export, void *data)
1616 export->api.userdata = data;
1619 /******************************************************************************
1620 ******************************************************************************
1621 ******************************************************************************
1622 ******************************************************************************
1624 ******************************************************************************
1625 ******************************************************************************
1626 ******************************************************************************
1627 ******************************************************************************/
1632 struct afb_export *export;
1635 static void do_init(int sig, void *closure)
1638 struct init *init = closure;
1639 struct afb_export *export;
1644 export = init->export;
1645 switch (export->version) {
1646 #if defined(WITH_LEGACY_BINDING_V1)
1648 rc = export->init.v1 ? export->init.v1(
1649 (struct afb_service_x1){
1651 .itf = &hooked_service_itf,
1653 .itf = &service_itf,
1655 .closure = to_api_x3(export) }) : 0;
1659 rc = export->init.v2 ? export->init.v2() : 0;
1662 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1669 init->return_code = rc;
1673 int afb_export_start(struct afb_export *export)
1679 switch (export->state) {
1683 case Api_State_Init:
1684 /* starting in progress: it is an error */
1685 ERROR("Service of API %s required started while starting", export->api.apiname);
1692 /* set event handling */
1693 switch (export->version) {
1694 #if defined(WITH_LEGACY_BINDING_V1)
1698 if (export->on_any_event_v12) {
1699 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1708 ERROR("Can't set event handler for %s", export->api.apiname);
1713 /* Starts the service */
1714 if (export->hooksvc & afb_hook_flag_api_start)
1715 afb_hook_api_start_before(export);
1718 export->state = Api_State_Init;
1719 init.export = export;
1720 sig_monitor(0, do_init, &init);
1721 rc = init.return_code;
1722 export->state = Api_State_Run;
1725 if (export->hooksvc & afb_hook_flag_api_start)
1726 afb_hook_api_start_after(export, rc);
1730 /* initialisation error */
1731 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1738 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1740 struct afb_export *export = closure;
1742 xreq->request.api = to_api_x3(export);
1744 switch (export->version) {
1745 #if defined(WITH_LEGACY_BINDING_V1)
1747 afb_api_so_v1_process_call(export->desc.v1, xreq);
1751 afb_api_so_v2_process_call(export->desc.v2, xreq);
1754 afb_api_v3_process_call(export->desc.v3, xreq);
1757 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1762 static struct json_object *api_describe_cb(void *closure)
1764 struct afb_export *export = closure;
1765 struct json_object *result;
1767 switch (export->version) {
1768 #if defined(WITH_LEGACY_BINDING_V1)
1770 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1774 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1777 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1786 static int api_service_start_cb(void *closure)
1788 struct afb_export *export = closure;
1790 return afb_export_start(export);
1794 static void api_update_hooks_cb(void *closure)
1795 __attribute__((alias("set_interfaces")));
1797 void afb_export_update_hooks(struct afb_export *export)
1798 __attribute__((alias("set_interfaces")));
1801 static int api_get_logmask_cb(void *closure)
1803 struct afb_export *export = closure;
1805 return afb_export_logmask_get(export);
1808 static void api_set_logmask_cb(void *closure, int level)
1810 struct afb_export *export = closure;
1812 afb_export_logmask_set(export, level);
1815 static void api_unref_cb(void *closure)
1817 struct afb_export *export = closure;
1819 afb_export_unref(export);
1822 static struct afb_api_itf export_api_itf =
1824 .call = api_call_cb,
1825 .service_start = api_service_start_cb,
1827 .update_hooks = api_update_hooks_cb,
1829 .get_logmask = api_get_logmask_cb,
1830 .set_logmask = api_set_logmask_cb,
1831 .describe = api_describe_cb,
1832 .unref = api_unref_cb
1835 int afb_export_declare(struct afb_export *export,
1839 struct afb_api_item afb_api;
1841 if (export->declared)
1844 /* init the record structure */
1845 afb_api.closure = afb_export_addref(export);
1846 afb_api.itf = &export_api_itf;
1847 afb_api.group = noconcurrency ? export : NULL;
1849 /* records the binding */
1850 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1852 export->declared = 1;
1854 ERROR("can't declare export %s to set %s, ABORTING it!",
1855 export->api.apiname,
1856 afb_apiset_name(export->declare_set));
1857 afb_export_unref(export);
1864 void afb_export_undeclare(struct afb_export *export)
1866 if (export->declared) {
1867 export->declared = 0;
1868 afb_apiset_del(export->declare_set, export->api.apiname);
1872 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1874 return afb_evt_event_x2_add_watch(export->listener, event);
1877 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1879 return afb_evt_event_x2_remove_watch(export->listener, event);
1882 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1884 afb_xreq_process(xreq, export->call_set);
1887 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1889 afb_context_init(context, export->session, NULL);
1890 context->validated = 1;