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;
233 /* clone the globals */
234 if (json_object_object_get_ex(configuration, "*", &obj))
235 result = wrap_json_clone(obj);
237 result = json_object_new_object();
240 if (json_object_object_get_ex(configuration, export->name, &obj))
241 wrap_json_object_add(result, obj);
243 /* add library path */
244 for (iter = export ; iter && !iter->path ; iter = iter->creator);
246 json_object_object_add(result, "binding-path", json_object_new_string(iter->path));
248 export->settings = result;
252 /******************************************************************************
253 ******************************************************************************
254 ******************************************************************************
255 ******************************************************************************
257 ******************************************************************************
258 ******************************************************************************
259 ******************************************************************************
260 ******************************************************************************/
262 /**********************************************
264 **********************************************/
265 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)
268 struct afb_export *export = from_api_x3(closure);
270 if (!fmt || vasprintf(&p, fmt, args) < 0)
271 vverbose(level, file, line, function, fmt, args);
273 verbose(level, file, line, function, "[API %s] %s", export->api.apiname, p);
278 static void legacy_vverbose_v1_cb(struct afb_api_x3 *closure, int level, const char *file, int line, const char *fmt, va_list args)
280 vverbose_cb(closure, level, file, line, NULL, fmt, args);
283 static struct afb_event_x2 *event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
285 struct afb_export *export = from_api_x3(closure);
287 /* check daemon state */
288 if (export->state == Api_State_Pre_Init) {
289 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->api.apiname, name);
294 /* create the event */
295 return afb_evt_event_x2_create2(export->api.apiname, name);
298 static struct afb_event_x1 legacy_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
300 struct afb_event_x2 *event = event_x2_make_cb(closure, name);
301 return afb_evt_event_from_evtid(afb_evt_event_x2_to_evtid(event));
304 static int event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
308 struct afb_export *export = from_api_x3(closure);
310 /* check daemon state */
311 if (export->state == Api_State_Pre_Init) {
312 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit",
313 export->api.apiname, name, json_object_to_json_string_ext(object, JSON_C_TO_STRING_NOSLASHESCAPE));
318 /* makes the event name */
319 plen = strlen(export->api.apiname);
321 event = alloca(nlen + plen + 2);
322 memcpy(event, export->api.apiname, plen);
324 memcpy(event + plen + 1, name, nlen + 1);
326 /* broadcast the event */
327 return afb_evt_broadcast(event, object);
330 static int rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
332 return afb_common_rootdir_open_locale(filename, flags, locale);
335 static int queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
337 return jobs_queue(group, timeout, callback, argument);
340 static struct afb_req_x1 legacy_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
342 return afb_xreq_unstore(sreq);
345 static int require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
347 struct afb_export *export = from_api_x3(closure);
349 char *iter, *end, save;
351 /* scan the names in a local copy */
353 iter = strdupa(name);
359 if (!save) /* at end? */
362 /* search for the end */
364 while (save && !isspace(save))
368 /* check the required api */
369 if (export->state == Api_State_Pre_Init)
370 rc2 = afb_apiset_require(export->declare_set, export->api.apiname, name);
372 rc2 = -!((initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->call_set, iter, 1));
381 static int add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
383 struct afb_export *export = from_api_x3(closure);
384 if (!afb_api_is_valid_name(aliasname)) {
385 ERROR("[API %s] Can't add alias to %s: bad API name", export->api.apiname, aliasname);
389 NOTICE("[API %s] aliasing [API %s] to [API %s]", export->api.apiname, apiname?:"<null>", aliasname);
390 afb_export_add_alias(export, apiname, aliasname);
394 static struct afb_api_x3 *api_new_api_cb(
395 struct afb_api_x3 *closure,
399 int (*preinit)(void*, struct afb_api_x3 *),
400 void *preinit_closure)
402 struct afb_export *export = from_api_x3(closure);
403 struct afb_api_v3 *apiv3 = afb_api_v3_create(
404 export->declare_set, export->call_set,
405 api, info, noconcurrency,
406 preinit, preinit_closure, 1,
408 return apiv3 ? to_api_x3(afb_api_v3_export(apiv3)) : NULL;
411 /**********************************************
413 **********************************************/
414 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)
416 struct afb_export *export = from_api_x3(closure);
419 vverbose_cb(closure, level, file, line, function, fmt, args);
420 afb_hook_api_vverbose(export, level, file, line, function, fmt, ap);
424 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)
426 hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
429 static struct afb_event_x2 *hooked_event_x2_make_cb(struct afb_api_x3 *closure, const char *name)
431 struct afb_export *export = from_api_x3(closure);
432 struct afb_event_x2 *r = event_x2_make_cb(closure, name);
433 afb_hook_api_event_make(export, name, r);
437 static struct afb_event_x1 legacy_hooked_event_x1_make_cb(struct afb_api_x3 *closure, const char *name)
439 struct afb_event_x2 *event = hooked_event_x2_make_cb(closure, name);
440 struct afb_event_x1 e;
442 e.itf = event ? event->itf : NULL;
446 static int hooked_event_broadcast_cb(struct afb_api_x3 *closure, const char *name, struct json_object *object)
449 struct afb_export *export = from_api_x3(closure);
450 json_object_get(object);
451 afb_hook_api_event_broadcast_before(export, name, json_object_get(object));
452 r = event_broadcast_cb(closure, name, object);
453 afb_hook_api_event_broadcast_after(export, name, object, r);
454 json_object_put(object);
458 static struct sd_event *hooked_get_event_loop(struct afb_api_x3 *closure)
460 struct afb_export *export = from_api_x3(closure);
461 struct sd_event *r = afb_systemd_get_event_loop();
462 return afb_hook_api_get_event_loop(export, r);
465 static struct sd_bus *hooked_get_user_bus(struct afb_api_x3 *closure)
467 struct afb_export *export = from_api_x3(closure);
468 struct sd_bus *r = afb_systemd_get_user_bus();
469 return afb_hook_api_get_user_bus(export, r);
472 static struct sd_bus *hooked_get_system_bus(struct afb_api_x3 *closure)
474 struct afb_export *export = from_api_x3(closure);
475 struct sd_bus *r = afb_systemd_get_system_bus();
476 return afb_hook_api_get_system_bus(export, r);
479 static int hooked_rootdir_get_fd(struct afb_api_x3 *closure)
481 struct afb_export *export = from_api_x3(closure);
482 int r = afb_common_rootdir_get_fd();
483 return afb_hook_api_rootdir_get_fd(export, r);
486 static int hooked_rootdir_open_locale_cb(struct afb_api_x3 *closure, const char *filename, int flags, const char *locale)
488 struct afb_export *export = from_api_x3(closure);
489 int r = rootdir_open_locale_cb(closure, filename, flags, locale);
490 return afb_hook_api_rootdir_open_locale(export, filename, flags, locale, r);
493 static int hooked_queue_job_cb(struct afb_api_x3 *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
495 struct afb_export *export = from_api_x3(closure);
496 int r = queue_job_cb(closure, callback, argument, group, timeout);
497 return afb_hook_api_queue_job(export, callback, argument, group, timeout, r);
500 static struct afb_req_x1 legacy_hooked_unstore_req_cb(struct afb_api_x3 *closure, struct afb_stored_req *sreq)
502 struct afb_export *export = from_api_x3(closure);
503 afb_hook_api_legacy_unstore_req(export, sreq);
504 return legacy_unstore_req_cb(closure, sreq);
507 static int hooked_require_api_cb(struct afb_api_x3 *closure, const char *name, int initialized)
510 struct afb_export *export = from_api_x3(closure);
511 afb_hook_api_require_api(export, name, initialized);
512 result = require_api_cb(closure, name, initialized);
513 return afb_hook_api_require_api_result(export, name, initialized, result);
516 static int hooked_add_alias_cb(struct afb_api_x3 *closure, const char *apiname, const char *aliasname)
518 struct afb_export *export = from_api_x3(closure);
519 int result = add_alias_cb(closure, apiname, aliasname);
520 return afb_hook_api_add_alias(export, apiname, aliasname, result);
523 static struct afb_api_x3 *hooked_api_new_api_cb(
524 struct afb_api_x3 *closure,
528 int (*preinit)(void*, struct afb_api_x3 *),
529 void *preinit_closure)
531 struct afb_api_x3 *result;
532 struct afb_export *export = from_api_x3(closure);
533 afb_hook_api_new_api_before(export, api, info, noconcurrency);
534 result = api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
535 afb_hook_api_new_api_after(export, -!result, api);
539 /**********************************************
541 **********************************************/
542 static const struct afb_daemon_itf_x1 daemon_itf = {
543 .vverbose_v1 = legacy_vverbose_v1_cb,
544 .vverbose_v2 = vverbose_cb,
545 .event_make = legacy_event_x1_make_cb,
546 .event_broadcast = event_broadcast_cb,
547 .get_event_loop = afb_systemd_get_event_loop,
548 .get_user_bus = afb_systemd_get_user_bus,
549 .get_system_bus = afb_systemd_get_system_bus,
550 .rootdir_get_fd = afb_common_rootdir_get_fd,
551 .rootdir_open_locale = rootdir_open_locale_cb,
552 .queue_job = queue_job_cb,
553 .unstore_req = legacy_unstore_req_cb,
554 .require_api = require_api_cb,
555 .add_alias = add_alias_cb,
556 .new_api = api_new_api_cb,
559 static const struct afb_daemon_itf_x1 hooked_daemon_itf = {
560 .vverbose_v1 = legacy_hooked_vverbose_v1_cb,
561 .vverbose_v2 = hooked_vverbose_cb,
562 .event_make = legacy_hooked_event_x1_make_cb,
563 .event_broadcast = hooked_event_broadcast_cb,
564 .get_event_loop = hooked_get_event_loop,
565 .get_user_bus = hooked_get_user_bus,
566 .get_system_bus = hooked_get_system_bus,
567 .rootdir_get_fd = hooked_rootdir_get_fd,
568 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
569 .queue_job = hooked_queue_job_cb,
570 .unstore_req = legacy_hooked_unstore_req_cb,
571 .require_api = hooked_require_api_cb,
572 .add_alias = hooked_add_alias_cb,
573 .new_api = hooked_api_new_api_cb,
576 /******************************************************************************
577 ******************************************************************************
578 ******************************************************************************
579 ******************************************************************************
581 ******************************************************************************
582 ******************************************************************************
583 ******************************************************************************
584 ******************************************************************************/
586 /* the common session for services sharing their session */
587 static struct afb_session *common_session;
589 /******************************************************************************
590 ******************************************************************************
591 ******************************************************************************
592 ******************************************************************************
594 ******************************************************************************
595 ******************************************************************************
596 ******************************************************************************
597 ******************************************************************************/
600 struct afb_api_x3 *apix3,
603 struct json_object *args,
604 void (*callback)(void*, struct json_object*, const char *error, const char *info, struct afb_api_x3*),
607 struct afb_export *export = from_api_x3(apix3);
608 return afb_calls_call(export, api, verb, args, callback, closure);
611 static int call_sync_x3(
612 struct afb_api_x3 *apix3,
615 struct json_object *args,
616 struct json_object **object,
620 struct afb_export *export = from_api_x3(apix3);
621 return afb_calls_call_sync(export, api, verb, args, object, error, info);
624 static void legacy_call_v12(
625 struct afb_api_x3 *apix3,
628 struct json_object *args,
629 void (*callback)(void*, int, struct json_object*),
632 struct afb_export *export = from_api_x3(apix3);
633 afb_calls_legacy_call_v12(export, api, verb, args, callback, closure);
636 static void legacy_call_x3(
637 struct afb_api_x3 *apix3,
640 struct json_object *args,
641 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
644 struct afb_export *export = from_api_x3(apix3);
645 afb_calls_legacy_call_v3(export, api, verb, args, callback, closure);
648 static int legacy_call_sync(
649 struct afb_api_x3 *apix3,
652 struct json_object *args,
653 struct json_object **result)
655 struct afb_export *export = from_api_x3(apix3);
656 return afb_calls_legacy_call_sync(export, api, verb, args, result);
659 static void hooked_call_x3(
660 struct afb_api_x3 *apix3,
663 struct json_object *args,
664 void (*callback)(void*, struct json_object*, const char*, const char*, struct afb_api_x3*),
667 struct afb_export *export = from_api_x3(apix3);
668 afb_calls_hooked_call(export, api, verb, args, callback, closure);
671 static int hooked_call_sync_x3(
672 struct afb_api_x3 *apix3,
675 struct json_object *args,
676 struct json_object **object,
680 struct afb_export *export = from_api_x3(apix3);
681 return afb_calls_hooked_call_sync(export, api, verb, args, object, error, info);
684 static void legacy_hooked_call_v12(
685 struct afb_api_x3 *apix3,
688 struct json_object *args,
689 void (*callback)(void*, int, struct json_object*),
692 struct afb_export *export = from_api_x3(apix3);
693 afb_calls_legacy_hooked_call_v12(export, api, verb, args, callback, closure);
696 static void legacy_hooked_call_x3(
697 struct afb_api_x3 *apix3,
700 struct json_object *args,
701 void (*callback)(void*, int, struct json_object*, struct afb_api_x3*),
704 struct afb_export *export = from_api_x3(apix3);
705 afb_calls_legacy_hooked_call_v3(export, api, verb, args, callback, closure);
708 static int legacy_hooked_call_sync(
709 struct afb_api_x3 *apix3,
712 struct json_object *args,
713 struct json_object **result)
715 struct afb_export *export = from_api_x3(apix3);
716 return afb_calls_legacy_hooked_call_sync(export, api, verb, args, result);
719 /* the interface for services */
720 static const struct afb_service_itf_x1 service_itf = {
721 .call = legacy_call_v12,
722 .call_sync = legacy_call_sync
725 /* the interface for services */
726 static const struct afb_service_itf_x1 hooked_service_itf = {
727 .call = legacy_hooked_call_v12,
728 .call_sync = legacy_hooked_call_sync
731 /******************************************************************************
732 ******************************************************************************
733 ******************************************************************************
734 ******************************************************************************
736 ******************************************************************************
737 ******************************************************************************
738 ******************************************************************************
739 ******************************************************************************/
741 static int api_set_verbs_v2_cb(
742 struct afb_api_x3 *api,
743 const struct afb_verb_v2 *verbs)
745 struct afb_export *export = from_api_x3(api);
747 if (export->unsealed) {
748 afb_api_v3_set_verbs_v2(export->desc.v3, verbs);
756 static int api_set_verbs_v3_cb(
757 struct afb_api_x3 *api,
758 const struct afb_verb_v3 *verbs)
760 struct afb_export *export = from_api_x3(api);
762 if (!export->unsealed) {
767 afb_api_v3_set_verbs_v3(export->desc.v3, verbs);
771 static int api_add_verb_cb(
772 struct afb_api_x3 *api,
775 void (*callback)(struct afb_req_x2 *req),
777 const struct afb_auth *auth,
781 struct afb_export *export = from_api_x3(api);
783 if (!export->unsealed) {
788 return afb_api_v3_add_verb(export->desc.v3, verb, info, callback, vcbdata, auth, (uint16_t)session, glob);
791 static int api_del_verb_cb(
792 struct afb_api_x3 *api,
796 struct afb_export *export = from_api_x3(api);
798 if (!export->unsealed) {
803 return afb_api_v3_del_verb(export->desc.v3, verb, vcbdata);
806 static int api_set_on_event_cb(
807 struct afb_api_x3 *api,
808 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
810 struct afb_export *export = from_api_x3(api);
811 return afb_export_handle_events_v3(export, onevent);
814 static int api_set_on_init_cb(
815 struct afb_api_x3 *api,
816 int (*oninit)(struct afb_api_x3 *api))
818 struct afb_export *export = from_api_x3(api);
820 return afb_export_handle_init_v3(export, oninit);
823 static void api_seal_cb(
824 struct afb_api_x3 *api)
826 struct afb_export *export = from_api_x3(api);
828 export->unsealed = 0;
831 static int event_handler_add_cb(
832 struct afb_api_x3 *api,
834 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
837 struct afb_export *export = from_api_x3(api);
839 return afb_export_event_handler_add(export, pattern, callback, closure);
842 static int event_handler_del_cb(
843 struct afb_api_x3 *api,
847 struct afb_export *export = from_api_x3(api);
849 return afb_export_event_handler_del(export, pattern, closure);
852 static int class_provide_cb(struct afb_api_x3 *api, const char *name)
854 struct afb_export *export = from_api_x3(api);
857 char *iter, *end, save;
859 iter = strdupa(name);
865 if (!save) /* at end? */
868 /* search for the end */
870 while (save && !isspace(save))
874 rc2 = afb_apiset_provide_class(export->declare_set, api->apiname, iter);
883 static int class_require_cb(struct afb_api_x3 *api, const char *name)
885 struct afb_export *export = from_api_x3(api);
888 char *iter, *end, save;
890 iter = strdupa(name);
896 if (!save) /* at end? */
899 /* search for the end */
901 while (save && !isspace(save))
905 rc2 = afb_apiset_require_class(export->declare_set, api->apiname, iter);
914 static int delete_api_cb(struct afb_api_x3 *api)
916 struct afb_export *export = from_api_x3(api);
918 if (!export->unsealed) {
923 afb_export_undeclare(export);
924 afb_export_unref(export);
928 static struct json_object *settings_cb(struct afb_api_x3 *api)
930 struct afb_export *export = from_api_x3(api);
931 struct json_object *result = export->settings;
933 result = make_settings(export);
937 static int hooked_api_set_verbs_v2_cb(
938 struct afb_api_x3 *api,
939 const struct afb_verb_v2 *verbs)
941 struct afb_export *export = from_api_x3(api);
942 int result = api_set_verbs_v2_cb(api, verbs);
943 return afb_hook_api_api_set_verbs_v2(export, result, verbs);
946 static int hooked_api_set_verbs_v3_cb(
947 struct afb_api_x3 *api,
948 const struct afb_verb_v3 *verbs)
950 struct afb_export *export = from_api_x3(api);
951 int result = api_set_verbs_v3_cb(api, verbs);
952 return afb_hook_api_api_set_verbs_v3(export, result, verbs);
955 static int hooked_api_add_verb_cb(
956 struct afb_api_x3 *api,
959 void (*callback)(struct afb_req_x2 *req),
961 const struct afb_auth *auth,
965 struct afb_export *export = from_api_x3(api);
966 int result = api_add_verb_cb(api, verb, info, callback, vcbdata, auth, session, glob);
967 return afb_hook_api_api_add_verb(export, result, verb, info, glob);
970 static int hooked_api_del_verb_cb(
971 struct afb_api_x3 *api,
975 struct afb_export *export = from_api_x3(api);
976 int result = api_del_verb_cb(api, verb, vcbdata);
977 return afb_hook_api_api_del_verb(export, result, verb);
980 static int hooked_api_set_on_event_cb(
981 struct afb_api_x3 *api,
982 void (*onevent)(struct afb_api_x3 *api, const char *event, struct json_object *object))
984 struct afb_export *export = from_api_x3(api);
985 int result = api_set_on_event_cb(api, onevent);
986 return afb_hook_api_api_set_on_event(export, result);
989 static int hooked_api_set_on_init_cb(
990 struct afb_api_x3 *api,
991 int (*oninit)(struct afb_api_x3 *api))
993 struct afb_export *export = from_api_x3(api);
994 int result = api_set_on_init_cb(api, oninit);
995 return afb_hook_api_api_set_on_init(export, result);
998 static void hooked_api_seal_cb(
999 struct afb_api_x3 *api)
1001 struct afb_export *export = from_api_x3(api);
1002 afb_hook_api_api_seal(export);
1006 static int hooked_event_handler_add_cb(
1007 struct afb_api_x3 *api,
1008 const char *pattern,
1009 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1012 struct afb_export *export = from_api_x3(api);
1013 int result = event_handler_add_cb(api, pattern, callback, closure);
1014 return afb_hook_api_event_handler_add(export, result, pattern);
1017 static int hooked_event_handler_del_cb(
1018 struct afb_api_x3 *api,
1019 const char *pattern,
1022 struct afb_export *export = from_api_x3(api);
1023 int result = event_handler_del_cb(api, pattern, closure);
1024 return afb_hook_api_event_handler_del(export, result, pattern);
1027 static int hooked_class_provide_cb(struct afb_api_x3 *api, const char *name)
1029 struct afb_export *export = from_api_x3(api);
1030 int result = class_provide_cb(api, name);
1031 return afb_hook_api_class_provide(export, result, name);
1034 static int hooked_class_require_cb(struct afb_api_x3 *api, const char *name)
1036 struct afb_export *export = from_api_x3(api);
1037 int result = class_require_cb(api, name);
1038 return afb_hook_api_class_require(export, result, name);
1041 static int hooked_delete_api_cb(struct afb_api_x3 *api)
1043 struct afb_export *export = afb_export_addref(from_api_x3(api));
1044 int result = delete_api_cb(api);
1045 result = afb_hook_api_delete_api(export, result);
1046 afb_export_unref(export);
1050 static struct json_object *hooked_settings_cb(struct afb_api_x3 *api)
1052 struct afb_export *export = from_api_x3(api);
1053 struct json_object *result = settings_cb(api);
1054 result = afb_hook_api_settings(export, result);
1058 static const struct afb_api_x3_itf api_x3_itf = {
1060 .vverbose = (void*)vverbose_cb,
1062 .get_event_loop = afb_systemd_get_event_loop,
1063 .get_user_bus = afb_systemd_get_user_bus,
1064 .get_system_bus = afb_systemd_get_system_bus,
1065 .rootdir_get_fd = afb_common_rootdir_get_fd,
1066 .rootdir_open_locale = rootdir_open_locale_cb,
1067 .queue_job = queue_job_cb,
1069 .require_api = require_api_cb,
1070 .add_alias = add_alias_cb,
1072 .event_broadcast = event_broadcast_cb,
1073 .event_make = event_x2_make_cb,
1075 .legacy_call = legacy_call_x3,
1076 .legacy_call_sync = legacy_call_sync,
1078 .api_new_api = api_new_api_cb,
1079 .api_set_verbs_v2 = api_set_verbs_v2_cb,
1080 .api_add_verb = api_add_verb_cb,
1081 .api_del_verb = api_del_verb_cb,
1082 .api_set_on_event = api_set_on_event_cb,
1083 .api_set_on_init = api_set_on_init_cb,
1084 .api_seal = api_seal_cb,
1085 .api_set_verbs_v3 = api_set_verbs_v3_cb,
1086 .event_handler_add = event_handler_add_cb,
1087 .event_handler_del = event_handler_del_cb,
1090 .call_sync = call_sync_x3,
1092 .class_provide = class_provide_cb,
1093 .class_require = class_require_cb,
1095 .delete_api = delete_api_cb,
1096 .settings = settings_cb,
1099 static const struct afb_api_x3_itf hooked_api_x3_itf = {
1101 .vverbose = hooked_vverbose_cb,
1103 .get_event_loop = hooked_get_event_loop,
1104 .get_user_bus = hooked_get_user_bus,
1105 .get_system_bus = hooked_get_system_bus,
1106 .rootdir_get_fd = hooked_rootdir_get_fd,
1107 .rootdir_open_locale = hooked_rootdir_open_locale_cb,
1108 .queue_job = hooked_queue_job_cb,
1110 .require_api = hooked_require_api_cb,
1111 .add_alias = hooked_add_alias_cb,
1113 .event_broadcast = hooked_event_broadcast_cb,
1114 .event_make = hooked_event_x2_make_cb,
1116 .legacy_call = legacy_hooked_call_x3,
1117 .legacy_call_sync = legacy_hooked_call_sync,
1119 .api_new_api = hooked_api_new_api_cb,
1120 .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
1121 .api_add_verb = hooked_api_add_verb_cb,
1122 .api_del_verb = hooked_api_del_verb_cb,
1123 .api_set_on_event = hooked_api_set_on_event_cb,
1124 .api_set_on_init = hooked_api_set_on_init_cb,
1125 .api_seal = hooked_api_seal_cb,
1126 .api_set_verbs_v3 = hooked_api_set_verbs_v3_cb,
1127 .event_handler_add = hooked_event_handler_add_cb,
1128 .event_handler_del = hooked_event_handler_del_cb,
1130 .call = hooked_call_x3,
1131 .call_sync = hooked_call_sync_x3,
1133 .class_provide = hooked_class_provide_cb,
1134 .class_require = hooked_class_require_cb,
1136 .delete_api = hooked_delete_api_cb,
1137 .settings = hooked_settings_cb,
1140 /******************************************************************************
1141 ******************************************************************************
1142 ******************************************************************************
1143 ******************************************************************************
1145 ******************************************************************************
1146 ******************************************************************************
1147 ******************************************************************************
1148 ******************************************************************************/
1151 * Propagates the event to the service
1153 static void listener_of_events(void *closure, const char *event, int eventid, struct json_object *object)
1155 struct event_handler *handler;
1156 struct afb_export *export = from_api_x3(closure);
1158 /* hook the event before */
1159 if (export->hooksvc & afb_hook_flag_api_on_event)
1160 afb_hook_api_on_event_before(export, event, eventid, object);
1162 /* transmit to specific handlers */
1163 /* search the handler */
1164 handler = export->event_handlers;
1166 if (fnmatch(handler->pattern, event, 0)) {
1167 if (!(export->hooksvc & afb_hook_flag_api_on_event_handler))
1168 handler->callback(handler->closure, event, object, to_api_x3(export));
1170 afb_hook_api_on_event_handler_before(export, event, eventid, object, handler->pattern);
1171 handler->callback(handler->closure, event, object, to_api_x3(export));
1172 afb_hook_api_on_event_handler_after(export, event, eventid, object, handler->pattern);
1175 handler = handler->next;
1178 /* transmit to default handler */
1179 if (export->on_any_event_v3)
1180 export->on_any_event_v3(to_api_x3(export), event, object);
1181 else if (export->on_any_event_v12)
1182 export->on_any_event_v12(event, object);
1184 /* hook the event after */
1185 if (export->hooksvc & afb_hook_flag_api_on_event)
1186 afb_hook_api_on_event_after(export, event, eventid, object);
1187 json_object_put(object);
1190 /* the interface for events */
1191 static const struct afb_evt_itf evt_itf = {
1192 .broadcast = listener_of_events,
1193 .push = listener_of_events
1196 /* ensure an existing listener */
1197 static int ensure_listener(struct afb_export *export)
1199 if (!export->listener) {
1200 export->listener = afb_evt_listener_create(&evt_itf, export);
1201 if (export->listener == NULL)
1207 int afb_export_event_handler_add(
1208 struct afb_export *export,
1209 const char *pattern,
1210 void (*callback)(void *, const char*, struct json_object*, struct afb_api_x3*),
1214 struct event_handler *handler, **previous;
1216 rc = ensure_listener(export);
1220 /* search the handler */
1221 previous = &export->event_handlers;
1222 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1223 previous = &handler->next;
1225 /* error if found */
1227 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1232 /* create the event */
1233 handler = malloc(strlen(pattern) + sizeof * handler);
1235 ERROR("[API %s] can't allocate event handler %s", export->api.apiname, pattern);
1240 /* init and record */
1241 handler->next = NULL;
1242 handler->callback = callback;
1243 handler->closure = closure;
1244 strcpy(handler->pattern, pattern);
1245 *previous = handler;
1250 int afb_export_event_handler_del(
1251 struct afb_export *export,
1252 const char *pattern,
1255 struct event_handler *handler, **previous;
1257 /* search the handler */
1258 previous = &export->event_handlers;
1259 while ((handler = *previous) && strcasecmp(handler->pattern, pattern))
1260 previous = &handler->next;
1262 /* error if found */
1264 ERROR("[API %s] event handler %s already exists", export->api.apiname, pattern);
1269 /* remove the found event */
1271 *closure = handler->closure;
1273 *previous = handler->next;
1278 /******************************************************************************
1279 ******************************************************************************
1280 ******************************************************************************
1281 ******************************************************************************
1283 ******************************************************************************
1284 ******************************************************************************
1285 ******************************************************************************
1286 ******************************************************************************/
1288 static struct afb_export *create(
1289 struct afb_apiset *declare_set,
1290 struct afb_apiset *call_set,
1291 const char *apiname,
1293 enum afb_api_version version)
1295 struct afb_export *export;
1298 /* session shared with other exports */
1299 if (common_session == NULL) {
1300 common_session = afb_session_create (0);
1301 if (common_session == NULL)
1304 lenapi = strlen(apiname);
1305 export = calloc(1, sizeof *export + lenapi + (path == apiname || !path ? 0 : strlen(path)));
1309 export->refcount = 1;
1310 strcpy(export->name, apiname);
1311 export->api.apiname = export->name;
1312 if (path == apiname)
1313 export->path = export->name;
1315 export->path = strcpy(&export->name[lenapi + 1], path);
1316 export->version = version;
1317 export->state = Api_State_Pre_Init;
1318 export->session = afb_session_addref(common_session);
1319 export->declare_set = afb_apiset_addref(declare_set);
1320 export->call_set = afb_apiset_addref(call_set);
1325 struct afb_export *afb_export_addref(struct afb_export *export)
1328 __atomic_add_fetch(&export->refcount, 1, __ATOMIC_RELAXED);
1332 void afb_export_unref(struct afb_export *export)
1334 if (export && !__atomic_sub_fetch(&export->refcount, 1, __ATOMIC_RELAXED))
1335 afb_export_destroy(export);
1338 void afb_export_destroy(struct afb_export *export)
1340 struct event_handler *handler;
1343 while ((handler = export->event_handlers)) {
1344 export->event_handlers = handler->next;
1347 if (export->listener != NULL)
1348 afb_evt_listener_unref(export->listener);
1349 afb_session_unref(export->session);
1350 afb_apiset_unref(export->declare_set);
1351 afb_apiset_unref(export->call_set);
1352 json_object_put(export->settings);
1353 afb_export_unref(export->creator);
1354 if (export->api.apiname != export->name)
1355 free((void*)export->api.apiname);
1360 struct afb_export *afb_export_create_none_for_path(
1361 struct afb_apiset *declare_set,
1362 struct afb_apiset *call_set,
1364 int (*creator)(void*, struct afb_api_x3*),
1367 struct afb_export *export = create(declare_set, call_set, path, path, Api_Version_None);
1369 afb_export_logmask_set(export, logmask);
1370 afb_export_update_hooks(export);
1371 if (creator && creator(closure, to_api_x3(export)) < 0) {
1372 afb_export_unref(export);
1379 #if defined(WITH_LEGACY_BINDING_V1)
1380 struct afb_export *afb_export_create_v1(struct afb_apiset *declare_set,
1381 struct afb_apiset *call_set,
1382 const char *apiname,
1383 int (*init)(struct afb_service_x1),
1384 void (*onevent)(const char*, struct json_object*),
1387 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_1);
1389 export->init.v1 = init;
1390 export->on_any_event_v12 = onevent;
1391 export->export.v1.mode = AFB_MODE_LOCAL;
1392 export->export.v1.daemon.closure = to_api_x3(export);
1393 afb_export_logmask_set(export, logmask);
1394 afb_export_update_hooks(export);
1400 struct afb_export *afb_export_create_v2(struct afb_apiset *declare_set,
1401 struct afb_apiset *call_set,
1402 const char *apiname,
1403 const struct afb_binding_v2 *binding,
1404 struct afb_binding_data_v2 *data,
1406 void (*onevent)(const char*, struct json_object*),
1409 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_2);
1411 export->init.v2 = init;
1412 export->on_any_event_v12 = onevent;
1413 export->desc.v2 = binding;
1414 export->export.v2 = data;
1415 data->daemon.closure = to_api_x3(export);
1416 data->service.closure = to_api_x3(export);
1417 afb_export_logmask_set(export, logmask);
1418 afb_export_update_hooks(export);
1423 struct afb_export *afb_export_create_v3(struct afb_apiset *declare_set,
1424 struct afb_apiset *call_set,
1425 const char *apiname,
1426 struct afb_api_v3 *apiv3,
1427 struct afb_export* creator,
1430 struct afb_export *export = create(declare_set, call_set, apiname, path, Api_Version_3);
1432 export->unsealed = 1;
1433 export->desc.v3 = apiv3;
1434 export->creator = afb_export_addref(creator);
1435 afb_export_logmask_set(export, logmask);
1436 afb_export_update_hooks(export);
1441 int afb_export_add_alias(struct afb_export *export, const char *apiname, const char *aliasname)
1443 return afb_apiset_add_alias(export->declare_set, apiname ?: export->api.apiname, aliasname);
1446 int afb_export_rename(struct afb_export *export, const char *apiname)
1450 if (export->declared) {
1455 /* copy the name locally */
1456 name = strdup(apiname);
1462 if (export->api.apiname != export->name)
1463 free((void*)export->api.apiname);
1464 export->api.apiname = name;
1466 afb_export_update_hooks(export);
1470 const char *afb_export_apiname(const struct afb_export *export)
1472 return export->api.apiname;
1475 void afb_export_update_hooks(struct afb_export *export)
1477 export->hookditf = afb_hook_flags_api(export->api.apiname);
1478 export->hooksvc = afb_hook_flags_api(export->api.apiname);
1479 export->api.itf = export->hookditf|export->hooksvc ? &hooked_api_x3_itf : &api_x3_itf;
1481 switch (export->version) {
1482 #if defined(WITH_LEGACY_BINDING_V1)
1484 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1488 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1489 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1494 int afb_export_unshare_session(struct afb_export *export)
1496 if (export->session == common_session) {
1497 export->session = afb_session_create (0);
1498 if (export->session)
1499 afb_session_unref(common_session);
1501 export->session = common_session;
1508 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1511 switch (export->version) {
1512 #if defined(WITH_LEGACY_BINDING_V1)
1518 ERROR("invalid version 12 for API %s", export->api.apiname);
1523 export->on_any_event_v12 = on_event;
1524 return ensure_listener(export);
1527 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))
1530 switch (export->version) {
1531 case Api_Version_3: break;
1533 ERROR("invalid version Dyn for API %s", export->api.apiname);
1538 export->on_any_event_v3 = on_event;
1539 return ensure_listener(export);
1542 int afb_export_handle_init_v3(struct afb_export *export, int (*oninit)(struct afb_api_x3 *api))
1544 if (export->state != Api_State_Pre_Init) {
1545 ERROR("[API %s] Bad call to 'afb_api_x3_on_init', must be in PreInit", export->api.apiname);
1550 export->init.v3 = oninit;
1554 #if defined(WITH_LEGACY_BINDING_V1)
1556 * Starts a new service (v1)
1558 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1560 return export->desc.v1 = regfun(&export->export.v1);
1564 int afb_export_preinit_x3(
1565 struct afb_export *export,
1566 int (*preinit)(void*, struct afb_api_x3*),
1569 return preinit(closure, to_api_x3(export));
1572 int afb_export_logmask_get(const struct afb_export *export)
1574 return export->api.logmask;
1577 void afb_export_logmask_set(struct afb_export *export, int mask)
1579 export->api.logmask = mask;
1580 switch (export->version) {
1581 #if defined(WITH_LEGACY_BINDING_V1)
1582 case Api_Version_1: export->export.v1.verbosity = verbosity_from_mask(mask); break;
1584 case Api_Version_2: export->export.v2->verbosity = verbosity_from_mask(mask); break;
1588 void *afb_export_userdata_get(const struct afb_export *export)
1590 return export->api.userdata;
1593 void afb_export_userdata_set(struct afb_export *export, void *data)
1595 export->api.userdata = data;
1598 /******************************************************************************
1599 ******************************************************************************
1600 ******************************************************************************
1601 ******************************************************************************
1603 ******************************************************************************
1604 ******************************************************************************
1605 ******************************************************************************
1606 ******************************************************************************/
1611 struct afb_export *export;
1614 static void do_init(int sig, void *closure)
1617 struct init *init = closure;
1618 struct afb_export *export;
1623 export = init->export;
1624 switch (export->version) {
1625 #if defined(WITH_LEGACY_BINDING_V1)
1627 rc = export->init.v1 ? export->init.v1(
1628 (struct afb_service_x1){
1629 .itf = &hooked_service_itf,
1630 .closure = to_api_x3(export) }) : 0;
1634 rc = export->init.v2 ? export->init.v2() : 0;
1637 rc = export->init.v3 ? export->init.v3(to_api_x3(export)) : 0;
1644 init->return_code = rc;
1648 int afb_export_start(struct afb_export *export)
1654 switch (export->state) {
1658 case Api_State_Init:
1659 /* starting in progress: it is an error */
1660 ERROR("Service of API %s required started while starting", export->api.apiname);
1667 /* set event handling */
1668 switch (export->version) {
1669 #if defined(WITH_LEGACY_BINDING_V1)
1673 if (export->on_any_event_v12) {
1674 rc = afb_export_handle_events_v12(export, export->on_any_event_v12);
1683 ERROR("Can't set event handler for %s", export->api.apiname);
1687 /* Starts the service */
1688 if (export->hooksvc & afb_hook_flag_api_start)
1689 afb_hook_api_start_before(export);
1691 export->state = Api_State_Init;
1692 init.export = export;
1693 sig_monitor(0, do_init, &init);
1694 rc = init.return_code;
1695 export->state = Api_State_Run;
1697 if (export->hooksvc & afb_hook_flag_api_start)
1698 afb_hook_api_start_after(export, rc);
1701 /* initialisation error */
1702 ERROR("Initialisation of service API %s failed (%d): %m", export->api.apiname, rc);
1709 static void api_call_cb(void *closure, struct afb_xreq *xreq)
1711 struct afb_export *export = closure;
1713 xreq->request.api = to_api_x3(export);
1715 switch (export->version) {
1716 #if defined(WITH_LEGACY_BINDING_V1)
1718 afb_api_so_v1_process_call(export->desc.v1, xreq);
1722 afb_api_so_v2_process_call(export->desc.v2, xreq);
1725 afb_api_v3_process_call(export->desc.v3, xreq);
1728 afb_xreq_reply(xreq, NULL, "bad-api-type", NULL);
1733 static struct json_object *api_describe_cb(void *closure)
1735 struct afb_export *export = closure;
1736 struct json_object *result;
1738 switch (export->version) {
1739 #if defined(WITH_LEGACY_BINDING_V1)
1741 result = afb_api_so_v1_make_description_openAPIv3(export->desc.v1, export->api.apiname);
1745 result = afb_api_so_v2_make_description_openAPIv3(export->desc.v2, export->api.apiname);
1748 result = afb_api_v3_make_description_openAPIv3(export->desc.v3, export->api.apiname);
1757 static int api_service_start_cb(void *closure)
1759 struct afb_export *export = closure;
1761 return afb_export_start(export);
1764 static void api_update_hooks_cb(void *closure)
1766 struct afb_export *export = closure;
1768 afb_export_update_hooks(export);
1771 static int api_get_logmask_cb(void *closure)
1773 struct afb_export *export = closure;
1775 return afb_export_logmask_get(export);
1778 static void api_set_logmask_cb(void *closure, int level)
1780 struct afb_export *export = closure;
1782 afb_export_logmask_set(export, level);
1785 static void api_unref_cb(void *closure)
1787 struct afb_export *export = closure;
1789 afb_export_unref(export);
1792 static struct afb_api_itf export_api_itf =
1794 .call = api_call_cb,
1795 .service_start = api_service_start_cb,
1796 .update_hooks = api_update_hooks_cb,
1797 .get_logmask = api_get_logmask_cb,
1798 .set_logmask = api_set_logmask_cb,
1799 .describe = api_describe_cb,
1800 .unref = api_unref_cb
1803 int afb_export_declare(struct afb_export *export,
1807 struct afb_api_item afb_api;
1809 if (export->declared)
1812 /* init the record structure */
1813 afb_api.closure = afb_export_addref(export);
1814 afb_api.itf = &export_api_itf;
1815 afb_api.group = noconcurrency ? export : NULL;
1817 /* records the binding */
1818 rc = afb_apiset_add(export->declare_set, export->api.apiname, afb_api);
1820 export->declared = 1;
1822 ERROR("can't declare export %s to set %s, ABORTING it!",
1823 export->api.apiname,
1824 afb_apiset_name(export->declare_set));
1825 afb_export_unref(export);
1832 void afb_export_undeclare(struct afb_export *export)
1834 if (export->declared) {
1835 export->declared = 0;
1836 afb_apiset_del(export->declare_set, export->api.apiname);
1840 int afb_export_subscribe(struct afb_export *export, struct afb_event_x2 *event)
1842 return afb_evt_event_x2_add_watch(export->listener, event);
1845 int afb_export_unsubscribe(struct afb_export *export, struct afb_event_x2 *event)
1847 return afb_evt_event_x2_remove_watch(export->listener, event);
1850 void afb_export_process_xreq(struct afb_export *export, struct afb_xreq *xreq)
1852 afb_xreq_process(xreq, export->call_set);
1855 void afb_export_context_init(struct afb_export *export, struct afb_context *context)
1857 afb_context_init(context, export->session, NULL);
1858 context->validated = 1;