From 4be084408c6d3d7b7f90a2493829c8ce0cebb397 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Thu, 4 May 2017 16:21:18 +0200 Subject: [PATCH] Prepare bindings version 2 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Change-Id: Ic9e417d9a36f5da08883c3ded127d8350ff893cc Signed-off-by: José Bollo --- include/afb/afb-binding-v1.h | 93 +++++++++++---------- include/afb/afb-binding-v2.h | 38 +++++++-- include/afb/afb-binding.h | 191 ++++++------------------------------------- include/afb/afb-daemon-itf.h | 152 ++++++++++++++++++++++++++++++++++ include/afb/afb-session.h | 65 +++++++++++++++ src/afb-api-so-v1.c | 7 +- src/afb-api-so-v2.c | 32 +++++--- src/afb-api-so-v2.h | 2 +- src/afb-api-so.c | 1 - src/afb-config.c | 2 +- src/afb-ditf.c | 26 ++++-- src/afb-ditf.h | 13 +-- src/afb-monitor.c | 5 +- src/afb-svc.c | 144 ++++++++++++++++++++------------ src/afb-svc.h | 14 ++-- src/afb-xreq.c | 2 +- src/afb-xreq.h | 2 +- src/main.c | 2 +- 18 files changed, 479 insertions(+), 312 deletions(-) create mode 100644 include/afb/afb-daemon-itf.h create mode 100644 include/afb/afb-session.h diff --git a/include/afb/afb-binding-v1.h b/include/afb/afb-binding-v1.h index 6281dd8a..dc7af6f5 100644 --- a/include/afb/afb-binding-v1.h +++ b/include/afb/afb-binding-v1.h @@ -17,9 +17,10 @@ #pragma once -struct afb_binding_interface; struct json_object; struct afb_service; +struct afb_binding_v1; +struct afb_binding_interface_v1; /* * Function for registering the binding @@ -44,7 +45,7 @@ struct afb_service; * the function 'afbBindingV1ServiceInit' is called, the 'interface' * is fully functionnal. */ -extern const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *interface); +extern const struct afb_binding_v1 *afbBindingV1Register (const struct afb_binding_interface_v1 *interface); /* * When a binding have an exported implementation of the @@ -71,47 +72,6 @@ extern int afbBindingV1ServiceInit(struct afb_service service); extern void afbBindingV1ServiceEvent(const char *event, struct json_object *object); -/* - * Enum for Session/Token/Assurance middleware. - * This enumeration is valid for bindings of type 1 - */ -enum afb_session_v1 -{ - AFB_SESSION_NONE = 0, /* nothing required */ - AFB_SESSION_CREATE = 1, /* Obsolete */ - AFB_SESSION_CLOSE = 2, /* After token authentification, closes the session at end */ - AFB_SESSION_RENEW = 4, /* After token authentification, refreshes the token at end */ - AFB_SESSION_CHECK = 8, /* Requires token authentification */ - - AFB_SESSION_LOA_GE = 16, /* check that the LOA is greater or equal to the given value */ - AFB_SESSION_LOA_LE = 32, /* check that the LOA is lesser or equal to the given value */ - AFB_SESSION_LOA_EQ = 48, /* check that the LOA is equal to the given value */ - - AFB_SESSION_LOA_SHIFT = 6, /* shift for LOA */ - AFB_SESSION_LOA_MASK = 7, /* mask for LOA */ - - AFB_SESSION_LOA_0 = 0, /* value for LOA of 0 */ - AFB_SESSION_LOA_1 = 64, /* value for LOA of 1 */ - AFB_SESSION_LOA_2 = 128, /* value for LOA of 2 */ - AFB_SESSION_LOA_3 = 192, /* value for LOA of 3 */ - AFB_SESSION_LOA_4 = 256, /* value for LOA of 4 */ - - AFB_SESSION_LOA_LE_0 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_0, /* check LOA <= 0 */ - AFB_SESSION_LOA_LE_1 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_1, /* check LOA <= 1 */ - AFB_SESSION_LOA_LE_2 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_2, /* check LOA <= 2 */ - AFB_SESSION_LOA_LE_3 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_3, /* check LOA <= 3 */ - - AFB_SESSION_LOA_GE_0 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_0, /* check LOA >= 0 */ - AFB_SESSION_LOA_GE_1 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_1, /* check LOA >= 1 */ - AFB_SESSION_LOA_GE_2 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_2, /* check LOA >= 2 */ - AFB_SESSION_LOA_GE_3 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_3, /* check LOA >= 3 */ - - AFB_SESSION_LOA_EQ_0 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_0, /* check LOA == 0 */ - AFB_SESSION_LOA_EQ_1 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_1, /* check LOA == 1 */ - AFB_SESSION_LOA_EQ_2 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_2, /* check LOA == 2 */ - AFB_SESSION_LOA_EQ_3 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_3 /* check LOA == 3 */ -}; - /* * Description of one verb of the API provided by the binding * This enumeration is valid for bindings of type version 1 @@ -119,7 +79,7 @@ enum afb_session_v1 struct afb_verb_desc_v1 { const char *name; /* name of the verb */ - enum afb_session_v1 session; /* authorisation and session requirements of the verb */ + enum afb_session_flags session; /* authorisation and session requirements of the verb */ void (*callback)(struct afb_req req); /* callback function implementing the verb */ const char *info; /* textual description of the verb */ }; @@ -138,7 +98,7 @@ struct afb_binding_desc_v1 * Definition of the type+versions of the binding. * The definition uses hashes. */ -enum afb_binding_type +enum afb_binding_type_v1 { AFB_BINDING_VERSION_1 = 123456789 }; @@ -146,11 +106,50 @@ enum afb_binding_type /* * Description of a binding */ -struct afb_binding +struct afb_binding_v1 { - enum afb_binding_type type; /* type of the binding */ + enum afb_binding_type_v1 type; /* type of the binding */ union { struct afb_binding_desc_v1 v1; /* description of the binding of type 1 */ }; }; +/* + * config mode + */ +enum afb_mode_v1 { + AFB_MODE_LOCAL = 0, /* run locally */ + AFB_MODE_REMOTE, /* run remotely */ + AFB_MODE_GLOBAL /* run either remotely or locally (DONT USE! reserved for future) */ +}; + +/* + * Interface between the daemon and the binding. + */ +struct afb_binding_interface_v1 +{ + struct afb_daemon daemon; /* access to the daemon facilies */ + int verbosity; /* level of verbosity */ + enum afb_mode_v1 mode; /* run mode (local or remote) */ +}; + +/* + * Macros for logging messages + */ +#if !defined(AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO) +# if !defined(AFB_BINDING_PRAGMA_NO_VERBOSE_DETAILS) +# define AFB_ERROR_V1(itf,...) do{if(itf->verbosity>=0)afb_daemon_verbose(itf->daemon,3,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# define AFB_WARNING_V1(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,4,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# define AFB_NOTICE_V1(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,5,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# define AFB_INFO_V1(itf,...) do{if(itf->verbosity>=2)afb_daemon_verbose(itf->daemon,6,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# define AFB_DEBUG_V1(itf,...) do{if(itf->verbosity>=3)afb_daemon_verbose(itf->daemon,7,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# else +# define AFB_ERROR_V1(itf,...) do{if(itf->verbosity>=0)afb_daemon_verbose(itf->daemon,3,NULL,0,__VA_ARGS__);}while(0) +# define AFB_WARNING_V1(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,4,NULL,0,__VA_ARGS__);}while(0) +# define AFB_NOTICE_V1(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,5,NULL,0,__VA_ARGS__);}while(0) +# define AFB_INFO_V1(itf,...) do{if(itf->verbosity>=2)afb_daemon_verbose(itf->daemon,6,NULL,0,__VA_ARGS__);}while(0) +# define AFB_DEBUG_V1(itf,...) do{if(itf->verbosity>=3)afb_daemon_verbose(itf->daemon,7,NULL,0,__VA_ARGS__);}while(0) +# endif +#endif + + diff --git a/include/afb/afb-binding-v2.h b/include/afb/afb-binding-v2.h index 97956411..17adb02e 100644 --- a/include/afb/afb-binding-v2.h +++ b/include/afb/afb-binding-v2.h @@ -17,17 +17,23 @@ #pragma once -struct afb_binding_interface; +#include + struct afb_service; +struct afb_daemon; +struct afb_binding_v2; + struct json_object; /* - * A binding V2 MUST have an exported symbol of name + * A binding V2 MUST have two exported symbols of name: * - * afbBindingV2 + * - afbBindingV2 + * - afbBindingV2verbosity * */ extern const struct afb_binding_v2 afbBindingV2; +extern int afbBindingV2verbosity; /* * Description of one verb of the API provided by the binding @@ -38,7 +44,7 @@ struct afb_verb_v2 const char *verb; /* name of the verb */ void (*callback)(struct afb_req req); /* callback function implementing the verb */ const char * permissions; /* required permissions */ - enum afb_session_v1 session; /* authorisation and session requirements of the verb */ + uint32_t session; /* authorisation and session requirements of the verb */ }; /* @@ -49,8 +55,26 @@ struct afb_binding_v2 const char *api; /* api name for the binding */ const char *specification; /* textual specification of the binding */ const struct afb_verb_v2 *verbs; /* array of descriptions of verbs terminated by a NULL name */ - int (*init)(const struct afb_binding_interface *interface); - int (*start)(const struct afb_binding_interface *interface, struct afb_service service); - void (*onevent)(const char *event, struct json_object *object); + int (*init)(struct afb_daemon daemon); + int (*start)(struct afb_service service); + void (*onevent)(struct afb_service service, const char *event, struct json_object *object); }; +/* + * Macros for logging messages + */ +#if !defined(AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO) +# if !defined(AFB_BINDING_PRAGMA_NO_VERBOSE_DETAILS) +# define AFB_ERROR_V2(daemon,...) do{if(afbBindingV2verbosity>=0)afb_daemon_verbose(daemon,3,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# define AFB_WARNING_V2(daemon,...) do{if(afbBindingV2verbosity>=1)afb_daemon_verbose(daemon,4,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# define AFB_NOTICE_V2(daemon,...) do{if(afbBindingV2verbosity>=1)afb_daemon_verbose(daemon,5,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# define AFB_INFO_V2(daemon,...) do{if(afbBindingV2verbosity>=2)afb_daemon_verbose(daemon,6,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# define AFB_DEBUG_V2(daemon,...) do{if(afbBindingV2verbosity>=3)afb_daemon_verbose(daemon,7,__FILE__,__LINE__,__VA_ARGS__);}while(0) +# else +# define AFB_ERROR_V2(daemon,...) do{if(afbBindingV2verbosity>=0)afb_daemon_verbose(daemon,3,NULL,0,__VA_ARGS__);}while(0) +# define AFB_WARNING_V2(daemon,...) do{if(afbBindingV2verbosity>=1)afb_daemon_verbose(daemon,4,NULL,0,__VA_ARGS__);}while(0) +# define AFB_NOTICE_V2(daemon,...) do{if(afbBindingV2verbosity>=1)afb_daemon_verbose(daemon,5,NULL,0,__VA_ARGS__);}while(0) +# define AFB_INFO_V2(daemon,...) do{if(afbBindingV2verbosity>=2)afb_daemon_verbose(daemon,6,NULL,0,__VA_ARGS__);}while(0) +# define AFB_DEBUG_V2(daemon,...) do{if(afbBindingV2verbosity>=3)afb_daemon_verbose(daemon,7,NULL,0,__VA_ARGS__);}while(0) +# endif +#endif diff --git a/include/afb/afb-binding.h b/include/afb/afb-binding.h index 9c845153..cea1b552 100644 --- a/include/afb/afb-binding.h +++ b/include/afb/afb-binding.h @@ -32,182 +32,41 @@ * */ +#define AFB_BINDING_PRAGMA_KEEP_OBSOLETE_V1 +#define AFB_BINDING_PRAGMA_KEEP_OBSOLETE_V2 +#define AFB_BINDING_PRAGMA_DECLARE_V1 +#define AFB_BINDING_PRAGMA_DECLARE_V2 + +#define AFB_BINDING_LOWER_VERSION 1 +#define AFB_BINDING_UPPER_VERSION 2 +#define AFB_BINDING_DEFAULT_VERSION 1 + +#ifndef AFB_BINDING_CURRENT_VERSION +#define AFB_BINDING_CURRENT_VERSION AFB_BINDING_DEFAULT_VERSION +#endif + /* * Some function of the library are exported to afb-daemon. */ +#include "afb-session.h" #include "afb-event-itf.h" #include "afb-req-itf.h" #include "afb-service-itf.h" +#include "afb-daemon-itf.h" #include "afb-binding-v1.h" #include "afb-binding-v2.h" -/* - * config mode - */ -enum afb_mode { - AFB_MODE_LOCAL = 0, /* run locally */ - AFB_MODE_REMOTE, /* run remotely */ - AFB_MODE_GLOBAL /* run either remotely or locally (DONT USE! reserved for future) */ -}; - -/* declaration of features of libsystemd */ -struct sd_event; -struct sd_bus; - -/* - * Definition of the facilities provided by the daemon. - */ -struct afb_daemon_itf { - int (*event_broadcast)(void *closure, const char *name, struct json_object *object); /* broadcasts evant 'name' with 'object' */ - struct sd_event *(*get_event_loop)(void *closure); /* gets the common systemd's event loop */ - struct sd_bus *(*get_user_bus)(void *closure); /* gets the common systemd's user d-bus */ - struct sd_bus *(*get_system_bus)(void *closure); /* gets the common systemd's system d-bus */ - void (*vverbose)(void*closure, int level, const char *file, int line, const char *fmt, va_list args); - struct afb_event (*event_make)(void *closure, const char *name); /* creates an event of 'name' */ - int (*rootdir_get_fd)(void *closure); - int (*rootdir_open_locale)(void *closure, const char *filename, int flags, const char *locale); - int (*queue_job)(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout); -}; - -/* - * Structure for accessing daemon. - * See also: afb_daemon_get_event_sender, afb_daemon_get_event_loop, afb_daemon_get_user_bus, afb_daemon_get_system_bus - */ -struct afb_daemon { - const struct afb_daemon_itf *itf; /* the interfacing functions */ - void *closure; /* the closure when calling these functions */ -}; - -/* - * Interface between the daemon and the binding. - */ -struct afb_binding_interface -{ - struct afb_daemon daemon; /* access to the daemon facilies */ - int verbosity; /* level of verbosity */ - enum afb_mode mode; /* run mode (local or remote) */ -}; - -/* - * Retrieves the common systemd's event loop of AFB - * 'daemon' MUST be the daemon given in interface when activating the binding. - */ -static inline struct sd_event *afb_daemon_get_event_loop(struct afb_daemon daemon) -{ - return daemon.itf->get_event_loop(daemon.closure); -} - -/* - * Retrieves the common systemd's user/session d-bus of AFB - * 'daemon' MUST be the daemon given in interface when activating the binding. - */ -static inline struct sd_bus *afb_daemon_get_user_bus(struct afb_daemon daemon) -{ - return daemon.itf->get_user_bus(daemon.closure); -} - -/* - * Retrieves the common systemd's system d-bus of AFB - * 'daemon' MUST be the daemon given in interface when activating the binding. - */ -static inline struct sd_bus *afb_daemon_get_system_bus(struct afb_daemon daemon) -{ - return daemon.itf->get_system_bus(daemon.closure); -} - -/* - * Broadcasts widely the event of 'name' with the data 'object'. - * 'object' can be NULL. - * 'daemon' MUST be the daemon given in interface when activating the binding. - * - * For convenience, the function calls 'json_object_put' for 'object'. - * Thus, in the case where 'object' should remain available after - * the function returns, the function 'json_object_get' shall be used. - * - * Returns the count of clients that received the event. - */ -static inline int afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object) -{ - return daemon.itf->event_broadcast(daemon.closure, name, object); -} - -/* - * Creates an event of 'name' and returns it. - * 'daemon' MUST be the daemon given in interface when activating the binding. - */ -static inline struct afb_event afb_daemon_make_event(struct afb_daemon daemon, const char *name) -{ - return daemon.itf->event_make(daemon.closure, name); -} - -/* - * Send a message described by 'fmt' and following parameters - * to the journal for the verbosity 'level'. - * 'file' and 'line' are indicators of position of the code in source files. - * 'daemon' MUST be the daemon given in interface when activating the binding. - */ -static inline void afb_daemon_verbose(struct afb_daemon daemon, int level, const char *file, int line, const char *fmt, ...) __attribute__((format(printf, 5, 6))); -static inline void afb_daemon_verbose(struct afb_daemon daemon, int level, const char *file, int line, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - daemon.itf->vverbose(daemon.closure, level, file, line, fmt, args); - va_end(args); -} - -/* - * Macros for logging messages - */ -#if !defined(NO_BINDING_VERBOSE_MACRO) -# if !defined(NO_BINDING_FILE_LINE_INDICATION) -# define ERROR(itf,...) do{if(itf->verbosity>=0)afb_daemon_verbose(itf->daemon,3,__FILE__,__LINE__,__VA_ARGS__);}while(0) -# define WARNING(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,4,__FILE__,__LINE__,__VA_ARGS__);}while(0) -# define NOTICE(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,5,__FILE__,__LINE__,__VA_ARGS__);}while(0) -# define INFO(itf,...) do{if(itf->verbosity>=2)afb_daemon_verbose(itf->daemon,6,__FILE__,__LINE__,__VA_ARGS__);}while(0) -# define DEBUG(itf,...) do{if(itf->verbosity>=3)afb_daemon_verbose(itf->daemon,7,__FILE__,__LINE__,__VA_ARGS__);}while(0) -# else -# define ERROR(itf,...) do{if(itf->verbosity>=0)afb_daemon_verbose(itf->daemon,3,NULL,0,__VA_ARGS__);}while(0) -# define WARNING(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,4,NULL,0,__VA_ARGS__);}while(0) -# define NOTICE(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,5,NULL,0,__VA_ARGS__);}while(0) -# define INFO(itf,...) do{if(itf->verbosity>=2)afb_daemon_verbose(itf->daemon,6,NULL,0,__VA_ARGS__);}while(0) -# define DEBUG(itf,...) do{if(itf->verbosity>=3)afb_daemon_verbose(itf->daemon,7,NULL,0,__VA_ARGS__);}while(0) -# endif +#if AFB_BINDING_CURRENT_VERSION == 1 +#define afb_binding afb_binding_v1 +#define afb_binding_interface afb_binding_interface_v1 +#if !defined(AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO) +#define ERROR AFB_ERROR_V1 +#define WARNING AFB_WARNING_V1 +#define NOTICE AFB_NOTICE_V1 +#define INFO AFB_INFO_V1 +#define DEBUG AFB_DEBUG_V1 +#endif #endif -/* - * Get the root directory file descriptor. This file descriptor can - * be used with functions 'openat', 'fstatat', ... - */ -static inline int afb_daemon_rootdir_get_fd(struct afb_daemon daemon) -{ - return daemon.itf->rootdir_get_fd(daemon.closure); -} - -/* - * Opens 'filename' within the root directory with 'flags' (see function openat) - * using the 'locale' definition (example: "jp,en-US") that can be NULL. - * Returns the file descriptor or -1 in case of error. - */ -static inline int afb_daemon_rootdir_open_locale(struct afb_daemon daemon, const char *filename, int flags, const char *locale) -{ - return daemon.itf->rootdir_open_locale(daemon.closure, filename, flags, locale); -} -/* - * Queue the job defined by 'callback' and 'argument' for being executed asynchronously - * in this thread (later) or in an other thread. - * If 'group' is not NUL, the jobs queued with a same value (as the pointer value 'group') - * are executed in sequence in the order of there submission. - * If 'timeout' is not 0, it represent the maximum execution time for the job in seconds. - * At first, the job is called with 0 as signum and the given argument. - * The job is executed with the monitoring of its time and some signals like SIGSEGV and - * SIGFPE. When a such signal is catched, the job is terminated and reexecuted but with - * signum being the signal number (SIGALRM when timeout expired). - * - * Returns 0 in case of success or -1 in case of error. - */ -static inline int afb_daemon_queue_job(struct afb_daemon daemon, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout) -{ - return daemon.itf->queue_job(daemon.closure, callback, argument, group, timeout); -} diff --git a/include/afb/afb-daemon-itf.h b/include/afb/afb-daemon-itf.h new file mode 100644 index 00000000..88ce27c9 --- /dev/null +++ b/include/afb/afb-daemon-itf.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2016, 2017 "IoT.bzh" + * Author: José Bollo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +/* declaration of features of libsystemd */ +struct sd_event; +struct sd_bus; + +/* + * Definition of the facilities provided by the daemon. + */ +struct afb_daemon_itf { + int (*event_broadcast)(void *closure, const char *name, struct json_object *object); /* broadcasts evant 'name' with 'object' */ + struct sd_event *(*get_event_loop)(void *closure); /* gets the common systemd's event loop */ + struct sd_bus *(*get_user_bus)(void *closure); /* gets the common systemd's user d-bus */ + struct sd_bus *(*get_system_bus)(void *closure); /* gets the common systemd's system d-bus */ + void (*vverbose)(void*closure, int level, const char *file, int line, const char *fmt, va_list args); + struct afb_event (*event_make)(void *closure, const char *name); /* creates an event of 'name' */ + int (*rootdir_get_fd)(void *closure); + int (*rootdir_open_locale)(void *closure, const char *filename, int flags, const char *locale); + int (*queue_job)(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout); +}; + +/* + * Structure for accessing daemon. + * See also: afb_daemon_get_event_sender, afb_daemon_get_event_loop, afb_daemon_get_user_bus, afb_daemon_get_system_bus + */ +struct afb_daemon { + const struct afb_daemon_itf *itf; /* the interfacing functions */ + void *closure; /* the closure when calling these functions */ +}; + +/* + * Retrieves the common systemd's event loop of AFB + * 'daemon' MUST be the daemon given in interface when activating the binding. + */ +static inline struct sd_event *afb_daemon_get_event_loop(struct afb_daemon daemon) +{ + return daemon.itf->get_event_loop(daemon.closure); +} + +/* + * Retrieves the common systemd's user/session d-bus of AFB + * 'daemon' MUST be the daemon given in interface when activating the binding. + */ +static inline struct sd_bus *afb_daemon_get_user_bus(struct afb_daemon daemon) +{ + return daemon.itf->get_user_bus(daemon.closure); +} + +/* + * Retrieves the common systemd's system d-bus of AFB + * 'daemon' MUST be the daemon given in interface when activating the binding. + */ +static inline struct sd_bus *afb_daemon_get_system_bus(struct afb_daemon daemon) +{ + return daemon.itf->get_system_bus(daemon.closure); +} + +/* + * Broadcasts widely the event of 'name' with the data 'object'. + * 'object' can be NULL. + * 'daemon' MUST be the daemon given in interface when activating the binding. + * + * For convenience, the function calls 'json_object_put' for 'object'. + * Thus, in the case where 'object' should remain available after + * the function returns, the function 'json_object_get' shall be used. + * + * Returns the count of clients that received the event. + */ +static inline int afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object) +{ + return daemon.itf->event_broadcast(daemon.closure, name, object); +} + +/* + * Creates an event of 'name' and returns it. + * 'daemon' MUST be the daemon given in interface when activating the binding. + */ +static inline struct afb_event afb_daemon_make_event(struct afb_daemon daemon, const char *name) +{ + return daemon.itf->event_make(daemon.closure, name); +} + +/* + * Send a message described by 'fmt' and following parameters + * to the journal for the verbosity 'level'. + * 'file' and 'line' are indicators of position of the code in source files. + * 'daemon' MUST be the daemon given in interface when activating the binding. + */ +static inline void afb_daemon_verbose(struct afb_daemon daemon, int level, const char *file, int line, const char *fmt, ...) __attribute__((format(printf, 5, 6))); +static inline void afb_daemon_verbose(struct afb_daemon daemon, int level, const char *file, int line, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + daemon.itf->vverbose(daemon.closure, level, file, line, fmt, args); + va_end(args); +} + +/* + * Get the root directory file descriptor. This file descriptor can + * be used with functions 'openat', 'fstatat', ... + */ +static inline int afb_daemon_rootdir_get_fd(struct afb_daemon daemon) +{ + return daemon.itf->rootdir_get_fd(daemon.closure); +} + +/* + * Opens 'filename' within the root directory with 'flags' (see function openat) + * using the 'locale' definition (example: "jp,en-US") that can be NULL. + * Returns the file descriptor or -1 in case of error. + */ +static inline int afb_daemon_rootdir_open_locale(struct afb_daemon daemon, const char *filename, int flags, const char *locale) +{ + return daemon.itf->rootdir_open_locale(daemon.closure, filename, flags, locale); +} + +/* + * Queue the job defined by 'callback' and 'argument' for being executed asynchronously + * in this thread (later) or in an other thread. + * If 'group' is not NUL, the jobs queued with a same value (as the pointer value 'group') + * are executed in sequence in the order of there submission. + * If 'timeout' is not 0, it represent the maximum execution time for the job in seconds. + * At first, the job is called with 0 as signum and the given argument. + * The job is executed with the monitoring of its time and some signals like SIGSEGV and + * SIGFPE. When a such signal is catched, the job is terminated and reexecuted but with + * signum being the signal number (SIGALRM when timeout expired). + * + * Returns 0 in case of success or -1 in case of error. + */ +static inline int afb_daemon_queue_job(struct afb_daemon daemon, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout) +{ + return daemon.itf->queue_job(daemon.closure, callback, argument, group, timeout); +} diff --git a/include/afb/afb-session.h b/include/afb/afb-session.h new file mode 100644 index 00000000..fe8edc1a --- /dev/null +++ b/include/afb/afb-session.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2016, 2017 "IoT.bzh" + * Author: José Bollo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +/* + * Enum for Session/Token/Assurance middleware. + */ +enum afb_session_flags +{ + AFB_SESSION_NONE = 0, /* nothing required */ +#if defined(AFB_BINDING_PRAGMA_DECLARE_V1) && defined(AFB_BINDING_PRAGMA_KEEP_OBSOLETE_V1) + AFB_SESSION_CREATE = 1, /* Obsolete */ +#endif + AFB_SESSION_CLOSE = 2, /* After token authentification, closes the session at end */ + AFB_SESSION_RENEW = 4, /* After token authentification, refreshes the token at end */ + AFB_SESSION_CHECK = 8, /* Requires token authentification */ + + AFB_SESSION_LOA_GE = 16, /* check that the LOA is greater or equal to the given value */ +#if defined(AFB_BINDING_PRAGMA_DECLARE_V1) || defined(AFB_BINDING_PRAGMA_KEEP_OBSOLETE_V2) + AFB_SESSION_LOA_LE = 32, /* check that the LOA is lesser or equal to the given value */ + AFB_SESSION_LOA_EQ = 48, /* check that the LOA is equal to the given value */ +#endif + + AFB_SESSION_LOA_SHIFT = 6, /* shift for LOA */ + AFB_SESSION_LOA_MASK = 7, /* mask for LOA */ + + AFB_SESSION_LOA_0 = 0, /* value for LOA of 0 */ + AFB_SESSION_LOA_1 = 64, /* value for LOA of 1 */ + AFB_SESSION_LOA_2 = 128, /* value for LOA of 2 */ + AFB_SESSION_LOA_3 = 192, /* value for LOA of 3 */ + AFB_SESSION_LOA_4 = 256, /* value for LOA of 4 */ + +#if defined(AFB_BINDING_PRAGMA_DECLARE_V1) || defined(AFB_BINDING_PRAGMA_KEEP_OBSOLETE_V2) + AFB_SESSION_LOA_LE_0 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_0, /* check LOA <= 0 */ + AFB_SESSION_LOA_LE_1 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_1, /* check LOA <= 1 */ + AFB_SESSION_LOA_LE_2 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_2, /* check LOA <= 2 */ + AFB_SESSION_LOA_LE_3 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_3, /* check LOA <= 3 */ + + AFB_SESSION_LOA_EQ_0 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_0, /* check LOA == 0 */ + AFB_SESSION_LOA_EQ_1 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_1, /* check LOA == 1 */ + AFB_SESSION_LOA_EQ_2 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_2, /* check LOA == 2 */ + AFB_SESSION_LOA_EQ_3 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_3, /* check LOA == 3 */ +#endif + + AFB_SESSION_LOA_GE_0 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_0, /* check LOA >= 0 */ + AFB_SESSION_LOA_GE_1 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_1, /* check LOA >= 1 */ + AFB_SESSION_LOA_GE_2 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_2, /* check LOA >= 2 */ + AFB_SESSION_LOA_GE_3 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_3 /* check LOA >= 3 */ +}; + diff --git a/src/afb-api-so-v1.c b/src/afb-api-so-v1.c index eedfc010..739d2557 100644 --- a/src/afb-api-so-v1.c +++ b/src/afb-api-so-v1.c @@ -16,7 +16,7 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO +#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include #include @@ -27,6 +27,7 @@ #include #include "afb-api.h" +#include "afb-api-so-v1.h" #include "afb-apiset.h" #include "afb-svc.h" #include "afb-evt.h" @@ -105,7 +106,7 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct /* get the event handler if any */ onevent = dlsym(desc->handle, afb_api_so_v1_service_event); - desc->service = afb_svc_create(apiset, share_session, init, onevent); + desc->service = afb_svc_create_v1(apiset, share_session, init, onevent); if (desc->service == NULL) { /* starting error */ ERROR("Starting service %s failed", desc->binding->v1.prefix); @@ -204,7 +205,7 @@ int afb_api_so_v1_add(const char *path, void *handle, struct afb_apiset *apiset) desc->handle = handle; /* init the interface */ - afb_ditf_init(&desc->ditf, path); + afb_ditf_init_v1(&desc->ditf, path); /* init the binding */ NOTICE("binding [%s] calling registering function %s", path, afb_api_so_v1_register); diff --git a/src/afb-api-so-v2.c b/src/afb-api-so-v2.c index 092fd31a..cc832090 100644 --- a/src/afb-api-so-v2.c +++ b/src/afb-api-so-v2.c @@ -16,7 +16,7 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO +#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include #include @@ -26,6 +26,7 @@ #include #include "afb-api.h" +#include "afb-api-so-v2.h" #include "afb-apiset.h" #include "afb-svc.h" #include "afb-ditf.h" @@ -41,6 +42,7 @@ * names of symbols */ static const char afb_api_so_v2_descriptor[] = "afbBindingV2"; +static const char afb_api_so_v2_verbosity[] = "afbBindingV2verbosity"; /** * structure for memorizing verbs sorted with permissions @@ -55,6 +57,7 @@ struct verb_v2 { */ struct api_so_v2 { const struct afb_binding_v2 *binding; /* descriptor */ + int *verbosity; /* verbosity */ void *handle; /* context of dlopen */ struct afb_svc *service; /* handler for service started */ struct afb_ditf ditf; /* daemon interface */ @@ -94,8 +97,8 @@ static void call_cb(void *closure, struct afb_xreq *xreq) static int service_start_cb(void *closure, int share_session, int onneed, struct afb_apiset *apiset) { - int (*start)(const struct afb_binding_interface *interface, struct afb_service service); - void (*onevent)(const char *event, struct json_object *object); + int (*start)(struct afb_service service); + void (*onevent)(struct afb_service service, const char *event, struct json_object *object); struct api_so_v2 *desc = closure; @@ -124,7 +127,7 @@ static int service_start_cb(void *closure, int share_session, int onneed, struct /* get the event handler if any */ onevent = desc->binding->onevent; - desc->service = afb_svc_create_v2(apiset, share_session, onevent, start, &desc->ditf.interface); + desc->service = afb_svc_create_v2(apiset, share_session, start, onevent, &desc->ditf); if (desc->service == NULL) { /* starting error */ ERROR("Starting service %s failed", desc->binding->api); @@ -143,13 +146,13 @@ static void update_hooks_cb(void *closure) static int get_verbosity_cb(void *closure) { struct api_so_v2 *desc = closure; - return desc->ditf.interface.verbosity; + return *desc->verbosity; } static void set_verbosity_cb(void *closure, int level) { struct api_so_v2 *desc = closure; - desc->ditf.interface.verbosity = level; + *desc->verbosity = level; } static struct json_object *describe_cb(void *closure) @@ -168,7 +171,7 @@ static struct afb_api_itf so_v2_api_itf = { }; -int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle, struct afb_apiset *apiset) +int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle, struct afb_apiset *apiset, int *pver) { int rc; struct api_so_v2 *desc; @@ -193,6 +196,7 @@ int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle goto error; } desc->binding = binding; + desc->verbosity = pver; desc->handle = handle; desc->service = NULL; memset(&desc->ditf, 0, sizeof desc->ditf); @@ -224,12 +228,12 @@ int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle } /* init the interface */ - afb_ditf_init(&desc->ditf, binding->api); + afb_ditf_init_v2(&desc->ditf, binding->api); /* init the binding */ if (binding->init) { INFO("binding %s calling init function", binding->api); - rc = binding->init(&desc->ditf.interface); + rc = binding->init(desc->ditf.daemon); if (rc < 0) { ERROR("binding %s initialisation function failed...", binding->api); goto error2; @@ -259,15 +263,21 @@ error: int afb_api_so_v2_add(const char *path, void *handle, struct afb_apiset *apiset) { const struct afb_binding_v2 *binding; + int *pver; /* retrieves the register function */ binding = dlsym(handle, afb_api_so_v2_descriptor); - if (!binding) + pver = dlsym(handle, afb_api_so_v2_verbosity); + if (!binding && !pver) return 0; INFO("binding [%s] looks like an AFB binding V2", path); /* basic checks */ + if (!binding || !pver) { + ERROR("binding [%s] incomplete symbols...", path); + goto error; + } if (binding->api == NULL || *binding->api == 0) { ERROR("binding [%s] bad api name...", path); goto error; @@ -285,7 +295,7 @@ int afb_api_so_v2_add(const char *path, void *handle, struct afb_apiset *apiset) goto error; } - return afb_api_so_v2_add_binding(binding, handle, apiset); + return afb_api_so_v2_add_binding(binding, handle, apiset, pver); error: return -1; diff --git a/src/afb-api-so-v2.h b/src/afb-api-so-v2.h index 9b169cea..b60ebe66 100644 --- a/src/afb-api-so-v2.h +++ b/src/afb-api-so-v2.h @@ -22,4 +22,4 @@ struct afb_apiset; struct afb_binding_v2; extern int afb_api_so_v2_add(const char *path, void *handle, struct afb_apiset *apiset); -extern int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle, struct afb_apiset *apiset); +extern int afb_api_so_v2_add_binding(const struct afb_binding_v2 *binding, void *handle, struct afb_apiset *apiset, int *verbosity); diff --git a/src/afb-api-so.c b/src/afb-api-so.c index 4b8f070c..b5da60f5 100644 --- a/src/afb-api-so.c +++ b/src/afb-api-so.c @@ -16,7 +16,6 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO #include #include diff --git a/src/afb-config.c b/src/afb-config.c index 0fcb1cb2..80dde93f 100644 --- a/src/afb-config.c +++ b/src/afb-config.c @@ -16,7 +16,7 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO +#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include #include diff --git a/src/afb-ditf.c b/src/afb-ditf.c index fde9e043..e6b6857c 100644 --- a/src/afb-ditf.c +++ b/src/afb-ditf.c @@ -16,7 +16,7 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO +#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include #include @@ -199,8 +199,16 @@ static const struct afb_daemon_itf hooked_daemon_itf = { .queue_job = hooked_queue_job_cb }; -void afb_ditf_init(struct afb_ditf *ditf, const char *prefix) +void afb_ditf_init_v2(struct afb_ditf *ditf, const char *prefix) { + ditf->version = 2; + ditf->daemon.closure = ditf; + afb_ditf_rename(ditf, prefix); +} + +void afb_ditf_init_v1(struct afb_ditf *ditf, const char *prefix) +{ + ditf->version = 1; ditf->interface.verbosity = verbosity; ditf->interface.mode = AFB_MODE_LOCAL; ditf->interface.daemon.closure = ditf; @@ -215,9 +223,15 @@ void afb_ditf_rename(struct afb_ditf *ditf, const char *prefix) void afb_ditf_update_hook(struct afb_ditf *ditf) { - if (afb_hook_flags_ditf(ditf->prefix)) - ditf->interface.daemon.itf = &hooked_daemon_itf; - else - ditf->interface.daemon.itf = &daemon_itf; + int hooked = !!afb_hook_flags_ditf(ditf->prefix); + switch (ditf->version) { + case 1: + ditf->interface.daemon.itf = hooked ? &hooked_daemon_itf : &daemon_itf; + break; + default: + case 2: + ditf->daemon.itf = hooked ? &hooked_daemon_itf : &daemon_itf; + break; + } } diff --git a/src/afb-ditf.h b/src/afb-ditf.h index 3e8d99a7..2af76d28 100644 --- a/src/afb-ditf.h +++ b/src/afb-ditf.h @@ -16,7 +16,7 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO +#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include #include @@ -33,15 +33,18 @@ #include "verbose.h" -struct afb_binding_interface; - struct afb_ditf { - struct afb_binding_interface interface; + int version; const char *prefix; + union { + struct afb_binding_interface_v1 interface; + struct afb_daemon daemon; + }; }; -extern void afb_ditf_init(struct afb_ditf *ditf, const char *prefix); +extern void afb_ditf_init_v1(struct afb_ditf *ditf, const char *prefix); +extern void afb_ditf_init_v2(struct afb_ditf *ditf, const char *prefix); extern void afb_ditf_rename(struct afb_ditf *ditf, const char *prefix); extern void afb_ditf_update_hook(struct afb_ditf *ditf); diff --git a/src/afb-monitor.c b/src/afb-monitor.c index 7f47a1cb..dfaa6791 100644 --- a/src/afb-monitor.c +++ b/src/afb-monitor.c @@ -16,7 +16,7 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO +#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include @@ -36,7 +36,8 @@ extern struct afb_apiset *main_apiset; int afb_monitor_init() { - return afb_api_so_v2_add_binding(&_afb_binding_v2_, NULL, main_apiset); + static int v; + return afb_api_so_v2_add_binding(&_afb_binding_v2_, NULL, main_apiset, &v); } /****************************************************************************** diff --git a/src/afb-svc.c b/src/afb-svc.c index 0ae56b81..57173412 100644 --- a/src/afb-svc.c +++ b/src/afb-svc.c @@ -18,6 +18,7 @@ #define _GNU_SOURCE #include +#include #include @@ -32,6 +33,7 @@ #include "afb-xreq.h" #include "afb-cred.h" #include "afb-apiset.h" +#include "afb-ditf.h" #include "verbose.h" /* @@ -49,7 +51,13 @@ struct afb_svc struct afb_evt_listener *listener; /* on event callback for the service */ - void (*on_event)(const char *event, struct json_object *object); + union { + void (*on_event_v1)(const char *event, struct json_object *object); + void (*on_event_v2)(struct afb_service service, const char *event, struct json_object *object); + }; + + /* the daemon interface */ + struct afb_ditf *ditf; }; /* @@ -65,7 +73,8 @@ struct svc_req }; /* functions for services */ -static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object); +static void svc_on_event_v1(void *closure, const char *event, int eventid, struct json_object *object); +static void svc_on_event_v2(void *closure, const char *event, int eventid, struct json_object *object); static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cbclosure); @@ -75,9 +84,13 @@ static const struct afb_service_itf service_itf = { }; /* the interface for events */ -static const struct afb_evt_itf evt_itf = { - .broadcast = svc_on_event, - .push = svc_on_event +static const struct afb_evt_itf evt_itf_v1 = { + .broadcast = svc_on_event_v1, + .push = svc_on_event_v1 +}; +static const struct afb_evt_itf evt_itf_v2 = { + .broadcast = svc_on_event_v2, + .push = svc_on_event_v2 }; /* functions for requests of services */ @@ -93,21 +106,45 @@ const struct afb_xreq_query_itf afb_svc_xreq_itf = { /* the common session for services sharing their session */ static struct afb_session *common_session; +static inline struct afb_service to_afb_service_v1(struct afb_svc *svc) +{ + return (struct afb_service){ .itf = &service_itf, .closure = svc }; +} + +static inline struct afb_service to_afb_service_v2(struct afb_svc *svc) +{ + return (struct afb_service){ .itf = &service_itf, .closure = svc }; +} + +/* + * Frees a service + */ +static void svc_free(struct afb_svc *svc) +{ + if (svc->listener != NULL) + afb_evt_listener_unref(svc->listener); + if (svc->session) + afb_session_unref(svc->session); + afb_apiset_unref(svc->apiset); + free(svc); +} + /* * Allocates a new service */ static struct afb_svc *afb_svc_alloc( struct afb_apiset *apiset, - int share_session, - void (*on_event)(const char *event, struct json_object *object) + int share_session ) { struct afb_svc *svc; /* allocates the svc handler */ - svc = malloc(sizeof * svc); - if (svc == NULL) - goto error; + svc = calloc(1, sizeof * svc); + if (svc == NULL) { + errno = ENOMEM; + return NULL; + } /* instanciate the apiset */ svc->apiset = afb_apiset_addref(apiset); @@ -118,44 +155,30 @@ static struct afb_svc *afb_svc_alloc( if (common_session == NULL) { common_session = afb_session_create (NULL, 0); if (common_session == NULL) - goto error2; + goto error; } svc->session = afb_session_addref(common_session); } else { /* session dedicated to the svc */ svc->session = afb_session_create (NULL, 0); if (svc->session == NULL) - goto error2; - } - - /* initialises the listener if needed */ - svc->on_event = on_event; - if (on_event == NULL) - svc->listener = NULL; - else { - svc->listener = afb_evt_listener_create(&evt_itf, svc); - if (svc->listener == NULL) - goto error3; + goto error; } return svc; -error3: - afb_session_unref(svc->session); -error2: - afb_apiset_unref(svc->apiset); - free(svc); error: + svc_free(svc); return NULL; } /* * Creates a new service */ -struct afb_svc *afb_svc_create( +struct afb_svc *afb_svc_create_v1( struct afb_apiset *apiset, int share_session, - int (*init)(struct afb_service service), + int (*start)(struct afb_service service), void (*on_event)(const char *event, struct json_object *object) ) { @@ -163,24 +186,27 @@ struct afb_svc *afb_svc_create( struct afb_svc *svc; /* allocates the svc handler */ - svc = afb_svc_alloc(apiset, share_session, on_event); + svc = afb_svc_alloc(apiset, share_session); if (svc == NULL) goto error; + /* initialises the listener if needed */ + if (on_event) { + svc->on_event_v1 = on_event; + svc->listener = afb_evt_listener_create(&evt_itf_v1, svc); + if (svc->listener == NULL) + goto error; + } + /* initialises the svc now */ - rc = init((struct afb_service){ .itf = &service_itf, .closure = svc }); + rc = start(to_afb_service_v1(svc)); if (rc < 0) - goto error2; + goto error; return svc; -error2: - if (svc->listener != NULL) - afb_evt_listener_unref(svc->listener); - afb_session_unref(svc->session); - afb_apiset_unref(svc->apiset); - free(svc); error: + svc_free(svc); return NULL; } @@ -190,43 +216,57 @@ error: struct afb_svc *afb_svc_create_v2( struct afb_apiset *apiset, int share_session, - void (*on_event)(const char *event, struct json_object *object), - int (*start)(const struct afb_binding_interface *interface, struct afb_service service), - const struct afb_binding_interface *interface + int (*start)(struct afb_service service), + void (*on_event)(struct afb_service service, const char *event, struct json_object *object), + struct afb_ditf *ditf ) { int rc; struct afb_svc *svc; /* allocates the svc handler */ - svc = afb_svc_alloc(apiset, share_session, on_event); + svc = afb_svc_alloc(apiset, share_session); if (svc == NULL) goto error; + svc->ditf = ditf; + + /* initialises the listener if needed */ + if (on_event) { + svc->on_event_v2 = on_event; + svc->listener = afb_evt_listener_create(&evt_itf_v2, svc); + if (svc->listener == NULL) + goto error; + } /* initialises the svc now */ - rc = start(interface, (struct afb_service){ .itf = &service_itf, .closure = svc }); + rc = start(to_afb_service_v2(svc)); if (rc < 0) - goto error2; + goto error; return svc; -error2: - if (svc->listener != NULL) - afb_evt_listener_unref(svc->listener); - afb_session_unref(svc->session); - afb_apiset_unref(svc->apiset); - free(svc); error: + svc_free(svc); return NULL; } /* * Propagates the event to the service */ -static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object) +static void svc_on_event_v1(void *closure, const char *event, int eventid, struct json_object *object) +{ + struct afb_svc *svc = closure; + svc->on_event_v1(event, object); + json_object_put(object); +} + +/* + * Propagates the event to the service + */ +static void svc_on_event_v2(void *closure, const char *event, int eventid, struct json_object *object) { struct afb_svc *svc = closure; - svc->on_event(event, object); + svc->on_event_v2(to_afb_service_v2(svc), event, object); json_object_put(object); } diff --git a/src/afb-svc.h b/src/afb-svc.h index 0105624c..62b329df 100644 --- a/src/afb-svc.h +++ b/src/afb-svc.h @@ -20,17 +20,17 @@ struct afb_svc; struct afb_service; struct afb_apiset; -struct afb_binding_interface; +struct afb_ditf; -extern struct afb_svc *afb_svc_create( +extern struct afb_svc *afb_svc_create_v1( struct afb_apiset *apiset, int share_session, - int (*init)(struct afb_service service), - void (*onevent)(const char *event, struct json_object *object)); + int (*start)(struct afb_service service), + void (*on_event)(const char *event, struct json_object *object)); extern struct afb_svc *afb_svc_create_v2( struct afb_apiset *apiset, int share_session, - void (*on_event)(const char *event, struct json_object *object), - int (*start)(const struct afb_binding_interface *interface, struct afb_service service), - const struct afb_binding_interface *interface); + int (*start)(struct afb_service service), + void (*on_event)(struct afb_service service, const char *event, struct json_object *object), + struct afb_ditf *ditf); diff --git a/src/afb-xreq.c b/src/afb-xreq.c index d6cf91fd..0aef608a 100644 --- a/src/afb-xreq.c +++ b/src/afb-xreq.c @@ -16,7 +16,7 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO +#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include #include diff --git a/src/afb-xreq.h b/src/afb-xreq.h index 7327c222..498aed5c 100644 --- a/src/afb-xreq.h +++ b/src/afb-xreq.h @@ -18,7 +18,7 @@ #pragma once -#define NO_BINDING_VERBOSE_MACRO +#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include #include "afb-context.h" #include "afb-evt.h" diff --git a/src/main.c b/src/main.c index 0522e708..35182413 100644 --- a/src/main.c +++ b/src/main.c @@ -17,7 +17,7 @@ */ #define _GNU_SOURCE -#define NO_BINDING_VERBOSE_MACRO +#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include #include -- 2.16.6