/* Authors: Pavel Březina Copyright (C) 2017 Red Hat This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _SBUS_H_ #define _SBUS_H_ #include #include #include #include #include "util/util.h" #include "sbus/sbus_typeof.h" #include "sbus/sbus_declarations.h" #include "sbus/sbus_interface.h" #include "sbus/sbus_request.h" #include "sbus/sbus_errors.h" struct sbus_listener; struct sbus_connection; struct sbus_server; struct sbus_node; /** * Connect to D-Bus system bus, naming this end-point @dbus_name. * * If @last_activity_time pointer is given, it is updated with current time * each time an important event (such as method or property call) on the bus * occurs. It is not updated when an signal arrives. * * @param mem_ctx Memory context. * @param ev Tevent context. * @param dbus_name Name of this end-point. * @param last_activity_time Pointer to a time that is updated each time * an event occurs. * * @return New sbus connection or NULL on error. */ struct sbus_connection * sbus_connect_system(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *dbus_name, time_t *last_activity_time); /** * Connect to a private D-Bus bus at @address. * * If @last_activity_time pointer is given, it is updated with current time * each time an important event (such as method or property call) on the bus * occurs. It is not updated when an signal arrives. * * @param mem_ctx Memory context. * @param ev Tevent context. * @param address Remote end-point address. * @param dbus_name Name of this end-point. * @param last_activity_time Pointer to a time that is updated each time * an event occurs. * * @return New sbus connection or NULL on error. * * @see sbus_server_create */ struct sbus_connection * sbus_connect_private(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *address, const char *dbus_name, time_t *last_activity_time); /** * Connect to a private D-Bus bus at @address an perform its initialization * asynchronously. Usually, you can just call @sbus_connect_private which * will block for a while during Hello and RequestName calls, which is mostly * ok since it is done during process initialization. However, you have to * use asynchronous call if you are connecting to a server which runs on the * same process, otherwise it will end up in dead lock. * * If @last_activity_time pointer is given, it is updated with current time * each time an important event (such as method or property call) on the bus * occurs. It is not updated when an signal arrives. * * @param mem_ctx Memory context. * @param ev Tevent context. * @param address Remote end-point address. * @param dbus_name Name of this end-point. * @param last_activity_time Pointer to a time that is updated each time * an event occurs. * * @return Tevent request or NULL on error. * * @see sbus_server_create */ struct tevent_req * sbus_connect_private_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *address, const char *dbus_name, time_t *last_activity_time); /** * Recieve reply from @sbus_connect_private_send. * * @param mem_ctx Memory context. * @param req Tevent request. * @param _conn Established sbus connection. * * @return EOK on success, other errno code on failure. * * @see sbus_server_create */ errno_t sbus_connect_private_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, struct sbus_connection **_conn); /** * Create a new sbus server at socket address @address. * * @param mem_ctx Memory context. * @param ev Tevent context. * @param address Socket address. * @param use_symlink If a symlink to @address should be created. * @param uid Socket owner uid. * @param gid Socket owner gid. * @param on_conn_cb On new connection callback function. * @param on_conn_data Private data passed to the callback. * * @return New sbus server or NULL on error. */ struct sbus_server * sbus_server_create(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *address, bool use_symlink, uint32_t max_connections, uid_t uid, gid_t gid, sbus_server_on_connection_cb on_conn_cb, sbus_server_on_connection_data on_conn_data); /** * Create a new sbus server at socket address @address and connect to it. * * @param mem_ctx Memory context. * @param ev Tevent context. * @param dbus_name Name of the connection. * @param last_activity_time Pointer to a time that is updated each time * an event occurs on connection. * @param address Socket address. * @param use_symlink If a symlink to @address should be created. * @param uid Socket owner uid. * @param gid Socket owner gid. * @param on_conn_cb On new connection callback function. * @param on_conn_data Private data passed to the callback. * * @return Tevent request or NULL on error. */ struct tevent_req * sbus_server_create_and_connect_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *dbus_name, time_t *last_activity_time, const char *address, bool use_symlink, uint32_t max_connections, uid_t uid, gid_t gid, sbus_server_on_connection_cb on_conn_cb, sbus_server_on_connection_data on_conn_data); /** * Receive reply from @sbus_server_create_and_connect_send. * * @param mem_ctx Memory context. * @param req Tevent request. * @param _server Created sbus server. * @param _conn Established sbus connection. * * @return EOK on success, other errno code on failure. * * @see sbus_server_create_and_connect_send */ errno_t sbus_server_create_and_connect_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, struct sbus_server **_server, struct sbus_connection **_conn); /** * Find active sbus connection by its name. * * @param server An sbus server. * @param name Connection unique or well-known name. * * @return The sbus connection associated with name or NULL if not found. */ struct sbus_connection * sbus_server_find_connection(struct sbus_server *server, const char *name); /** * Set server callback that is run everytime a new connection is established * with the server. * * Callback is of type: * errno_t callback(struct sbus_connection *conn, * data_type *data) * * where @conn is the newly established sbus connection. If other error code * than EOK is returned by the callback, the connection is killed. * * @param server An sbus server. * @param callback Callback function. * @param data Private data passed to the callback. */ #define sbus_server_set_on_connection(server, callback, data) do { \ SBUS_CHECK_FUNCTION(callback, errno_t, \ struct sbus_connection *, \ SBUS_TYPEOF(data)); \ _sbus_server_set_on_connection((server), #callback, \ (sbus_server_on_connection_cb)callback, \ (sbus_server_on_connection_data)data); \ } while(0) /** * Set custom destructor on an sbus connection. * * This destructor is called when a connection is being freed after it * is finalized. It is not allowed to use further manipulate with this * connection within the destructor. * * Destructor is of type: * void my_destructor(data_type *data) * * @param conn An sbus connection. * @param destructor Destructor function. * @param data Private data passed to the destructor. */ #define sbus_connection_set_destructor(conn, destructor, data) do { \ SBUS_CHECK_FUNCTION(destructor, void, SBUS_TYPEOF(data)); \ _sbus_connection_set_destructor((conn), #destructor, \ (sbus_connection_destructor_fn)destructor, \ (sbus_connection_destructor_data)data); \ } while(0) /** * Set custom access check function on an sbus connection. * * This function is called on each incoming sbus request to check whether * the caller has enough permissions to run such request. * * Access check function is of type: * errno_t my_access_check(struct sbus_request *sbus_request, data_type *data) * * The function shall return EOK if access is granted, EPERM if access is * denied and other errno code on error. * * @param conn An sbus connection. * @param check_fn Access check function. * @param data Private data passed to the access check function. */ #define sbus_connection_set_access_check(conn, check_fn, data) do { \ SBUS_CHECK_FUNCTION(check_fn, errno_t, \ struct sbus_request *, \ SBUS_TYPEOF(data)); \ _sbus_connection_set_access_check((conn), #check_fn, \ (sbus_connection_access_check_fn)check_fn, \ (sbus_connection_access_check_data)data); \ } while(0) /** * Set connection private data. * * @param conn An sbus connection. * @param data Private data. */ void sbus_connection_set_data(struct sbus_connection *conn, void *data); /** * Retrieve connection private data. * * @param conn An sbus connection. * @param type Private data type. */ #define sbus_connection_get_data(conn, type) \ talloc_get_type(_sbus_connection_get_data(conn), type) /** * Reconnection status that is pass to a reconnection callback. */ enum sbus_reconnect_status { /** * Reconnection was successful. */ SBUS_RECONNECT_SUCCESS, /** * Reconnection failed because maximum number of retires was exceeded. */ SBUS_RECONNECT_EXCEEDED_RETRIES, /** * Reconnection failed due to unspecified error. */ SBUS_RECONNECT_ERROR }; /** * Enable automatic reconnection when an sbus connection is dropped. * * You can also set a callback that is called upon successful or * unsuccessful reconnection. * * Callback is of type: * void callback(struct sbus_connection *conn, * enum sbus_reconnect_status status, * data_type *data) * * @param conn An sbus connection. * @param max_retries Maximum number of reconnection retries. * @param callback Callback function. * @param data Private data passed to the callback. */ #define sbus_reconnect_enable(conn, max_retries, callback, data) do { \ SBUS_CHECK_FUNCTION(callback, void, \ struct sbus_connection *, \ enum sbus_reconnect_status, \ SBUS_TYPEOF(data)); \ _sbus_reconnect_enable((conn), max_retries, \ (sbus_reconnect_cb)callback, (sbus_reconnect_data)data); \ } while(0) /** * Associate an object path with an sbus interface. The object @path may also * contain an asterisk at the end to indicate that the interface should be * applied for the path subtree. */ struct sbus_path { const char *path; struct sbus_interface *iface; }; /** * Add new object or subtree path to the connection router. * * The specified interface will be associated with this path. You can add * single path multiple times if you want this path to have more interfaces * associated. * * @param conn An sbus connection. * @param path Object or subtree path. * @param iface An sbus interface. * * @return EOK or other error code on failure. */ errno_t sbus_connection_add_path(struct sbus_connection *conn, const char *path, struct sbus_interface *iface); /** * Associate multiple object paths with interfaces at once. * * The paths and interfaces are associated through @map which is * NULL terminated array of @sbus_router_path. * * @param conn An sbus connection. * @param map pairs to add into router. * * @return EOK or other error code on failure. */ errno_t sbus_connection_add_path_map(struct sbus_connection *conn, struct sbus_path *map); /** * Add new signal listener to the router. * * Create a new listener with @SBUS_LISTEN_SYNC or @SBUS_LISTEN_ASYNC. * * @param conn An sbus connection. * @param listener An sbus signal listerner. * * @return EOK or other error code on failure. * * @see SBUS_LISTENERS, SBUS_LISTEN_SYNC, SBUS_LISTEN_ASYNC */ errno_t sbus_router_listen(struct sbus_connection *conn, struct sbus_listener *listener); /** * Add multiple signal listeners to the router at once. * * @param conn An sbus connection. * @param listener An sbus signal listener array. * * @return EOK or other error code on failure. * * @see SBUS_LISTENERS, SBUS_LISTEN_SYNC, SBUS_LISTEN_ASYNC */ errno_t sbus_router_listen_map(struct sbus_connection *conn, struct sbus_listener *map); /** * Register new node with the router. * * Each node is associated with a node factory which is a function that * returns list of node object names for given object path. * * Create a new node with @SBUS_NODE_SYNC or @SBUS_NODE_ASYNC. * * @param conn An sbus connection. * @param node An sbus node description. * * @return EOK or other error code on failure * * @see SBUS_NODES, SBUS_NODE_SYNC, SBUS_NODE_ASYNC */ errno_t sbus_router_add_node(struct sbus_connection *conn, struct sbus_node *node); /** * Register multiple nodes with the router at once. Each node is associated * with a node factory which is a function that returns list of node object * names or given object path. * * @param conn An sbus connection. * @param node An sbus node description array. * * @return EOK or other error code on failure. * * @see SBUS_NODES, SBUS_NODE_SYNC, SBUS_NODE_ASYNC */ errno_t sbus_router_add_node_map(struct sbus_connection *conn, struct sbus_node *map); /* Get connection name, well known name is preferred. */ const char * sbus_connection_get_name(struct sbus_connection *conn); #endif /* _SBUS_H_ */