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 /* scan the names in a local copy */
357 iter = strdupa(name);
363 if (!save) /* at end? */
366 /* search for the end */
368 while (save && !isspace(save))
372 /* check the required api */
373 if (export->state == Api_State_Pre_Init)
374 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
376 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
385 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
387 struct afb_export *export = from_api_x3(closure);
388 if (!afb_api_is_valid_name(aliasname)) {
389 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
393 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
394 afb_export_add_alias(export, apiname, aliasname);
398 static struct afb_api_x3 *api_new_api_cb(
399 struct afb_api_x3 *closure,
403 int (*preinit)(void*, struct afb_api_x3 *),
404 void *preinit_closure)
406 struct afb_export *export = from_api_x3(closure);
407 struct afb_api_v3 *apiv3 = afb_api_v3_create(
408 export->declare_set, export->call_set,
409 api, info, noconcurrency,
410 preinit, preinit_closure, 1,
412 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
415 /**********************************************
417 **********************************************/
418 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)
420 struct afb_export *export = from_api_x3(closure);
423 vverbose_cb(closure, level, file, line, function, fmt, args);
424 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
428 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)
430 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
433 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
435 struct afb_export *export = from_api_x3(closure);
436 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
437 afb_hook_api_event_make(export, name, r);
441 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
443 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
444 struct afb_event_x1 e;
446 e.itf = event ? event->itf : NULL;
450 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
453 struct afb_export *export = from_api_x3(closure);
454 json_object_get(object);
455 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
456 r = event_broadcast_cb(closure, name, object);
457 afb_hook_api_event_broadcast_after(export, name, object, r);
458 json_object_put(object);
462 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
464 struct afb_export *export = from_api_x3(closure);
465 struct sd_event *r = afb_systemd_get_event_loop();
466 return afb_hook_api_get_event_loop(export, r);
469 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
471 struct afb_export *export = from_api_x3(closure);
472 struct sd_bus *r = afb_systemd_get_user_bus();
473 return afb_hook_api_get_user_bus(export, r);
476 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
478 struct afb_export *export = from_api_x3(closure);
479 struct sd_bus *r = afb_systemd_get_system_bus();
480 return afb_hook_api_get_system_bus(export, r);
483 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
485 struct afb_export *export = from_api_x3(closure);
486 int r = afb_common_rootdir_get_fd();
487 return afb_hook_api_rootdir_get_fd(export, r);
490 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
492 struct afb_export *export = from_api_x3(closure);
493 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
494 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
497 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
499 struct afb_export *export = from_api_x3(closure);
500 int r = queue_job_cb(closure, callback, argument, group, timeout);
501 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
504 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
506 struct afb_export *export = from_api_x3(closure);
507 afb_hook_api_legacy_unstore_req(export, sreq);
508 return legacy_unstore_req_cb(closure, sreq);
511 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
514 struct afb_export *export = from_api_x3(closure);
515 afb_hook_api_require_api(export, name, initialized);
516 result = require_api_cb(closure, name, initialized);
517 return afb_hook_api_require_api_result(export, name, initialized, result);
520 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
522 struct afb_export *export = from_api_x3(closure);
523 int result = add_alias_cb(closure, apiname, aliasname);
524 return afb_hook_api_add_alias(export, apiname, aliasname, result);
527 static struct afb_api_x3 *hooked_api_new_api_cb(
528 struct afb_api_x3 *closure,
532 int (*preinit)(void*, struct afb_api_x3 *),
533 void *preinit_closure)
535 struct afb_api_x3 *result;
536 struct afb_export *export = from_api_x3(closure);
537 afb_hook_api_new_api_before(export, api, info, noconcurrency);
538 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
539 afb_hook_api_new_api_after(export, -!result, api);
543 /**********************************************
545 **********************************************/
546 static const struct afb_daemon_itf_x1 daemon_itf = {
547 .vverbose_v1 = legacy_vverbose_v1_cb,
548 .vverbose_v2 = vverbose_cb,
549 .event_make = legacy_event_x1_make_cb,
550 .event_broadcast = event_broadcast_cb,
551 .get_event_loop = afb_systemd_get_event_loop,
552 .get_user_bus = afb_systemd_get_user_bus,
553 .get_system_bus = afb_systemd_get_system_bus,
554 .rootdir_get_fd = afb_common_rootdir_get_fd,
555 .rootdir_open_locale = rootdir_open_locale_cb,
556 .queue_job = queue_job_cb,
557 .unstore_req = legacy_unstore_req_cb,
558 .require_api = require_api_cb,
559 .add_alias = add_alias_cb,
560 .new_api = api_new_api_cb,
563 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
564 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
565 .vverbose_v2 = hooked_vverbose_cb,
566 .event_make = legacy_hooked_event_x1_make_cb,
567 .event_broadcast = hooked_event_broadcast_cb,
568 .get_event_loop = hooked_get_event_loop,
569 .get_user_bus = hooked_get_user_bus,
570 .get_system_bus = hooked_get_system_bus,
571 .rootdir_get_fd = hooked_rootdir_get_fd,
572 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
573 .queue_job = hooked_queue_job_cb,
574 .unstore_req = legacy_hooked_unstore_req_cb,
575 .require_api = hooked_require_api_cb,
576 .add_alias = hooked_add_alias_cb,
577 .new_api = hooked_api_new_api_cb,
580 /******************************************************************************
581 ******************************************************************************
582 ******************************************************************************
583 ******************************************************************************
585 ******************************************************************************
586 ******************************************************************************
587 ******************************************************************************
588 ******************************************************************************/
590 /* the common session for services sharing their session */
591 static struct afb_session *common_session;
593 /******************************************************************************
594 ******************************************************************************
595 ******************************************************************************
596 ******************************************************************************
598 ******************************************************************************
599 ******************************************************************************
600 ******************************************************************************
601 ******************************************************************************/
604 struct afb_api_x3 *apix3,
607 struct json_object *args,
608 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
611 struct afb_export *export = from_api_x3(apix3);
612 return afb_calls_call(export, api, verb, args, callback, closure);
615 static int call_sync_x3(
616 struct afb_api_x3 *apix3,
619 struct json_object *args,
620 struct json_object **object,
624 struct afb_export *export = from_api_x3(apix3);
625 return afb_calls_call_sync(export, api, verb, args, object, error, info);
628 static void legacy_call_v12(
629 struct afb_api_x3 *apix3,
632 struct json_object *args,
633 void (*callback)(void*, int, struct json_object*),
636 struct afb_export *export = from_api_x3(apix3);
637 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
640 static void legacy_call_x3(
641 struct afb_api_x3 *apix3,
644 struct json_object *args,
645 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
648 struct afb_export *export = from_api_x3(apix3);
649 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
652 static int legacy_call_sync(
653 struct afb_api_x3 *apix3,
656 struct json_object *args,
657 struct json_object **result)
659 struct afb_export *export = from_api_x3(apix3);
660 return afb_calls_legacy_call_sync(export, api, verb, args, result);
663 static void hooked_call_x3(
664 struct afb_api_x3 *apix3,
667 struct json_object *args,
668 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
671 struct afb_export *export = from_api_x3(apix3);
672 afb_calls_hooked_call(export, api, verb, args, callback, closure);
675 static int hooked_call_sync_x3(
676 struct afb_api_x3 *apix3,
679 struct json_object *args,
680 struct json_object **object,
684 struct afb_export *export = from_api_x3(apix3);
685 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
688 static void legacy_hooked_call_v12(
689 struct afb_api_x3 *apix3,
692 struct json_object *args,
693 void (*callback)(void*, int, struct json_object*),
696 struct afb_export *export = from_api_x3(apix3);
697 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
700 static void legacy_hooked_call_x3(
701 struct afb_api_x3 *apix3,
704 struct json_object *args,
705 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
708 struct afb_export *export = from_api_x3(apix3);
709 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
712 static int legacy_hooked_call_sync(
713 struct afb_api_x3 *apix3,
716 struct json_object *args,
717 struct json_object **result)
719 struct afb_export *export = from_api_x3(apix3);
720 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
723 /* the interface for services */
724 static const struct afb_service_itf_x1 service_itf = {
725 .call = legacy_call_v12,
726 .call_sync = legacy_call_sync
729 /* the interface for services */
730 static const struct afb_service_itf_x1 hooked_service_itf = {
731 .call = legacy_hooked_call_v12,
732 .call_sync = legacy_hooked_call_sync
735 /******************************************************************************
736 ******************************************************************************
737 ******************************************************************************
738 ******************************************************************************
740 ******************************************************************************
741 ******************************************************************************
742 ******************************************************************************
743 ******************************************************************************/
745 static int api_set_verbs_v2_cb(
746 struct afb_api_x3 *api,
747 const struct afb_verb_v2 *verbs)
749 struct afb_export *export = from_api_x3(api);
751 if (export->unsealed) {
752 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
760 static int api_set_verbs_v3_cb(
761 struct afb_api_x3 *api,
762 const struct afb_verb_v3 *verbs)
764 struct afb_export *export = from_api_x3(api);
766 if (!export->unsealed) {
771 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
775 static int api_add_verb_cb(
776 struct afb_api_x3 *api,
779 void (*callback)(struct afb_req_x2 *req),
781 const struct afb_auth *auth,
785 struct afb_export *export = from_api_x3(api);
787 if (!export->unsealed) {
792 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
795 static int api_del_verb_cb(
796 struct afb_api_x3 *api,
800 struct afb_export *export = from_api_x3(api);
802 if (!export->unsealed) {
807 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
810 static int api_set_on_event_cb(
811 struct afb_api_x3 *api,
812 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
814 struct afb_export *export = from_api_x3(api);
815 return afb_export_handle_events_v3(export, onevent);
818 static int api_set_on_init_cb(
819 struct afb_api_x3 *api,
820 int (*oninit)(struct afb_api_x3 *api))
822 struct afb_export *export = from_api_x3(api);
824 return afb_export_handle_init_v3(export, oninit);
827 static void api_seal_cb(
828 struct afb_api_x3 *api)
830 struct afb_export *export = from_api_x3(api);
832 export->unsealed = 0;
835 static int event_handler_add_cb(
836 struct afb_api_x3 *api,
838 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
841 struct afb_export *export = from_api_x3(api);
843 return afb_export_event_handler_add(export, pattern, callback, closure);
846 static int event_handler_del_cb(
847 struct afb_api_x3 *api,
851 struct afb_export *export = from_api_x3(api);
853 return afb_export_event_handler_del(export, pattern, closure);
856 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
858 struct afb_export *export = from_api_x3(api);
861 char *iter, *end, save;
863 iter = strdupa(name);
869 if (!save) /* at end? */
872 /* search for the end */
874 while (save && !isspace(save))
878 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
887 static int class_require_cb(struct afb_api_x3 *api, const char *name)
889 struct afb_export *export = from_api_x3(api);
892 char *iter, *end, save;
894 iter = strdupa(name);
900 if (!save) /* at end? */
903 /* search for the end */
905 while (save && !isspace(save))
909 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
918 static int delete_api_cb(struct afb_api_x3 *api)
920 struct afb_export *export = from_api_x3(api);
922 if (!export->unsealed) {
927 afb_export_undeclare(export);
928 afb_export_unref(export);
932 static struct json_object *settings_cb(struct afb_api_x3 *api)
934 struct afb_export *export = from_api_x3(api);
935 struct json_object *result = export->settings;
937 result = make_settings(export);
941 static int hooked_api_set_verbs_v2_cb(
942 struct afb_api_x3 *api,
943 const struct afb_verb_v2 *verbs)
945 struct afb_export *export = from_api_x3(api);
946 int result = api_set_verbs_v2_cb(api, verbs);
947 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
950 static int hooked_api_set_verbs_v3_cb(
951 struct afb_api_x3 *api,
952 const struct afb_verb_v3 *verbs)
954 struct afb_export *export = from_api_x3(api);
955 int result = api_set_verbs_v3_cb(api, verbs);
956 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
959 static int hooked_api_add_verb_cb(
960 struct afb_api_x3 *api,
963 void (*callback)(struct afb_req_x2 *req),
965 const struct afb_auth *auth,
969 struct afb_export *export = from_api_x3(api);
970 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
971 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
974 static int hooked_api_del_verb_cb(
975 struct afb_api_x3 *api,
979 struct afb_export *export = from_api_x3(api);
980 int result = api_del_verb_cb(api, verb, vcbdata);
981 return afb_hook_api_api_del_verb(export, result, verb);
984 static int hooked_api_set_on_event_cb(
985 struct afb_api_x3 *api,
986 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
988 struct afb_export *export = from_api_x3(api);
989 int result = api_set_on_event_cb(api, onevent);
990 return afb_hook_api_api_set_on_event(export, result);
993 static int hooked_api_set_on_init_cb(
994 struct afb_api_x3 *api,
995 int (*oninit)(struct afb_api_x3 *api))
997 struct afb_export *export = from_api_x3(api);
998 int result = api_set_on_init_cb(api, oninit);
999 return afb_hook_api_api_set_on_init(export, result);
1002 static void hooked_api_seal_cb(
1003 struct afb_api_x3 *api)
1005 struct afb_export *export = from_api_x3(api);
1006 afb_hook_api_api_seal(export);
1010 static int hooked_event_handler_add_cb(
1011 struct afb_api_x3 *api,
1012 const char *pattern,
1013 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1016 struct afb_export *export = from_api_x3(api);
1017 int result = event_handler_add_cb(api, pattern, callback, closure);
1018 return afb_hook_api_event_handler_add(export, result, pattern);
1021 static int hooked_event_handler_del_cb(
1022 struct afb_api_x3 *api,
1023 const char *pattern,
1026 struct afb_export *export = from_api_x3(api);
1027 int result = event_handler_del_cb(api, pattern, closure);
1028 return afb_hook_api_event_handler_del(export, result, pattern);
1031 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1033 struct afb_export *export = from_api_x3(api);
1034 int result = class_provide_cb(api, name);
1035 return afb_hook_api_class_provide(export, result, name);
1038 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1040 struct afb_export *export = from_api_x3(api);
1041 int result = class_require_cb(api, name);
1042 return afb_hook_api_class_require(export, result, name);
1045 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1047 struct afb_export *export = afb_export_addref(from_api_x3(api));
1048 int result = delete_api_cb(api);
1049 result = afb_hook_api_delete_api(export, result);
1050 afb_export_unref(export);
1054 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1056 struct afb_export *export = from_api_x3(api);
1057 struct json_object *result = settings_cb(api);
1058 result = afb_hook_api_settings(export, result);
1062 static const struct afb_api_x3_itf api_x3_itf = {
1064 .vverbose = (void*)vverbose_cb,
1066 .get_event_loop = afb_systemd_get_event_loop,
1067 .get_user_bus = afb_systemd_get_user_bus,
1068 .get_system_bus = afb_systemd_get_system_bus,
1069 .rootdir_get_fd = afb_common_rootdir_get_fd,
1070 .rootdir_open_locale = rootdir_open_locale_cb,
1071 .queue_job = queue_job_cb,
1073 .require_api = require_api_cb,
1074 .add_alias = add_alias_cb,
1076 .event_broadcast = event_broadcast_cb,
1077 .event_make = event_x2_make_cb,
1079 .legacy_call = legacy_call_x3,
1080 .legacy_call_sync = legacy_call_sync,
1082 .api_new_api = api_new_api_cb,
1083 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1084 .api_add_verb = api_add_verb_cb,
1085 .api_del_verb = api_del_verb_cb,
1086 .api_set_on_event = api_set_on_event_cb,
1087 .api_set_on_init = api_set_on_init_cb,
1088 .api_seal = api_seal_cb,
1089 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1090 .event_handler_add = event_handler_add_cb,
1091 .event_handler_del = event_handler_del_cb,
1094 .call_sync = call_sync_x3,
1096 .class_provide = class_provide_cb,
1097 .class_require = class_require_cb,
1099 .delete_api = delete_api_cb,
1100 .settings = settings_cb,
1103 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1105 .vverbose = hooked_vverbose_cb,
1107 .get_event_loop = hooked_get_event_loop,
1108 .get_user_bus = hooked_get_user_bus,
1109 .get_system_bus = hooked_get_system_bus,
1110 .rootdir_get_fd = hooked_rootdir_get_fd,
1111 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1112 .queue_job = hooked_queue_job_cb,
1114 .require_api = hooked_require_api_cb,
1115 .add_alias = hooked_add_alias_cb,
1117 .event_broadcast = hooked_event_broadcast_cb,
1118 .event_make = hooked_event_x2_make_cb,
1120 .legacy_call = legacy_hooked_call_x3,
1121 .legacy_call_sync = legacy_hooked_call_sync,
1123 .api_new_api = hooked_api_new_api_cb,
1124 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1125 .api_add_verb = hooked_api_add_verb_cb,
1126 .api_del_verb = hooked_api_del_verb_cb,
1127 .api_set_on_event = hooked_api_set_on_event_cb,
1128 .api_set_on_init = hooked_api_set_on_init_cb,
1129 .api_seal = hooked_api_seal_cb,
1130 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1131 .event_handler_add = hooked_event_handler_add_cb,
1132 .event_handler_del = hooked_event_handler_del_cb,
1134 .call = hooked_call_x3,
1135 .call_sync = hooked_call_sync_x3,
1137 .class_provide = hooked_class_provide_cb,
1138 .class_require = hooked_class_require_cb,
1140 .delete_api = hooked_delete_api_cb,
1141 .settings = hooked_settings_cb,
1144 /******************************************************************************
1145 ******************************************************************************
1146 ******************************************************************************
1147 ******************************************************************************
1149 ******************************************************************************
1150 ******************************************************************************
1151 ******************************************************************************
1152 ******************************************************************************/
1155 * Propagates the event to the service
1157 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1159 struct event_handler *handler;
1160 struct afb_export *export = from_api_x3(closure);
1162 /* hook the event before */
1163 if (export->hooksvc & afb_hook_flag_api_on_event)
1164 afb_hook_api_on_event_before(export, event, eventid, object);
1166 /* transmit to specific handlers */
1167 /* search the handler */
1168 handler = export->event_handlers;
1170 if (!fnmatch(handler->pattern, event, 0)) {
1171 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1172 handler->callback(handler->closure, event, object, to_api_x3(export));
1174 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1175 handler->callback(handler->closure, event, object, to_api_x3(export));
1176 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1179 handler = handler->next;
1182 /* transmit to default handler */
1183 if (export->on_any_event_v3)
1184 export->on_any_event_v3(to_api_x3(export), event, object);
1185 else if (export->on_any_event_v12)
1186 export->on_any_event_v12(event, object);
1188 /* hook the event after */
1189 if (export->hooksvc & afb_hook_flag_api_on_event)
1190 afb_hook_api_on_event_after(export, event, eventid, object);
1191 json_object_put(object);
1194 /* the interface for events */
1195 static const struct afb_evt_itf evt_itf = {
1196 .broadcast = listener_of_events,
1197 .push = listener_of_events
1200 /* ensure an existing listener */
1201 static int ensure_listener(struct afb_export *export)
1203 if (!export->listener) {
1204 export->listener = afb_evt_listener_create(&evt_itf, export);
1205 if (export->listener == NULL)
1211 int afb_export_event_handler_add(
1212 struct afb_export *export,
1213 const char *pattern,
1214 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1218 struct event_handler *handler, **previous;
1220 rc = ensure_listener(export);
1224 /* search the handler */
1225 previous = &export->event_handlers;
1226 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1227 previous = &handler->next;
1229 /* error if found */
1231 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1236 /* create the event */
1237 handler = malloc(strlen(pattern) + sizeof * handler);
1239 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1244 /* init and record */
1245 handler->next = NULL;
1246 handler->callback = callback;
1247 handler->closure = closure;
1248 strcpy(handler->pattern, pattern);
1249 *previous = handler;
1254 int afb_export_event_handler_del(
1255 struct afb_export *export,
1256 const char *pattern,
1259 struct event_handler *handler, **previous;
1261 /* search the handler */
1262 previous = &export->event_handlers;
1263 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1264 previous = &handler->next;
1266 /* error if found */
1268 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1273 /* remove the found event */
1275 *closure = handler->closure;
1277 *previous = handler->next;
1282 /******************************************************************************
1283 ******************************************************************************
1284 ******************************************************************************
1285 ******************************************************************************
1287 ******************************************************************************
1288 ******************************************************************************
1289 ******************************************************************************
1290 ******************************************************************************/
1292 static struct afb_export *create(
1293 struct afb_apiset *declare_set,
1294 struct afb_apiset *call_set,
1295 const char *apiname,
1297 enum afb_api_version version)
1299 struct afb_export *export;
1302 /* session shared with other exports */
1303 if (common_session == NULL) {
1304 common_session = afb_session_create (0);
1305 if (common_session == NULL)
1308 lenapi = strlen(apiname);
1309 export = calloc(1, sizeof *export + lenapi + (path == apiname || !path ? 0 : strlen(path)));
1313 export->refcount = 1;
1314 strcpy(export->name, apiname);
1315 export->api.apiname = export->name;
1316 if (path == apiname)
1317 export->path = export->name;
1319 export->path = strcpy(&export->name[lenapi + 1], path);
1320 export->version = version;
1321 export->state = Api_State_Pre_Init;
1322 export->session = afb_session_addref(common_session);
1323 export->declare_set = afb_apiset_addref(declare_set);
1324 export->call_set = afb_apiset_addref(call_set);
1329 struct afb_export *afb_export_addref(struct afb_export *export)
1332 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1336 void afb_export_unref(struct afb_export *export)
1338 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1339 afb_export_destroy(export);
1342 void afb_export_destroy(struct afb_export *export)
1344 struct event_handler *handler;
1347 while ((handler = export->event_handlers)) {
1348 export->event_handlers = handler->next;
1351 if (export->listener != NULL)
1352 afb_evt_listener_unref(export->listener);
1353 afb_session_unref(export->session);
1354 afb_apiset_unref(export->declare_set);
1355 afb_apiset_unref(export->call_set);
1356 json_object_put(export->settings);
1357 afb_export_unref(export->creator);
1358 if (export->api.apiname != export->name)
1359 free((void*)export->api.apiname);
1364 struct afb_export *afb_export_create_none_for_path(
1365 struct afb_apiset *declare_set,
1366 struct afb_apiset *call_set,
1368 int (*creator)(void*, struct afb_api_x3*),
1371 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1373 afb_export_logmask_set(export, logmask);
1374 afb_export_update_hooks(export);
1375 if (creator && creator(closure, to_api_x3(export)) < 0) {
1376 afb_export_unref(export);
1383 #if defined(WITH_LEGACY_BINDING_V1)
1384 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1385 struct afb_apiset *call_set,
1386 const char *apiname,
1387 int (*init)(struct afb_service_x1),
1388 void (*onevent)(const char*, struct json_object*),
1391 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1393 export->init.v1 = init;
1394 export->on_any_event_v12 = onevent;
1395 export->export.v1.mode = AFB_MODE_LOCAL;
1396 export->export.v1.daemon.closure = to_api_x3(export);
1397 afb_export_logmask_set(export, logmask);
1398 afb_export_update_hooks(export);
1404 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1405 struct afb_apiset *call_set,
1406 const char *apiname,
1407 const struct afb_binding_v2 *binding,
1408 struct afb_binding_data_v2 *data,
1410 void (*onevent)(const char*, struct json_object*),
1413 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1415 export->init.v2 = init;
1416 export->on_any_event_v12 = onevent;
1417 export->desc.v2 = binding;
1418 export->export.v2 = data;
1419 data->daemon.closure = to_api_x3(export);
1420 data->service.closure = to_api_x3(export);
1421 afb_export_logmask_set(export, logmask);
1422 afb_export_update_hooks(export);
1427 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1428 struct afb_apiset *call_set,
1429 const char *apiname,
1430 struct afb_api_v3 *apiv3,
1431 struct afb_export* creator,
1434 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1436 export->unsealed = 1;
1437 export->desc.v3 = apiv3;
1438 export->creator = afb_export_addref(creator);
1439 afb_export_logmask_set(export, logmask);
1440 afb_export_update_hooks(export);
1445 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1447 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1450 int afb_export_rename(struct afb_export *export, const char *apiname)
1454 if (export->declared) {
1459 /* copy the name locally */
1460 name = strdup(apiname);
1466 if (export->api.apiname != export->name)
1467 free((void*)export->api.apiname);
1468 export->api.apiname = name;
1470 afb_export_update_hooks(export);
1474 const char *afb_export_apiname(const struct afb_export *export)
1476 return export->api.apiname;
1479 void afb_export_update_hooks(struct afb_export *export)
1481 export->hookditf = afb_hook_flags_api(export->api.apiname);
1482 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1483 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1485 switch (export->version) {
1486 #if defined(WITH_LEGACY_BINDING_V1)
1488 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1492 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1493 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1498 int afb_export_unshare_session(struct afb_export *export)
1500 if (export->session == common_session) {
1501 export->session = afb_session_create (0);
1502 if (export->session)
1503 afb_session_unref(common_session);
1505 export->session = common_session;
1512 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1515 switch (export->version) {
1516 #if defined(WITH_LEGACY_BINDING_V1)
1522 ERROR("invalid version 12 for API %s", export->api.apiname);
1527 export->on_any_event_v12 = on_event;
1528 return ensure_listener(export);
1531 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))
1534 switch (export->version) {
1535 case Api_Version_3: break;
1537 ERROR("invalid version Dyn for API %s", export->api.apiname);
1542 export->on_any_event_v3 = on_event;
1543 return ensure_listener(export);
1546 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1548 if (export->state != Api_State_Pre_Init) {
1549 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1554 export->init.v3 = oninit;
1558 #if defined(WITH_LEGACY_BINDING_V1)
1560 * Starts a new service (v1)
1562 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1564 return export->desc.v1 = regfun(&export->export.v1);
1568 int afb_export_preinit_x3(
1569 struct afb_export *export,
1570 int (*preinit)(void*, struct afb_api_x3*),
1573 return preinit(closure, to_api_x3(export));
1576 int afb_export_logmask_get(const struct afb_export *export)
1578 return export->api.logmask;
1581 void afb_export_logmask_set(struct afb_export *export, int mask)
1583 export->api.logmask = mask;
1584 switch (export->version) {
1585 #if defined(WITH_LEGACY_BINDING_V1)
1586 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1588 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1592 void *afb_export_userdata_get(const struct afb_export *export)
1594 return export->api.userdata;
1597 void afb_export_userdata_set(struct afb_export *export, void *data)
1599 export->api.userdata = data;
1602 /******************************************************************************
1603 ******************************************************************************
1604 ******************************************************************************
1605 ******************************************************************************
1607 ******************************************************************************
1608 ******************************************************************************
1609 ******************************************************************************
1610 ******************************************************************************/
1615 struct afb_export *export;
1618 static void do_init(int sig, void *closure)
1621 struct init *init = closure;
1622 struct afb_export *export;
1627 export = init->export;
1628 switch (export->version) {
1629 #if defined(WITH_LEGACY_BINDING_V1)
1631 rc = export->init.v1 ? export->init.v1(
1632 (struct afb_service_x1){
1633 .itf = &hooked_service_itf,
1634 .closure = to_api_x3(export) }) : 0;
1638 rc = export->init.v2 ? export->init.v2() : 0;
1641 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1648 init->return_code = rc;
1652 int afb_export_start(struct afb_export *export)
1658 switch (export->state) {
1662 case Api_State_Init:
1663 /* starting in progress: it is an error */
1664 ERROR("Service of API %s required started while starting", export->api.apiname);
1671 /* set event handling */
1672 switch (export->version) {
1673 #if defined(WITH_LEGACY_BINDING_V1)
1677 if (export->on_any_event_v12) {
1678 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1687 ERROR("Can't set event handler for %s", export->api.apiname);
1691 /* Starts the service */
1692 if (export->hooksvc & afb_hook_flag_api_start)
1693 afb_hook_api_start_before(export);
1695 export->state = Api_State_Init;
1696 init.export = export;
1697 sig_monitor(0, do_init, &init);
1698 rc = init.return_code;
1699 export->state = Api_State_Run;
1701 if (export->hooksvc & afb_hook_flag_api_start)
1702 afb_hook_api_start_after(export, rc);
1705 /* initialisation error */
1706 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1713 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1715 struct afb_export *export = closure;
1717 xreq->request.api = to_api_x3(export);
1719 switch (export->version) {
1720 #if defined(WITH_LEGACY_BINDING_V1)
1722 afb_api_so_v1_process_call(export->desc.v1, xreq);
1726 afb_api_so_v2_process_call(export->desc.v2, xreq);
1729 afb_api_v3_process_call(export->desc.v3, xreq);
1732 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1737 static struct json_object *api_describe_cb(void *closure)
1739 struct afb_export *export = closure;
1740 struct json_object *result;
1742 switch (export->version) {
1743 #if defined(WITH_LEGACY_BINDING_V1)
1745 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1749 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1752 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1761 static int api_service_start_cb(void *closure)
1763 struct afb_export *export = closure;
1765 return afb_export_start(export);
1768 static void api_update_hooks_cb(void *closure)
1770 struct afb_export *export = closure;
1772 afb_export_update_hooks(export);
1775 static int api_get_logmask_cb(void *closure)
1777 struct afb_export *export = closure;
1779 return afb_export_logmask_get(export);
1782 static void api_set_logmask_cb(void *closure, int level)
1784 struct afb_export *export = closure;
1786 afb_export_logmask_set(export, level);
1789 static void api_unref_cb(void *closure)
1791 struct afb_export *export = closure;
1793 afb_export_unref(export);
1796 static struct afb_api_itf export_api_itf =
1798 .call = api_call_cb,
1799 .service_start = api_service_start_cb,
1800 .update_hooks = api_update_hooks_cb,
1801 .get_logmask = api_get_logmask_cb,
1802 .set_logmask = api_set_logmask_cb,
1803 .describe = api_describe_cb,
1804 .unref = api_unref_cb
1807 int afb_export_declare(struct afb_export *export,
1811 struct afb_api_item afb_api;
1813 if (export->declared)
1816 /* init the record structure */
1817 afb_api.closure = afb_export_addref(export);
1818 afb_api.itf = &export_api_itf;
1819 afb_api.group = noconcurrency ? export : NULL;
1821 /* records the binding */
1822 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1824 export->declared = 1;
1826 ERROR("can't declare export %s to set %s, ABORTING it!",
1827 export->api.apiname,
1828 afb_apiset_name(export->declare_set));
1829 afb_export_unref(export);
1836 void afb_export_undeclare(struct afb_export *export)
1838 if (export->declared) {
1839 export->declared = 0;
1840 afb_apiset_del(export->declare_set, export->api.apiname);
1844 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1846 return afb_evt_event_x2_add_watch(export->listener, event);
1849 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1851 return afb_evt_event_x2_remove_watch(export->listener, event);
1854 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1856 afb_xreq_process(xreq, export->call_set);
1859 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1861 afb_context_init(context, export->session, NULL);
1862 context->validated = 1;