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"
51 /*************************************************************************
53 ************************************************************************/
56 * structure for handling events
60 /* link to the next event handler of the list */
61 struct event_handler *next;
63 /* function to call on the case of the event */
64 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*);
66 /* closure for the callback */
69 /* the handled pattern */
74 * Actually supported versions
79 #if defined(WITH_LEGACY_BINDING_V1)
87 * The states of exported APIs
97 * structure of the exported API
102 struct afb_api_x3 api;
104 /* reference count */
107 /* version of the api */
114 unsigned declared: 1;
117 unsigned unsealed: 1;
123 /* session for service */
124 struct afb_session *session;
126 /* apiset the API is declared in */
127 struct afb_apiset *declare_set;
129 /* apiset for calls */
130 struct afb_apiset *call_set;
132 /* event listener for service or NULL */
133 struct afb_evt_listener *listener;
135 /* event handler list */
136 struct event_handler *event_handlers;
138 /* internal descriptors */
140 #if defined(WITH_LEGACY_BINDING_V1)
141 struct afb_binding_v1 *v1;
143 const struct afb_binding_v2 *v2;
144 struct afb_api_v3 *v3;
149 #if defined(WITH_LEGACY_BINDING_V1)
150 int (*v1)(struct afb_service_x1);
153 int (*v3)(struct afb_api_x3 *api);
157 void (*on_any_event_v12)(const char *event, struct json_object *object);
158 void (*on_any_event_v3)(struct afb_api_x3 *api, const char *event, struct json_object *object);
162 #if defined(WITH_LEGACY_BINDING_V1)
163 struct afb_binding_interface_v1 v1;
165 struct afb_binding_data_v2 *v2;
172 /*****************************************************************************/
174 static inline struct afb_api_x3 *to_api_x3(struct afb_export *export)
176 return (struct afb_api_x3*)export;
179 static inline struct afb_export *from_api_x3(struct afb_api_x3 *api)
181 return (struct afb_export*)api;
184 struct afb_export *afb_export_from_api_x3(struct afb_api_x3 *api)
186 return from_api_x3(api);
189 struct afb_api_x3 *afb_export_to_api_x3(struct afb_export *export)
191 return to_api_x3(export);
194 /******************************************************************************
195 ******************************************************************************
196 ******************************************************************************
197 ******************************************************************************
199 ******************************************************************************
200 ******************************************************************************
201 ******************************************************************************
202 ******************************************************************************/
204 /**********************************************
206 **********************************************/
207 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)
210 struct afb_export *export = from_api_x3(closure);
212 if (!fmt || vasprintf(&p, fmt, args) < 0)
213 vverbose(level, file, line, function, fmt, args);
215 verbose(level, file, line, function, "[API %s] %s", export->api.apiname, p);
220 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
222 vverbose_cb(closure, level, file, line, NULL, fmt, args);
225 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
227 struct afb_export *export = from_api_x3(closure);
229 /* check daemon state */
230 if (export->state == Api_State_Pre_Init) {
231 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
236 /* create the event */
237 return afb_evt_event_x2_create2(export->api.apiname, name);
240 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
242 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
243 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
246 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
250 struct afb_export *export = from_api_x3(closure);
252 /* check daemon state */
253 if (export->state == Api_State_Pre_Init) {
254 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));
259 /* makes the event name */
260 plen = strlen(export->api.apiname);
262 event = alloca(nlen + plen + 2);
263 memcpy(event, export->api.apiname, plen);
265 memcpy(event + plen + 1, name, nlen + 1);
267 /* broadcast the event */
268 return afb_evt_broadcast(event, object);
271 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
273 return afb_common_rootdir_open_locale(filename, flags, locale);
276 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
278 return jobs_queue(group, timeout, callback, argument);
281 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
283 return afb_xreq_unstore(sreq);
286 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
288 struct afb_export *export = from_api_x3(closure);
290 char *iter, *end, save;
292 /* scan the names in a local copy */
294 iter = strdupa(name);
300 if (!save) /* at end? */
303 /* search for the end */
305 while (save && !isspace(save))
309 /* check the required api */
310 if (export->state == Api_State_Pre_Init)
311 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
313 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
322 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
324 struct afb_export *export = from_api_x3(closure);
325 if (!afb_api_is_valid_name(aliasname)) {
326 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
330 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
331 afb_export_add_alias(export, apiname, aliasname);
335 static struct afb_api_x3 *api_new_api_cb(
336 struct afb_api_x3 *closure,
340 int (*preinit)(void*, struct afb_api_x3 *),
341 void *preinit_closure)
343 struct afb_export *export = from_api_x3(closure);
344 struct afb_api_v3 *apiv3 = afb_api_v3_create(export->declare_set, export->call_set, api, info, noconcurrency, preinit, preinit_closure, 1);
345 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
348 /**********************************************
350 **********************************************/
351 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)
353 struct afb_export *export = from_api_x3(closure);
356 vverbose_cb(closure, level, file, line, function, fmt, args);
357 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
361 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)
363 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
366 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
368 struct afb_export *export = from_api_x3(closure);
369 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
370 afb_hook_api_event_make(export, name, r);
374 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
376 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
377 struct afb_event_x1 e;
379 e.itf = event ? event->itf : NULL;
383 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
386 struct afb_export *export = from_api_x3(closure);
387 json_object_get(object);
388 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
389 r = event_broadcast_cb(closure, name, object);
390 afb_hook_api_event_broadcast_after(export, name, object, r);
391 json_object_put(object);
395 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
397 struct afb_export *export = from_api_x3(closure);
398 struct sd_event *r = afb_systemd_get_event_loop();
399 return afb_hook_api_get_event_loop(export, r);
402 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
404 struct afb_export *export = from_api_x3(closure);
405 struct sd_bus *r = afb_systemd_get_user_bus();
406 return afb_hook_api_get_user_bus(export, r);
409 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
411 struct afb_export *export = from_api_x3(closure);
412 struct sd_bus *r = afb_systemd_get_system_bus();
413 return afb_hook_api_get_system_bus(export, r);
416 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
418 struct afb_export *export = from_api_x3(closure);
419 int r = afb_common_rootdir_get_fd();
420 return afb_hook_api_rootdir_get_fd(export, r);
423 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
425 struct afb_export *export = from_api_x3(closure);
426 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
427 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
430 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
432 struct afb_export *export = from_api_x3(closure);
433 int r = queue_job_cb(closure, callback, argument, group, timeout);
434 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
437 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
439 struct afb_export *export = from_api_x3(closure);
440 afb_hook_api_legacy_unstore_req(export, sreq);
441 return legacy_unstore_req_cb(closure, sreq);
444 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
447 struct afb_export *export = from_api_x3(closure);
448 afb_hook_api_require_api(export, name, initialized);
449 result = require_api_cb(closure, name, initialized);
450 return afb_hook_api_require_api_result(export, name, initialized, result);
453 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
455 struct afb_export *export = from_api_x3(closure);
456 int result = add_alias_cb(closure, apiname, aliasname);
457 return afb_hook_api_add_alias(export, apiname, aliasname, result);
460 static struct afb_api_x3 *hooked_api_new_api_cb(
461 struct afb_api_x3 *closure,
465 int (*preinit)(void*, struct afb_api_x3 *),
466 void *preinit_closure)
468 struct afb_api_x3 *result;
469 struct afb_export *export = from_api_x3(closure);
470 afb_hook_api_new_api_before(export, api, info, noconcurrency);
471 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
472 afb_hook_api_new_api_after(export, -!result, api);
476 /**********************************************
478 **********************************************/
479 static const struct afb_daemon_itf_x1 daemon_itf = {
480 .vverbose_v1 = legacy_vverbose_v1_cb,
481 .vverbose_v2 = vverbose_cb,
482 .event_make = legacy_event_x1_make_cb,
483 .event_broadcast = event_broadcast_cb,
484 .get_event_loop = afb_systemd_get_event_loop,
485 .get_user_bus = afb_systemd_get_user_bus,
486 .get_system_bus = afb_systemd_get_system_bus,
487 .rootdir_get_fd = afb_common_rootdir_get_fd,
488 .rootdir_open_locale = rootdir_open_locale_cb,
489 .queue_job = queue_job_cb,
490 .unstore_req = legacy_unstore_req_cb,
491 .require_api = require_api_cb,
492 .add_alias = add_alias_cb,
493 .new_api = api_new_api_cb,
496 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
497 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
498 .vverbose_v2 = hooked_vverbose_cb,
499 .event_make = legacy_hooked_event_x1_make_cb,
500 .event_broadcast = hooked_event_broadcast_cb,
501 .get_event_loop = hooked_get_event_loop,
502 .get_user_bus = hooked_get_user_bus,
503 .get_system_bus = hooked_get_system_bus,
504 .rootdir_get_fd = hooked_rootdir_get_fd,
505 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
506 .queue_job = hooked_queue_job_cb,
507 .unstore_req = legacy_hooked_unstore_req_cb,
508 .require_api = hooked_require_api_cb,
509 .add_alias = hooked_add_alias_cb,
510 .new_api = hooked_api_new_api_cb,
513 /******************************************************************************
514 ******************************************************************************
515 ******************************************************************************
516 ******************************************************************************
518 ******************************************************************************
519 ******************************************************************************
520 ******************************************************************************
521 ******************************************************************************/
523 /* the common session for services sharing their session */
524 static struct afb_session *common_session;
526 /******************************************************************************
527 ******************************************************************************
528 ******************************************************************************
529 ******************************************************************************
531 ******************************************************************************
532 ******************************************************************************
533 ******************************************************************************
534 ******************************************************************************/
537 struct afb_api_x3 *apix3,
540 struct json_object *args,
541 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
544 struct afb_export *export = from_api_x3(apix3);
545 return afb_calls_call(export, api, verb, args, callback, closure);
548 static int call_sync_x3(
549 struct afb_api_x3 *apix3,
552 struct json_object *args,
553 struct json_object **object,
557 struct afb_export *export = from_api_x3(apix3);
558 return afb_calls_call_sync(export, api, verb, args, object, error, info);
561 static void legacy_call_v12(
562 struct afb_api_x3 *apix3,
565 struct json_object *args,
566 void (*callback)(void*, int, struct json_object*),
569 struct afb_export *export = from_api_x3(apix3);
570 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
573 static void legacy_call_x3(
574 struct afb_api_x3 *apix3,
577 struct json_object *args,
578 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
581 struct afb_export *export = from_api_x3(apix3);
582 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
585 static int legacy_call_sync(
586 struct afb_api_x3 *apix3,
589 struct json_object *args,
590 struct json_object **result)
592 struct afb_export *export = from_api_x3(apix3);
593 return afb_calls_legacy_call_sync(export, api, verb, args, result);
596 static void hooked_call_x3(
597 struct afb_api_x3 *apix3,
600 struct json_object *args,
601 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
604 struct afb_export *export = from_api_x3(apix3);
605 afb_calls_hooked_call(export, api, verb, args, callback, closure);
608 static int hooked_call_sync_x3(
609 struct afb_api_x3 *apix3,
612 struct json_object *args,
613 struct json_object **object,
617 struct afb_export *export = from_api_x3(apix3);
618 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
621 static void legacy_hooked_call_v12(
622 struct afb_api_x3 *apix3,
625 struct json_object *args,
626 void (*callback)(void*, int, struct json_object*),
629 struct afb_export *export = from_api_x3(apix3);
630 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
633 static void legacy_hooked_call_x3(
634 struct afb_api_x3 *apix3,
637 struct json_object *args,
638 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
641 struct afb_export *export = from_api_x3(apix3);
642 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
645 static int legacy_hooked_call_sync(
646 struct afb_api_x3 *apix3,
649 struct json_object *args,
650 struct json_object **result)
652 struct afb_export *export = from_api_x3(apix3);
653 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
656 /* the interface for services */
657 static const struct afb_service_itf_x1 service_itf = {
658 .call = legacy_call_v12,
659 .call_sync = legacy_call_sync
662 /* the interface for services */
663 static const struct afb_service_itf_x1 hooked_service_itf = {
664 .call = legacy_hooked_call_v12,
665 .call_sync = legacy_hooked_call_sync
668 /******************************************************************************
669 ******************************************************************************
670 ******************************************************************************
671 ******************************************************************************
673 ******************************************************************************
674 ******************************************************************************
675 ******************************************************************************
676 ******************************************************************************/
678 static int api_set_verbs_v2_cb(
679 struct afb_api_x3 *api,
680 const struct afb_verb_v2 *verbs)
682 struct afb_export *export = from_api_x3(api);
684 if (export->unsealed) {
685 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
693 static int api_set_verbs_v3_cb(
694 struct afb_api_x3 *api,
695 const struct afb_verb_v3 *verbs)
697 struct afb_export *export = from_api_x3(api);
699 if (!export->unsealed) {
704 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
708 static int api_add_verb_cb(
709 struct afb_api_x3 *api,
712 void (*callback)(struct afb_req_x2 *req),
714 const struct afb_auth *auth,
718 struct afb_export *export = from_api_x3(api);
720 if (!export->unsealed) {
725 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
728 static int api_del_verb_cb(
729 struct afb_api_x3 *api,
733 struct afb_export *export = from_api_x3(api);
735 if (!export->unsealed) {
740 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
743 static int api_set_on_event_cb(
744 struct afb_api_x3 *api,
745 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
747 struct afb_export *export = from_api_x3(api);
748 return afb_export_handle_events_v3(export, onevent);
751 static int api_set_on_init_cb(
752 struct afb_api_x3 *api,
753 int (*oninit)(struct afb_api_x3 *api))
755 struct afb_export *export = from_api_x3(api);
757 return afb_export_handle_init_v3(export, oninit);
760 static void api_seal_cb(
761 struct afb_api_x3 *api)
763 struct afb_export *export = from_api_x3(api);
765 export->unsealed = 0;
768 static int event_handler_add_cb(
769 struct afb_api_x3 *api,
771 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
774 struct afb_export *export = from_api_x3(api);
776 return afb_export_event_handler_add(export, pattern, callback, closure);
779 static int event_handler_del_cb(
780 struct afb_api_x3 *api,
784 struct afb_export *export = from_api_x3(api);
786 return afb_export_event_handler_del(export, pattern, closure);
789 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
791 struct afb_export *export = from_api_x3(api);
794 char *iter, *end, save;
796 iter = strdupa(name);
802 if (!save) /* at end? */
805 /* search for the end */
807 while (save && !isspace(save))
811 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
820 static int class_require_cb(struct afb_api_x3 *api, const char *name)
822 struct afb_export *export = from_api_x3(api);
825 char *iter, *end, save;
827 iter = strdupa(name);
833 if (!save) /* at end? */
836 /* search for the end */
838 while (save && !isspace(save))
842 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
851 static int delete_api_cb(struct afb_api_x3 *api)
853 struct afb_export *export = from_api_x3(api);
855 if (!export->unsealed) {
860 afb_export_undeclare(export);
861 afb_export_unref(export);
865 static int hooked_api_set_verbs_v2_cb(
866 struct afb_api_x3 *api,
867 const struct afb_verb_v2 *verbs)
869 struct afb_export *export = from_api_x3(api);
870 int result = api_set_verbs_v2_cb(api, verbs);
871 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
874 static int hooked_api_set_verbs_v3_cb(
875 struct afb_api_x3 *api,
876 const struct afb_verb_v3 *verbs)
878 struct afb_export *export = from_api_x3(api);
879 int result = api_set_verbs_v3_cb(api, verbs);
880 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
883 static int hooked_api_add_verb_cb(
884 struct afb_api_x3 *api,
887 void (*callback)(struct afb_req_x2 *req),
889 const struct afb_auth *auth,
893 struct afb_export *export = from_api_x3(api);
894 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
895 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
898 static int hooked_api_del_verb_cb(
899 struct afb_api_x3 *api,
903 struct afb_export *export = from_api_x3(api);
904 int result = api_del_verb_cb(api, verb, vcbdata);
905 return afb_hook_api_api_del_verb(export, result, verb);
908 static int hooked_api_set_on_event_cb(
909 struct afb_api_x3 *api,
910 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
912 struct afb_export *export = from_api_x3(api);
913 int result = api_set_on_event_cb(api, onevent);
914 return afb_hook_api_api_set_on_event(export, result);
917 static int hooked_api_set_on_init_cb(
918 struct afb_api_x3 *api,
919 int (*oninit)(struct afb_api_x3 *api))
921 struct afb_export *export = from_api_x3(api);
922 int result = api_set_on_init_cb(api, oninit);
923 return afb_hook_api_api_set_on_init(export, result);
926 static void hooked_api_seal_cb(
927 struct afb_api_x3 *api)
929 struct afb_export *export = from_api_x3(api);
930 afb_hook_api_api_seal(export);
934 static int hooked_event_handler_add_cb(
935 struct afb_api_x3 *api,
937 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
940 struct afb_export *export = from_api_x3(api);
941 int result = event_handler_add_cb(api, pattern, callback, closure);
942 return afb_hook_api_event_handler_add(export, result, pattern);
945 static int hooked_event_handler_del_cb(
946 struct afb_api_x3 *api,
950 struct afb_export *export = from_api_x3(api);
951 int result = event_handler_del_cb(api, pattern, closure);
952 return afb_hook_api_event_handler_del(export, result, pattern);
955 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
957 struct afb_export *export = from_api_x3(api);
958 int result = class_provide_cb(api, name);
959 return afb_hook_api_class_provide(export, result, name);
962 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
964 struct afb_export *export = from_api_x3(api);
965 int result = class_require_cb(api, name);
966 return afb_hook_api_class_require(export, result, name);
969 static int hooked_delete_api_cb(struct afb_api_x3 *api)
971 struct afb_export *export = afb_export_addref(from_api_x3(api));
972 int result = delete_api_cb(api);
973 result = afb_hook_api_delete_api(export, result);
974 afb_export_unref(export);
978 static const struct afb_api_x3_itf api_x3_itf = {
980 .vverbose = (void*)vverbose_cb,
982 .get_event_loop = afb_systemd_get_event_loop,
983 .get_user_bus = afb_systemd_get_user_bus,
984 .get_system_bus = afb_systemd_get_system_bus,
985 .rootdir_get_fd = afb_common_rootdir_get_fd,
986 .rootdir_open_locale = rootdir_open_locale_cb,
987 .queue_job = queue_job_cb,
989 .require_api = require_api_cb,
990 .add_alias = add_alias_cb,
992 .event_broadcast = event_broadcast_cb,
993 .event_make = event_x2_make_cb,
995 .legacy_call = legacy_call_x3,
996 .legacy_call_sync = legacy_call_sync,
998 .api_new_api = api_new_api_cb,
999 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1000 .api_add_verb = api_add_verb_cb,
1001 .api_del_verb = api_del_verb_cb,
1002 .api_set_on_event = api_set_on_event_cb,
1003 .api_set_on_init = api_set_on_init_cb,
1004 .api_seal = api_seal_cb,
1005 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1006 .event_handler_add = event_handler_add_cb,
1007 .event_handler_del = event_handler_del_cb,
1010 .call_sync = call_sync_x3,
1012 .class_provide = class_provide_cb,
1013 .class_require = class_require_cb,
1015 .delete_api = delete_api_cb,
1018 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1020 .vverbose = hooked_vverbose_cb,
1022 .get_event_loop = hooked_get_event_loop,
1023 .get_user_bus = hooked_get_user_bus,
1024 .get_system_bus = hooked_get_system_bus,
1025 .rootdir_get_fd = hooked_rootdir_get_fd,
1026 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1027 .queue_job = hooked_queue_job_cb,
1029 .require_api = hooked_require_api_cb,
1030 .add_alias = hooked_add_alias_cb,
1032 .event_broadcast = hooked_event_broadcast_cb,
1033 .event_make = hooked_event_x2_make_cb,
1035 .legacy_call = legacy_hooked_call_x3,
1036 .legacy_call_sync = legacy_hooked_call_sync,
1038 .api_new_api = hooked_api_new_api_cb,
1039 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1040 .api_add_verb = hooked_api_add_verb_cb,
1041 .api_del_verb = hooked_api_del_verb_cb,
1042 .api_set_on_event = hooked_api_set_on_event_cb,
1043 .api_set_on_init = hooked_api_set_on_init_cb,
1044 .api_seal = hooked_api_seal_cb,
1045 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1046 .event_handler_add = hooked_event_handler_add_cb,
1047 .event_handler_del = hooked_event_handler_del_cb,
1049 .call = hooked_call_x3,
1050 .call_sync = hooked_call_sync_x3,
1052 .class_provide = hooked_class_provide_cb,
1053 .class_require = hooked_class_require_cb,
1055 .delete_api = hooked_delete_api_cb,
1058 /******************************************************************************
1059 ******************************************************************************
1060 ******************************************************************************
1061 ******************************************************************************
1063 ******************************************************************************
1064 ******************************************************************************
1065 ******************************************************************************
1066 ******************************************************************************/
1069 * Propagates the event to the service
1071 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1073 struct event_handler *handler;
1074 struct afb_export *export = from_api_x3(closure);
1076 /* hook the event before */
1077 if (export->hooksvc & afb_hook_flag_api_on_event)
1078 afb_hook_api_on_event_before(export, event, eventid, object);
1080 /* transmit to specific handlers */
1081 /* search the handler */
1082 handler = export->event_handlers;
1084 if (fnmatch(handler->pattern, event, 0)) {
1085 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1086 handler->callback(handler->closure, event, object, to_api_x3(export));
1088 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1089 handler->callback(handler->closure, event, object, to_api_x3(export));
1090 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1093 handler = handler->next;
1096 /* transmit to default handler */
1097 if (export->on_any_event_v3)
1098 export->on_any_event_v3(to_api_x3(export), event, object);
1099 else if (export->on_any_event_v12)
1100 export->on_any_event_v12(event, object);
1102 /* hook the event after */
1103 if (export->hooksvc & afb_hook_flag_api_on_event)
1104 afb_hook_api_on_event_after(export, event, eventid, object);
1105 json_object_put(object);
1108 /* the interface for events */
1109 static const struct afb_evt_itf evt_itf = {
1110 .broadcast = listener_of_events,
1111 .push = listener_of_events
1114 /* ensure an existing listener */
1115 static int ensure_listener(struct afb_export *export)
1117 if (!export->listener) {
1118 export->listener = afb_evt_listener_create(&evt_itf, export);
1119 if (export->listener == NULL)
1125 int afb_export_event_handler_add(
1126 struct afb_export *export,
1127 const char *pattern,
1128 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1132 struct event_handler *handler, **previous;
1134 rc = ensure_listener(export);
1138 /* search the handler */
1139 previous = &export->event_handlers;
1140 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1141 previous = &handler->next;
1143 /* error if found */
1145 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1150 /* create the event */
1151 handler = malloc(strlen(pattern) + strlen(pattern));
1153 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1158 /* init and record */
1159 handler->next = NULL;
1160 handler->callback = callback;
1161 handler->closure = closure;
1162 strcpy(handler->pattern, pattern);
1163 export->event_handlers = handler;
1168 int afb_export_event_handler_del(
1169 struct afb_export *export,
1170 const char *pattern,
1173 struct event_handler *handler, **previous;
1175 /* search the handler */
1176 previous = &export->event_handlers;
1177 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1178 previous = &handler->next;
1180 /* error if found */
1182 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1187 /* remove the found event */
1189 *closure = handler->closure;
1191 *previous = handler->next;
1196 /******************************************************************************
1197 ******************************************************************************
1198 ******************************************************************************
1199 ******************************************************************************
1201 ******************************************************************************
1202 ******************************************************************************
1203 ******************************************************************************
1204 ******************************************************************************/
1206 static struct afb_export *create(
1207 struct afb_apiset *declare_set,
1208 struct afb_apiset *call_set,
1209 const char *apiname,
1210 enum afb_api_version version)
1212 struct afb_export *export;
1214 /* session shared with other exports */
1215 if (common_session == NULL) {
1216 common_session = afb_session_create (0);
1217 if (common_session == NULL)
1220 export = calloc(1, sizeof *export + strlen(apiname));
1224 export->refcount = 1;
1225 strcpy(export->name, apiname);
1226 export->api.apiname = export->name;
1227 export->version = version;
1228 export->state = Api_State_Pre_Init;
1229 export->session = afb_session_addref(common_session);
1230 export->declare_set = afb_apiset_addref(declare_set);
1231 export->call_set = afb_apiset_addref(call_set);
1236 struct afb_export *afb_export_addref(struct afb_export *export)
1239 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1243 void afb_export_unref(struct afb_export *export)
1245 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1246 afb_export_destroy(export);
1249 void afb_export_destroy(struct afb_export *export)
1251 struct event_handler *handler;
1254 while ((handler = export->event_handlers)) {
1255 export->event_handlers = handler->next;
1258 if (export->listener != NULL)
1259 afb_evt_listener_unref(export->listener);
1260 afb_session_unref(export->session);
1261 afb_apiset_unref(export->declare_set);
1262 afb_apiset_unref(export->call_set);
1263 if (export->api.apiname != export->name)
1264 free((void*)export->api.apiname);
1269 struct afb_export *afb_export_create_none_for_path(
1270 struct afb_apiset *declare_set,
1271 struct afb_apiset *call_set,
1273 int (*creator)(void*, struct afb_api_x3*),
1276 struct afb_export *export = create(declare_set, call_set, path, Api_Version_None);
1278 afb_export_logmask_set(export, logmask);
1279 afb_export_update_hooks(export);
1280 if (creator && creator(closure, to_api_x3(export)) < 0) {
1281 afb_export_unref(export);
1288 #if defined(WITH_LEGACY_BINDING_V1)
1289 struct afb_export *afb_export_create_v1(
1290 struct afb_apiset *declare_set,
1291 struct afb_apiset *call_set,
1292 const char *apiname,
1293 int (*init)(struct afb_service_x1),
1294 void (*onevent)(const char*, struct json_object*))
1296 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_1);
1298 export->init.v1 = init;
1299 export->on_any_event_v12 = onevent;
1300 export->export.v1.mode = AFB_MODE_LOCAL;
1301 export->export.v1.daemon.closure = to_api_x3(export);
1302 afb_export_logmask_set(export, logmask);
1303 afb_export_update_hooks(export);
1309 struct afb_export *afb_export_create_v2(
1310 struct afb_apiset *declare_set,
1311 struct afb_apiset *call_set,
1312 const char *apiname,
1313 const struct afb_binding_v2 *binding,
1314 struct afb_binding_data_v2 *data,
1316 void (*onevent)(const char*, struct json_object*))
1318 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_2);
1320 export->init.v2 = init;
1321 export->on_any_event_v12 = onevent;
1322 export->desc.v2 = binding;
1323 export->export.v2 = data;
1324 data->daemon.closure = to_api_x3(export);
1325 data->service.closure = to_api_x3(export);
1326 afb_export_logmask_set(export, logmask);
1327 afb_export_update_hooks(export);
1332 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1333 struct afb_apiset *call_set,
1334 const char *apiname,
1335 struct afb_api_v3 *apiv3)
1337 struct afb_export *export = create(declare_set, call_set, apiname, Api_Version_3);
1339 export->unsealed = 1;
1340 export->desc.v3 = apiv3;
1341 afb_export_logmask_set(export, logmask);
1342 afb_export_update_hooks(export);
1347 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1349 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1352 int afb_export_rename(struct afb_export *export, const char *apiname)
1356 if (export->declared) {
1361 /* copy the name locally */
1362 name = strdup(apiname);
1368 if (export->api.apiname != export->name)
1369 free((void*)export->api.apiname);
1370 export->api.apiname = name;
1372 afb_export_update_hooks(export);
1376 const char *afb_export_apiname(const struct afb_export *export)
1378 return export->api.apiname;
1381 void afb_export_update_hooks(struct afb_export *export)
1383 export->hookditf = afb_hook_flags_api(export->api.apiname);
1384 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1385 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1387 switch (export->version) {
1388 #if defined(WITH_LEGACY_BINDING_V1)
1390 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1394 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1395 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1400 int afb_export_unshare_session(struct afb_export *export)
1402 if (export->session == common_session) {
1403 export->session = afb_session_create (0);
1404 if (export->session)
1405 afb_session_unref(common_session);
1407 export->session = common_session;
1414 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1417 switch (export->version) {
1418 #if defined(WITH_LEGACY_BINDING_V1)
1424 ERROR("invalid version 12 for API %s", export->api.apiname);
1429 export->on_any_event_v12 = on_event;
1430 return ensure_listener(export);
1433 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))
1436 switch (export->version) {
1437 case Api_Version_3: break;
1439 ERROR("invalid version Dyn for API %s", export->api.apiname);
1444 export->on_any_event_v3 = on_event;
1445 return ensure_listener(export);
1448 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1450 if (export->state != Api_State_Pre_Init) {
1451 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1456 export->init.v3 = oninit;
1460 #if defined(WITH_LEGACY_BINDING_V1)
1462 * Starts a new service (v1)
1464 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1466 return export->desc.v1 = regfun(&export->export.v1);
1470 int afb_export_preinit_x3(
1471 struct afb_export *export,
1472 int (*preinit)(void*, struct afb_api_x3*),
1475 return preinit(closure, to_api_x3(export));
1478 int afb_export_logmask_get(const struct afb_export *export)
1480 return export->api.logmask;
1483 void afb_export_logmask_set(struct afb_export *export, int mask)
1485 export->api.logmask = mask;
1486 switch (export->version) {
1487 #if defined(WITH_LEGACY_BINDING_V1)
1488 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1490 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1494 void *afb_export_userdata_get(const struct afb_export *export)
1496 return export->api.userdata;
1499 void afb_export_userdata_set(struct afb_export *export, void *data)
1501 export->api.userdata = data;
1504 /******************************************************************************
1505 ******************************************************************************
1506 ******************************************************************************
1507 ******************************************************************************
1509 ******************************************************************************
1510 ******************************************************************************
1511 ******************************************************************************
1512 ******************************************************************************/
1514 int afb_export_start(struct afb_export *export, int share_session, int onneed)
1519 if (export->state != Api_State_Pre_Init) {
1520 /* not an error when onneed */
1524 /* already started: it is an error */
1525 ERROR("Service of API %s already started", export->api.apiname);
1529 /* unshare the session if asked */
1530 if (!share_session) {
1531 rc = afb_export_unshare_session(export);
1533 ERROR("Can't unshare the session for %s", export->api.apiname);
1538 /* set event handling */
1539 switch (export->version) {
1540 #if defined(WITH_LEGACY_BINDING_V1)
1544 if (export->on_any_event_v12)
1545 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1552 ERROR("Can't set event handler for %s", export->api.apiname);
1556 /* Starts the service */
1557 if (export->hooksvc & afb_hook_flag_api_start)
1558 afb_hook_api_start_before(export);
1560 export->state = Api_State_Init;
1561 switch (export->version) {
1562 #if defined(WITH_LEGACY_BINDING_V1)
1564 rc = export->init.v1 ? export->init.v1((struct afb_service_x1){ .itf = &hooked_service_itf, .closure = to_api_x3(export) }) : 0;
1568 rc = export->init.v2 ? export->init.v2() : 0;
1571 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1578 export->state = Api_State_Run;
1580 if (export->hooksvc & afb_hook_flag_api_start)
1581 afb_hook_api_start_after(export, rc);
1584 /* initialisation error */
1585 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1593 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1595 struct afb_export *export = closure;
1597 xreq->request.api = to_api_x3(export);
1599 switch (export->version) {
1600 #if defined(WITH_LEGACY_BINDING_V1)
1602 afb_api_so_v1_process_call(export->desc.v1, xreq);
1606 afb_api_so_v2_process_call(export->desc.v2, xreq);
1609 afb_api_v3_process_call(export->desc.v3, xreq);
1612 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1617 static struct json_object *api_describe_cb(void *closure)
1619 struct afb_export *export = closure;
1620 struct json_object *result;
1622 switch (export->version) {
1623 #if defined(WITH_LEGACY_BINDING_V1)
1625 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1629 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1632 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1641 static int api_service_start_cb(void *closure, int share_session, int onneed)
1643 struct afb_export *export = closure;
1645 return afb_export_start(export, share_session, onneed);
1648 static void api_update_hooks_cb(void *closure)
1650 struct afb_export *export = closure;
1652 afb_export_update_hooks(export);
1655 static int api_get_logmask_cb(void *closure)
1657 struct afb_export *export = closure;
1659 return afb_export_logmask_get(export);
1662 static void api_set_logmask_cb(void *closure, int level)
1664 struct afb_export *export = closure;
1666 afb_export_logmask_set(export, level);
1669 static void api_unref_cb(void *closure)
1671 struct afb_export *export = closure;
1673 afb_export_unref(export);
1676 static struct afb_api_itf export_api_itf =
1678 .call = api_call_cb,
1679 .service_start = api_service_start_cb,
1680 .update_hooks = api_update_hooks_cb,
1681 .get_logmask = api_get_logmask_cb,
1682 .set_logmask = api_set_logmask_cb,
1683 .describe = api_describe_cb,
1684 .unref = api_unref_cb
1687 int afb_export_declare(struct afb_export *export,
1691 struct afb_api_item afb_api;
1693 if (export->declared)
1696 /* init the record structure */
1697 afb_api.closure = afb_export_addref(export);
1698 afb_api.itf = &export_api_itf;
1699 afb_api.group = noconcurrency ? export : NULL;
1701 /* records the binding */
1702 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1704 export->declared = 1;
1706 ERROR("can't declare export %s to set %s, ABORTING it!",
1707 export->api.apiname,
1708 afb_apiset_name(export->declare_set));
1709 afb_export_addref(export);
1716 void afb_export_undeclare(struct afb_export *export)
1718 if (export->declared) {
1719 export->declared = 0;
1720 afb_apiset_del(export->declare_set, export->api.apiname);
1724 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1726 return afb_evt_event_x2_add_watch(export->listener, event);
1729 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1731 return afb_evt_event_x2_remove_watch(export->listener, event);
1734 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1736 afb_xreq_process(xreq, export->call_set);
1739 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1741 afb_context_init(context, export->session, NULL);