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>
28 #define AFB_BINDING_VERSION 0
29 #include <afb/afb-binding.h>
32 #include "afb-apiset.h"
33 #if defined(WITH_LEGACY_BINDING_V1)
34 #include "afb-api-so-v1.h"
36 #include "afb-api-so-v2.h"
37 #include "afb-api-v3.h"
38 #include "afb-common.h"
39 #include "afb-systemd.h"
42 #include "afb-export.h"
44 #include "afb-msg-json.h"
45 #include "afb-session.h"
47 #include "afb-calls.h"
50 #include "sig-monitor.h"
52 /*************************************************************************
54 ************************************************************************/
57 * structure for handling events
61 /* link to the next event handler of the list */
62 struct event_handler *next;
64 /* function to call on the case of the event */
65 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
67 /* closure for the callback */
70 /* the handled pattern */
75 * Actually supported versions
80 #if defined(WITH_LEGACY_BINDING_V1)
88 * The states of exported APIs
98 * structure of the exported API
103 struct afb_api_x3 api;
105 /* reference count */
108 /* version of the api */
115 unsigned declared: 1;
118 unsigned unsealed: 1;
124 /* session for service */
125 struct afb_session *session;
127 /* apiset the API is declared in */
128 struct afb_apiset *declare_set;
130 /* apiset for calls */
131 struct afb_apiset *call_set;
133 /* event listener for service or NULL */
134 struct afb_evt_listener *listener;
136 /* event handler list */
137 struct event_handler *event_handlers;
139 /* internal descriptors */
141 #if defined(WITH_LEGACY_BINDING_V1)
142 struct afb_binding_v1 *v1;
144 const struct afb_binding_v2 *v2;
145 struct afb_api_v3 *v3;
150 #if defined(WITH_LEGACY_BINDING_V1)
151 int (*v1)(struct afb_service_x1);
154 int (*v3)(struct afb_api_x3 *api);
158 void (*on_any_event_v12)(const char *event, struct json_object *object);
159 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
163 #if defined(WITH_LEGACY_BINDING_V1)
164 struct afb_binding_interface_v1 v1;
166 struct afb_binding_data_v2 *v2;
173 /*****************************************************************************/
175 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
177 return (struct afb_api_x3*)export;
180 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
182 return (struct afb_export*)api;
185 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
187 return from_api_x3(api);
190 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
192 return to_api_x3(export);
195 /******************************************************************************
196 ******************************************************************************
197 ******************************************************************************
198 ******************************************************************************
200 ******************************************************************************
201 ******************************************************************************
202 ******************************************************************************
203 ******************************************************************************/
205 /**********************************************
207 **********************************************/
208 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)
211 struct afb_export *export = from_api_x3(closure);
213 if (!fmt || vasprintf(&p, fmt, args) < 0)
214 vverbose(level, file, line, function, fmt, args);
216 verbose(level, file, line, function, "[API %s] %s", export->api.apiname, p);
221 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
223 vverbose_cb(closure, level, file, line, NULL, fmt, args);
226 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
228 struct afb_export *export = from_api_x3(closure);
230 /* check daemon state */
231 if (export->state == Api_State_Pre_Init) {
232 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
237 /* create the event */
238 return afb_evt_event_x2_create2(export->api.apiname, name);
241 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
243 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
244 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
247 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
251 struct afb_export *export = from_api_x3(closure);
253 /* check daemon state */
254 if (export->state == Api_State_Pre_Init) {
255 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit", export->api.apiname, name, json_object_to_json_string(object));
260 /* makes the event name */
261 plen = strlen(export->api.apiname);
263 event = alloca(nlen + plen + 2);
264 memcpy(event, export->api.apiname, plen);
266 memcpy(event + plen + 1, name, nlen + 1);
268 /* broadcast the event */
269 return afb_evt_broadcast(event, object);
272 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
274 return afb_common_rootdir_open_locale(filename, flags, locale);
277 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
279 return jobs_queue(group, timeout, callback, argument);
282 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
284 return afb_xreq_unstore(sreq);
287 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
289 struct afb_export *export = from_api_x3(closure);
291 char *iter, *end, save;
293 /* scan the names in a local copy */
295 iter = strdupa(name);
301 if (!save) /* at end? */
304 /* search for the end */
306 while (save && !isspace(save))
310 /* check the required api */
311 if (export->state == Api_State_Pre_Init)
312 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
314 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
323 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
325 struct afb_export *export = from_api_x3(closure);
326 if (!afb_api_is_valid_name(aliasname)) {
327 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
331 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
332 afb_export_add_alias(export, apiname, aliasname);
336 static struct afb_api_x3 *api_new_api_cb(
337 struct afb_api_x3 *closure,
341 int (*preinit)(void*, struct afb_api_x3 *),
342 void *preinit_closure)
344 struct afb_export *export = from_api_x3(closure);
345 struct afb_api_v3 *apiv3 = afb_api_v3_create(export->declare_set, export->call_set, api, info, noconcurrency, preinit, preinit_closure, 1);
346 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
349 /**********************************************
351 **********************************************/
352 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)
354 struct afb_export *export = from_api_x3(closure);
357 vverbose_cb(closure, level, file, line, function, fmt, args);
358 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
362 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)
364 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
367 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
369 struct afb_export *export = from_api_x3(closure);
370 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
371 afb_hook_api_event_make(export, name, r);
375 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
377 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
378 struct afb_event_x1 e;
380 e.itf = event ? event->itf : NULL;
384 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
387 struct afb_export *export = from_api_x3(closure);
388 json_object_get(object);
389 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
390 r = event_broadcast_cb(closure, name, object);
391 afb_hook_api_event_broadcast_after(export, name, object, r);
392 json_object_put(object);
396 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
398 struct afb_export *export = from_api_x3(closure);
399 struct sd_event *r = afb_systemd_get_event_loop();
400 return afb_hook_api_get_event_loop(export, r);
403 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
405 struct afb_export *export = from_api_x3(closure);
406 struct sd_bus *r = afb_systemd_get_user_bus();
407 return afb_hook_api_get_user_bus(export, r);
410 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
412 struct afb_export *export = from_api_x3(closure);
413 struct sd_bus *r = afb_systemd_get_system_bus();
414 return afb_hook_api_get_system_bus(export, r);
417 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
419 struct afb_export *export = from_api_x3(closure);
420 int r = afb_common_rootdir_get_fd();
421 return afb_hook_api_rootdir_get_fd(export, r);
424 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
426 struct afb_export *export = from_api_x3(closure);
427 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
428 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
431 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
433 struct afb_export *export = from_api_x3(closure);
434 int r = queue_job_cb(closure, callback, argument, group, timeout);
435 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
438 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
440 struct afb_export *export = from_api_x3(closure);
441 afb_hook_api_legacy_unstore_req(export, sreq);
442 return legacy_unstore_req_cb(closure, sreq);
445 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
448 struct afb_export *export = from_api_x3(closure);
449 afb_hook_api_require_api(export, name, initialized);
450 result = require_api_cb(closure, name, initialized);
451 return afb_hook_api_require_api_result(export, name, initialized, result);
454 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
456 struct afb_export *export = from_api_x3(closure);
457 int result = add_alias_cb(closure, apiname, aliasname);
458 return afb_hook_api_add_alias(export, apiname, aliasname, result);
461 static struct afb_api_x3 *hooked_api_new_api_cb(
462 struct afb_api_x3 *closure,
466 int (*preinit)(void*, struct afb_api_x3 *),
467 void *preinit_closure)
469 struct afb_api_x3 *result;
470 struct afb_export *export = from_api_x3(closure);
471 afb_hook_api_new_api_before(export, api, info, noconcurrency);
472 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
473 afb_hook_api_new_api_after(export, -!result, api);
477 /**********************************************
479 **********************************************/
480 static const struct afb_daemon_itf_x1 daemon_itf = {
481 .vverbose_v1 = legacy_vverbose_v1_cb,
482 .vverbose_v2 = vverbose_cb,
483 .event_make = legacy_event_x1_make_cb,
484 .event_broadcast = event_broadcast_cb,
485 .get_event_loop = afb_systemd_get_event_loop,
486 .get_user_bus = afb_systemd_get_user_bus,
487 .get_system_bus = afb_systemd_get_system_bus,
488 .rootdir_get_fd = afb_common_rootdir_get_fd,
489 .rootdir_open_locale = rootdir_open_locale_cb,
490 .queue_job = queue_job_cb,
491 .unstore_req = legacy_unstore_req_cb,
492 .require_api = require_api_cb,
493 .add_alias = add_alias_cb,
494 .new_api = api_new_api_cb,
497 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
498 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
499 .vverbose_v2 = hooked_vverbose_cb,
500 .event_make = legacy_hooked_event_x1_make_cb,
501 .event_broadcast = hooked_event_broadcast_cb,
502 .get_event_loop = hooked_get_event_loop,
503 .get_user_bus = hooked_get_user_bus,
504 .get_system_bus = hooked_get_system_bus,
505 .rootdir_get_fd = hooked_rootdir_get_fd,
506 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
507 .queue_job = hooked_queue_job_cb,
508 .unstore_req = legacy_hooked_unstore_req_cb,
509 .require_api = hooked_require_api_cb,
510 .add_alias = hooked_add_alias_cb,
511 .new_api = hooked_api_new_api_cb,
514 /******************************************************************************
515 ******************************************************************************
516 ******************************************************************************
517 ******************************************************************************
519 ******************************************************************************
520 ******************************************************************************
521 ******************************************************************************
522 ******************************************************************************/
524 /* the common session for services sharing their session */
525 static struct afb_session *common_session;
527 /******************************************************************************
528 ******************************************************************************
529 ******************************************************************************
530 ******************************************************************************
532 ******************************************************************************
533 ******************************************************************************
534 ******************************************************************************
535 ******************************************************************************/
538 struct afb_api_x3 *apix3,
541 struct json_object *args,
542 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
545 struct afb_export *export = from_api_x3(apix3);
546 return afb_calls_call(export, api, verb, args, callback, closure);
549 static int call_sync_x3(
550 struct afb_api_x3 *apix3,
553 struct json_object *args,
554 struct json_object **object,
558 struct afb_export *export = from_api_x3(apix3);
559 return afb_calls_call_sync(export, api, verb, args, object, error, info);
562 static void legacy_call_v12(
563 struct afb_api_x3 *apix3,
566 struct json_object *args,
567 void (*callback)(void*, int, struct json_object*),
570 struct afb_export *export = from_api_x3(apix3);
571 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
574 static void legacy_call_x3(
575 struct afb_api_x3 *apix3,
578 struct json_object *args,
579 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
582 struct afb_export *export = from_api_x3(apix3);
583 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
586 static int legacy_call_sync(
587 struct afb_api_x3 *apix3,
590 struct json_object *args,
591 struct json_object **result)
593 struct afb_export *export = from_api_x3(apix3);
594 return afb_calls_legacy_call_sync(export, api, verb, args, result);
597 static void hooked_call_x3(
598 struct afb_api_x3 *apix3,
601 struct json_object *args,
602 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
605 struct afb_export *export = from_api_x3(apix3);
606 afb_calls_hooked_call(export, api, verb, args, callback, closure);
609 static int hooked_call_sync_x3(
610 struct afb_api_x3 *apix3,
613 struct json_object *args,
614 struct json_object **object,
618 struct afb_export *export = from_api_x3(apix3);
619 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
622 static void legacy_hooked_call_v12(
623 struct afb_api_x3 *apix3,
626 struct json_object *args,
627 void (*callback)(void*, int, struct json_object*),
630 struct afb_export *export = from_api_x3(apix3);
631 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
634 static void legacy_hooked_call_x3(
635 struct afb_api_x3 *apix3,
638 struct json_object *args,
639 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
642 struct afb_export *export = from_api_x3(apix3);
643 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
646 static int legacy_hooked_call_sync(
647 struct afb_api_x3 *apix3,
650 struct json_object *args,
651 struct json_object **result)
653 struct afb_export *export = from_api_x3(apix3);
654 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
657 /* the interface for services */
658 static const struct afb_service_itf_x1 service_itf = {
659 .call = legacy_call_v12,
660 .call_sync = legacy_call_sync
663 /* the interface for services */
664 static const struct afb_service_itf_x1 hooked_service_itf = {
665 .call = legacy_hooked_call_v12,
666 .call_sync = legacy_hooked_call_sync
669 /******************************************************************************
670 ******************************************************************************
671 ******************************************************************************
672 ******************************************************************************
674 ******************************************************************************
675 ******************************************************************************
676 ******************************************************************************
677 ******************************************************************************/
679 static int api_set_verbs_v2_cb(
680 struct afb_api_x3 *api,
681 const struct afb_verb_v2 *verbs)
683 struct afb_export *export = from_api_x3(api);
685 if (export->unsealed) {
686 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
694 static int api_set_verbs_v3_cb(
695 struct afb_api_x3 *api,
696 const struct afb_verb_v3 *verbs)
698 struct afb_export *export = from_api_x3(api);
700 if (!export->unsealed) {
705 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
709 static int api_add_verb_cb(
710 struct afb_api_x3 *api,
713 void (*callback)(struct afb_req_x2 *req),
715 const struct afb_auth *auth,
719 struct afb_export *export = from_api_x3(api);
721 if (!export->unsealed) {
726 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
729 static int api_del_verb_cb(
730 struct afb_api_x3 *api,
734 struct afb_export *export = from_api_x3(api);
736 if (!export->unsealed) {
741 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
744 static int api_set_on_event_cb(
745 struct afb_api_x3 *api,
746 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
748 struct afb_export *export = from_api_x3(api);
749 return afb_export_handle_events_v3(export, onevent);
752 static int api_set_on_init_cb(
753 struct afb_api_x3 *api,
754 int (*oninit)(struct afb_api_x3 *api))
756 struct afb_export *export = from_api_x3(api);
758 return afb_export_handle_init_v3(export, oninit);
761 static void api_seal_cb(
762 struct afb_api_x3 *api)
764 struct afb_export *export = from_api_x3(api);
766 export->unsealed = 0;
769 static int event_handler_add_cb(
770 struct afb_api_x3 *api,
772 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
775 struct afb_export *export = from_api_x3(api);
777 return afb_export_event_handler_add(export, pattern, callback, closure);
780 static int event_handler_del_cb(
781 struct afb_api_x3 *api,
785 struct afb_export *export = from_api_x3(api);
787 return afb_export_event_handler_del(export, pattern, closure);
790 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
792 struct afb_export *export = from_api_x3(api);
795 char *iter, *end, save;
797 iter = strdupa(name);
803 if (!save) /* at end? */
806 /* search for the end */
808 while (save && !isspace(save))
812 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
821 static int class_require_cb(struct afb_api_x3 *api, const char *name)
823 struct afb_export *export = from_api_x3(api);
826 char *iter, *end, save;
828 iter = strdupa(name);
834 if (!save) /* at end? */
837 /* search for the end */
839 while (save && !isspace(save))
843 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
852 static int delete_api_cb(struct afb_api_x3 *api)
854 struct afb_export *export = from_api_x3(api);
856 if (!export->unsealed) {
861 afb_export_undeclare(export);
862 afb_export_unref(export);
866 static int hooked_api_set_verbs_v2_cb(
867 struct afb_api_x3 *api,
868 const struct afb_verb_v2 *verbs)
870 struct afb_export *export = from_api_x3(api);
871 int result = api_set_verbs_v2_cb(api, verbs);
872 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
875 static int hooked_api_set_verbs_v3_cb(
876 struct afb_api_x3 *api,
877 const struct afb_verb_v3 *verbs)
879 struct afb_export *export = from_api_x3(api);
880 int result = api_set_verbs_v3_cb(api, verbs);
881 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
884 static int hooked_api_add_verb_cb(
885 struct afb_api_x3 *api,
888 void (*callback)(struct afb_req_x2 *req),
890 const struct afb_auth *auth,
894 struct afb_export *export = from_api_x3(api);
895 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
896 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
899 static int hooked_api_del_verb_cb(
900 struct afb_api_x3 *api,
904 struct afb_export *export = from_api_x3(api);
905 int result = api_del_verb_cb(api, verb, vcbdata);
906 return afb_hook_api_api_del_verb(export, result, verb);
909 static int hooked_api_set_on_event_cb(
910 struct afb_api_x3 *api,
911 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
913 struct afb_export *export = from_api_x3(api);
914 int result = api_set_on_event_cb(api, onevent);
915 return afb_hook_api_api_set_on_event(export, result);
918 static int hooked_api_set_on_init_cb(
919 struct afb_api_x3 *api,
920 int (*oninit)(struct afb_api_x3 *api))
922 struct afb_export *export = from_api_x3(api);
923 int result = api_set_on_init_cb(api, oninit);
924 return afb_hook_api_api_set_on_init(export, result);
927 static void hooked_api_seal_cb(
928 struct afb_api_x3 *api)
930 struct afb_export *export = from_api_x3(api);
931 afb_hook_api_api_seal(export);
935 static int hooked_event_handler_add_cb(
936 struct afb_api_x3 *api,
938 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
941 struct afb_export *export = from_api_x3(api);
942 int result = event_handler_add_cb(api, pattern, callback, closure);
943 return afb_hook_api_event_handler_add(export, result, pattern);
946 static int hooked_event_handler_del_cb(
947 struct afb_api_x3 *api,
951 struct afb_export *export = from_api_x3(api);
952 int result = event_handler_del_cb(api, pattern, closure);
953 return afb_hook_api_event_handler_del(export, result, pattern);
956 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
958 struct afb_export *export = from_api_x3(api);
959 int result = class_provide_cb(api, name);
960 return afb_hook_api_class_provide(export, result, name);
963 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
965 struct afb_export *export = from_api_x3(api);
966 int result = class_require_cb(api, name);
967 return afb_hook_api_class_require(export, result, name);
970 static int hooked_delete_api_cb(struct afb_api_x3 *api)
972 struct afb_export *export = afb_export_addref(from_api_x3(api));
973 int result = delete_api_cb(api);
974 result = afb_hook_api_delete_api(export, result);
975 afb_export_unref(export);
979 static const struct afb_api_x3_itf api_x3_itf = {
981 .vverbose = (void*)vverbose_cb,
983 .get_event_loop = afb_systemd_get_event_loop,
984 .get_user_bus = afb_systemd_get_user_bus,
985 .get_system_bus = afb_systemd_get_system_bus,
986 .rootdir_get_fd = afb_common_rootdir_get_fd,
987 .rootdir_open_locale = rootdir_open_locale_cb,
988 .queue_job = queue_job_cb,
990 .require_api = require_api_cb,
991 .add_alias = add_alias_cb,
993 .event_broadcast = event_broadcast_cb,
994 .event_make = event_x2_make_cb,
996 .legacy_call = legacy_call_x3,
997 .legacy_call_sync = legacy_call_sync,
999 .api_new_api = api_new_api_cb,
1000 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1001 .api_add_verb = api_add_verb_cb,
1002 .api_del_verb = api_del_verb_cb,
1003 .api_set_on_event = api_set_on_event_cb,
1004 .api_set_on_init = api_set_on_init_cb,
1005 .api_seal = api_seal_cb,
1006 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1007 .event_handler_add = event_handler_add_cb,
1008 .event_handler_del = event_handler_del_cb,
1011 .call_sync = call_sync_x3,
1013 .class_provide = class_provide_cb,
1014 .class_require = class_require_cb,
1016 .delete_api = delete_api_cb,
1019 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1021 .vverbose = hooked_vverbose_cb,
1023 .get_event_loop = hooked_get_event_loop,
1024 .get_user_bus = hooked_get_user_bus,
1025 .get_system_bus = hooked_get_system_bus,
1026 .rootdir_get_fd = hooked_rootdir_get_fd,
1027 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1028 .queue_job = hooked_queue_job_cb,
1030 .require_api = hooked_require_api_cb,
1031 .add_alias = hooked_add_alias_cb,
1033 .event_broadcast = hooked_event_broadcast_cb,
1034 .event_make = hooked_event_x2_make_cb,
1036 .legacy_call = legacy_hooked_call_x3,
1037 .legacy_call_sync = legacy_hooked_call_sync,
1039 .api_new_api = hooked_api_new_api_cb,
1040 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1041 .api_add_verb = hooked_api_add_verb_cb,
1042 .api_del_verb = hooked_api_del_verb_cb,
1043 .api_set_on_event = hooked_api_set_on_event_cb,
1044 .api_set_on_init = hooked_api_set_on_init_cb,
1045 .api_seal = hooked_api_seal_cb,
1046 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1047 .event_handler_add = hooked_event_handler_add_cb,
1048 .event_handler_del = hooked_event_handler_del_cb,
1050 .call = hooked_call_x3,
1051 .call_sync = hooked_call_sync_x3,
1053 .class_provide = hooked_class_provide_cb,
1054 .class_require = hooked_class_require_cb,
1056 .delete_api = hooked_delete_api_cb,
1059 /******************************************************************************
1060 ******************************************************************************
1061 ******************************************************************************
1062 ******************************************************************************
1064 ******************************************************************************
1065 ******************************************************************************
1066 ******************************************************************************
1067 ******************************************************************************/
1070 * Propagates the event to the service
1072 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1074 struct event_handler *handler;
1075 struct afb_export *export = from_api_x3(closure);
1077 /* hook the event before */
1078 if (export->hooksvc & afb_hook_flag_api_on_event)
1079 afb_hook_api_on_event_before(export, event, eventid, object);
1081 /* transmit to specific handlers */
1082 /* search the handler */
1083 handler = export->event_handlers;
1085 if (fnmatch(handler->pattern, event, 0)) {
1086 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1087 handler->callback(handler->closure, event, object, to_api_x3(export));
1089 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1090 handler->callback(handler->closure, event, object, to_api_x3(export));
1091 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1094 handler = handler->next;
1097 /* transmit to default handler */
1098 if (export->on_any_event_v3)
1099 export->on_any_event_v3(to_api_x3(export), event, object);
1100 else if (export->on_any_event_v12)
1101 export->on_any_event_v12(event, object);
1103 /* hook the event after */
1104 if (export->hooksvc & afb_hook_flag_api_on_event)
1105 afb_hook_api_on_event_after(export, event, eventid, object);
1106 json_object_put(object);
1109 /* the interface for events */
1110 static const struct afb_evt_itf evt_itf = {
1111 .broadcast = listener_of_events,
1112 .push = listener_of_events
1115 /* ensure an existing listener */
1116 static int ensure_listener(struct afb_export *export)
1118 if (!export->listener) {
1119 export->listener = afb_evt_listener_create(&evt_itf, export);
1120 if (export->listener == NULL)
1126 int afb_export_event_handler_add(
1127 struct afb_export *export,
1128 const char *pattern,
1129 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1133 struct event_handler *handler, **previous;
1135 rc = ensure_listener(export);
1139 /* search the handler */
1140 previous = &export->event_handlers;
1141 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1142 previous = &handler->next;
1144 /* error if found */
1146 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1151 /* create the event */
1152 handler = malloc(strlen(pattern) + strlen(pattern));
1154 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1159 /* init and record */
1160 handler->next = NULL;
1161 handler->callback = callback;
1162 handler->closure = closure;
1163 strcpy(handler->pattern, pattern);
1164 export->event_handlers = handler;
1169 int afb_export_event_handler_del(
1170 struct afb_export *export,
1171 const char *pattern,
1174 struct event_handler *handler, **previous;
1176 /* search the handler */
1177 previous = &export->event_handlers;
1178 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1179 previous = &handler->next;
1181 /* error if found */
1183 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1188 /* remove the found event */
1190 *closure = handler->closure;
1192 *previous = handler->next;
1197 /******************************************************************************
1198 ******************************************************************************
1199 ******************************************************************************
1200 ******************************************************************************
1202 ******************************************************************************
1203 ******************************************************************************
1204 ******************************************************************************
1205 ******************************************************************************/
1207 static struct afb_export *create(
1208 struct afb_apiset *declare_set,
1209 struct afb_apiset *call_set,
1210 const char *apiname,
1211 enum afb_api_version version)
1213 struct afb_export *export;
1215 /* session shared with other exports */
1216 if (common_session == NULL) {
1217 common_session = afb_session_create (0);
1218 if (common_session == NULL)
1221 export = calloc(1, sizeof *export + strlen(apiname));
1225 export->refcount = 1;
1226 strcpy(export->name, apiname);
1227 export->api.apiname = export->name;
1228 export->version = version;
1229 export->state = Api_State_Pre_Init;
1230 export->session = afb_session_addref(common_session);
1231 export->declare_set = afb_apiset_addref(declare_set);
1232 export->call_set = afb_apiset_addref(call_set);
1237 struct afb_export *afb_export_addref(struct afb_export *export)
1240 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1244 void afb_export_unref(struct afb_export *export)
1246 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1247 afb_export_destroy(export);
1250 void afb_export_destroy(struct afb_export *export)
1252 struct event_handler *handler;
1255 while ((handler = export->event_handlers)) {
1256 export->event_handlers = handler->next;
1259 if (export->listener != NULL)
1260 afb_evt_listener_unref(export->listener);
1261 afb_session_unref(export->session);
1262 afb_apiset_unref(export->declare_set);
1263 afb_apiset_unref(export->call_set);
1264 if (export->api.apiname != export->name)
1265 free((void*)export->api.apiname);
1270 struct afb_export *afb_export_create_none_for_path(
1271 struct afb_apiset *declare_set,
1272 struct afb_apiset *call_set,
1274 int (*creator)(void*, struct afb_api_x3*),
1277 struct afb_export *export = create(declare_set, call_set, path, Api_Version_None);
1279 afb_export_logmask_set(export, logmask);
1280 afb_export_update_hooks(export);
1281 if (creator && creator(closure, to_api_x3(export)) < 0) {
1282 afb_export_unref(export);
1289 #if defined(WITH_LEGACY_BINDING_V1)
1290 struct afb_export *afb_export_create_v1(
1291 struct afb_apiset *declare_set,
1292 struct afb_apiset *call_set,
1293 const char *apiname,
1294 int (*init)(struct afb_service_x1),
1295 void (*onevent)(const char*, struct json_object*))
1297 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_1);
1299 export->init.v1 = init;
1300 export->on_any_event_v12 = onevent;
1301 export->export.v1.mode = AFB_MODE_LOCAL;
1302 export->export.v1.daemon.closure = to_api_x3(export);
1303 afb_export_logmask_set(export, logmask);
1304 afb_export_update_hooks(export);
1310 struct afb_export *afb_export_create_v2(
1311 struct afb_apiset *declare_set,
1312 struct afb_apiset *call_set,
1313 const char *apiname,
1314 const struct afb_binding_v2 *binding,
1315 struct afb_binding_data_v2 *data,
1317 void (*onevent)(const char*, struct json_object*))
1319 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_2);
1321 export->init.v2 = init;
1322 export->on_any_event_v12 = onevent;
1323 export->desc.v2 = binding;
1324 export->export.v2 = data;
1325 data->daemon.closure = to_api_x3(export);
1326 data->service.closure = to_api_x3(export);
1327 afb_export_logmask_set(export, logmask);
1328 afb_export_update_hooks(export);
1333 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1334 struct afb_apiset *call_set,
1335 const char *apiname,
1336 struct afb_api_v3 *apiv3)
1338 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_3);
1340 export->unsealed = 1;
1341 export->desc.v3 = apiv3;
1342 afb_export_logmask_set(export, logmask);
1343 afb_export_update_hooks(export);
1348 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1350 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1353 int afb_export_rename(struct afb_export *export, const char *apiname)
1357 if (export->declared) {
1362 /* copy the name locally */
1363 name = strdup(apiname);
1369 if (export->api.apiname != export->name)
1370 free((void*)export->api.apiname);
1371 export->api.apiname = name;
1373 afb_export_update_hooks(export);
1377 const char *afb_export_apiname(const struct afb_export *export)
1379 return export->api.apiname;
1382 void afb_export_update_hooks(struct afb_export *export)
1384 export->hookditf = afb_hook_flags_api(export->api.apiname);
1385 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1386 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1388 switch (export->version) {
1389 #if defined(WITH_LEGACY_BINDING_V1)
1391 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1395 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1396 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1401 int afb_export_unshare_session(struct afb_export *export)
1403 if (export->session == common_session) {
1404 export->session = afb_session_create (0);
1405 if (export->session)
1406 afb_session_unref(common_session);
1408 export->session = common_session;
1415 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1418 switch (export->version) {
1419 #if defined(WITH_LEGACY_BINDING_V1)
1425 ERROR("invalid version 12 for API %s", export->api.apiname);
1430 export->on_any_event_v12 = on_event;
1431 return ensure_listener(export);
1434 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))
1437 switch (export->version) {
1438 case Api_Version_3: break;
1440 ERROR("invalid version Dyn for API %s", export->api.apiname);
1445 export->on_any_event_v3 = on_event;
1446 return ensure_listener(export);
1449 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1451 if (export->state != Api_State_Pre_Init) {
1452 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1457 export->init.v3 = oninit;
1461 #if defined(WITH_LEGACY_BINDING_V1)
1463 * Starts a new service (v1)
1465 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1467 return export->desc.v1 = regfun(&export->export.v1);
1471 int afb_export_preinit_x3(
1472 struct afb_export *export,
1473 int (*preinit)(void*, struct afb_api_x3*),
1476 return preinit(closure, to_api_x3(export));
1479 int afb_export_logmask_get(const struct afb_export *export)
1481 return export->api.logmask;
1484 void afb_export_logmask_set(struct afb_export *export, int mask)
1486 export->api.logmask = mask;
1487 switch (export->version) {
1488 #if defined(WITH_LEGACY_BINDING_V1)
1489 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1491 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1495 void *afb_export_userdata_get(const struct afb_export *export)
1497 return export->api.userdata;
1500 void afb_export_userdata_set(struct afb_export *export, void *data)
1502 export->api.userdata = data;
1505 /******************************************************************************
1506 ******************************************************************************
1507 ******************************************************************************
1508 ******************************************************************************
1510 ******************************************************************************
1511 ******************************************************************************
1512 ******************************************************************************
1513 ******************************************************************************/
1518 struct afb_export *export;
1521 static void do_init(int sig, void *closure)
1524 struct init *init = closure;
1525 struct afb_export *export;
1530 export = init->export;
1531 switch (export->version) {
1532 #if defined(WITH_LEGACY_BINDING_V1)
1534 rc = export->init.v1 ? export->init.v1(
1535 (struct afb_service_x1){
1536 .itf = &hooked_service_itf,
1537 .closure = to_api_x3(export) }) : 0;
1541 rc = export->init.v2 ? export->init.v2() : 0;
1544 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1551 init->return_code = rc;
1555 int afb_export_start(struct afb_export *export)
1561 switch (export->state) {
1565 case Api_State_Init:
1566 /* starting in progress: it is an error */
1567 ERROR("Service of API %s required started while starting", export->api.apiname);
1574 /* set event handling */
1575 switch (export->version) {
1576 #if defined(WITH_LEGACY_BINDING_V1)
1580 if (export->on_any_event_v12) {
1581 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1590 ERROR("Can't set event handler for %s", export->api.apiname);
1594 /* Starts the service */
1595 if (export->hooksvc & afb_hook_flag_api_start)
1596 afb_hook_api_start_before(export);
1598 export->state = Api_State_Init;
1599 init.export = export;
1600 sig_monitor(0, do_init, &init);
1601 rc = init.return_code;
1602 export->state = Api_State_Run;
1604 if (export->hooksvc & afb_hook_flag_api_start)
1605 afb_hook_api_start_after(export, rc);
1608 /* initialisation error */
1609 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1616 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1618 struct afb_export *export = closure;
1620 xreq->request.api = to_api_x3(export);
1622 switch (export->version) {
1623 #if defined(WITH_LEGACY_BINDING_V1)
1625 afb_api_so_v1_process_call(export->desc.v1, xreq);
1629 afb_api_so_v2_process_call(export->desc.v2, xreq);
1632 afb_api_v3_process_call(export->desc.v3, xreq);
1635 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1640 static struct json_object *api_describe_cb(void *closure)
1642 struct afb_export *export = closure;
1643 struct json_object *result;
1645 switch (export->version) {
1646 #if defined(WITH_LEGACY_BINDING_V1)
1648 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1652 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1655 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1664 static int api_service_start_cb(void *closure)
1666 struct afb_export *export = closure;
1668 return afb_export_start(export);
1671 static void api_update_hooks_cb(void *closure)
1673 struct afb_export *export = closure;
1675 afb_export_update_hooks(export);
1678 static int api_get_logmask_cb(void *closure)
1680 struct afb_export *export = closure;
1682 return afb_export_logmask_get(export);
1685 static void api_set_logmask_cb(void *closure, int level)
1687 struct afb_export *export = closure;
1689 afb_export_logmask_set(export, level);
1692 static void api_unref_cb(void *closure)
1694 struct afb_export *export = closure;
1696 afb_export_unref(export);
1699 static struct afb_api_itf export_api_itf =
1701 .call = api_call_cb,
1702 .service_start = api_service_start_cb,
1703 .update_hooks = api_update_hooks_cb,
1704 .get_logmask = api_get_logmask_cb,
1705 .set_logmask = api_set_logmask_cb,
1706 .describe = api_describe_cb,
1707 .unref = api_unref_cb
1710 int afb_export_declare(struct afb_export *export,
1714 struct afb_api_item afb_api;
1716 if (export->declared)
1719 /* init the record structure */
1720 afb_api.closure = afb_export_addref(export);
1721 afb_api.itf = &export_api_itf;
1722 afb_api.group = noconcurrency ? export : NULL;
1724 /* records the binding */
1725 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1727 export->declared = 1;
1729 ERROR("can't declare export %s to set %s, ABORTING it!",
1730 export->api.apiname,
1731 afb_apiset_name(export->declare_set));
1732 afb_export_addref(export);
1739 void afb_export_undeclare(struct afb_export *export)
1741 if (export->declared) {
1742 export->declared = 0;
1743 afb_apiset_del(export->declare_set, export->api.apiname);
1747 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1749 return afb_evt_event_x2_add_watch(export->listener, event);
1752 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1754 return afb_evt_event_x2_remove_watch(export->listener, event);
1757 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1759 afb_xreq_process(xreq, export->call_set);
1762 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1764 afb_context_init(context, export->session, NULL);