diff options
Diffstat (limited to 'server/dbus/sssd_dbus_connection.c')
-rw-r--r-- | server/dbus/sssd_dbus_connection.c | 576 |
1 files changed, 0 insertions, 576 deletions
diff --git a/server/dbus/sssd_dbus_connection.c b/server/dbus/sssd_dbus_connection.c deleted file mode 100644 index 3a169f79..00000000 --- a/server/dbus/sssd_dbus_connection.c +++ /dev/null @@ -1,576 +0,0 @@ -#include <sys/time.h> -#include "events.h" -#include "util/util.h" -#include "dbus/dbus.h" -#include "dbus/sssd_dbus.h" -#include "dbus/sssd_dbus_private.h" - -/* Types */ -struct dbus_ctx_list; - -struct sbus_conn_ctx { - DBusConnection *conn; - struct event_context *ev; - int connection_type; - int disconnect; - struct sbus_method_ctx *method_ctx_list; - sbus_conn_destructor_fn destructor; - void *private; /* Private data for this connection */ -}; - -struct sbus_conn_watch_ctx { - DBusWatch *watch; - int fd; - struct fd_event *fde; - struct sbus_conn_ctx *top; -}; - -struct sbus_conn_timeout_ctx { - DBusTimeout *timeout; - struct timed_event *te; - struct sbus_conn_ctx *top; -}; - -static int _method_list_contains_path(struct sbus_method_ctx *list, struct sbus_method_ctx *method); -static void sbus_unreg_object_paths(struct sbus_conn_ctx *dct_ctx); - -static void sbus_dispatch(struct event_context *ev, - struct timed_event *te, - struct timeval tv, void *data) -{ - struct timed_event *new_event; - struct sbus_conn_ctx *dct_ctx; - DBusConnection *conn; - int ret; - - if (data == NULL) { - return; - } - - dct_ctx = talloc_get_type(data, struct sbus_conn_ctx); - - conn = dct_ctx->conn; - DEBUG(3, ("conn: %lX\n", conn)); - - if((dct_ctx->disconnect) || (!dbus_connection_get_is_connected(conn))) { - DEBUG(0,("Connection is not open for dispatching.\n")); - /* - * Free the connection object. - * This will invoke the destructor for the connection - */ - talloc_free(dct_ctx); - dct_ctx = NULL; - return; - } - - /* Dispatch only once each time through the mainloop to avoid - * starving other features - */ - ret = dbus_connection_get_dispatch_status(conn); - if (ret != DBUS_DISPATCH_COMPLETE) { - DEBUG(2,("Dispatching.\n")); - dbus_connection_dispatch(conn); - } - - /* If other dispatches are waiting, queue up the do_dispatch function - * for the next loop. - */ - ret = dbus_connection_get_dispatch_status(conn); - if (ret != DBUS_DISPATCH_COMPLETE) { - new_event = event_add_timed(ev, dct_ctx, tv, sbus_dispatch, dct_ctx); - if (new_event == NULL) { - DEBUG(0,("Could not add dispatch event!\n")); - - /* TODO: Calling exit here is bad */ - exit(1); - } - } -} - -/* - * dbus_connection_read_write_handler - * Callback for D-BUS to handle messages on a file-descriptor - */ -static void sbus_conn_read_write_handler(struct event_context *ev, - struct fd_event *fde, - uint16_t flags, void *data) -{ - struct sbus_conn_watch_ctx *conn_w_ctx; - conn_w_ctx = talloc_get_type(data, struct sbus_conn_watch_ctx); - - DEBUG(0,("Connection is open for read/write.\n")); - dbus_connection_ref(conn_w_ctx->top->conn); - if (flags & EVENT_FD_READ) { - dbus_watch_handle(conn_w_ctx->watch, DBUS_WATCH_READABLE); - } - if (flags & EVENT_FD_WRITE) { - dbus_watch_handle(conn_w_ctx->watch, DBUS_WATCH_WRITABLE); - } - dbus_connection_unref(conn_w_ctx->top->conn); -} - -/* - * add_connection_watch - * Set up hooks into the libevents mainloop for - * D-BUS to add file descriptor-based events - */ -static dbus_bool_t sbus_add_conn_watch(DBusWatch *watch, void *data) -{ - unsigned int flags; - unsigned int event_flags; - struct sbus_conn_ctx *dt_ctx; - struct sbus_conn_watch_ctx *conn_w_ctx; - - if (!dbus_watch_get_enabled(watch)) { - return TRUE; - } - - dt_ctx = talloc_get_type(data, struct sbus_conn_ctx); - - conn_w_ctx = talloc_zero(dt_ctx, struct sbus_conn_watch_ctx); - conn_w_ctx->top = dt_ctx; - conn_w_ctx->watch = watch; - - flags = dbus_watch_get_flags(watch); - conn_w_ctx->fd = dbus_watch_get_unix_fd(watch); - - event_flags = 0; - - if (flags & DBUS_WATCH_READABLE) - event_flags |= EVENT_FD_READ; - - if (flags & DBUS_WATCH_WRITABLE) - event_flags |= EVENT_FD_WRITE; - - if (event_flags == 0) - return FALSE; - - DEBUG(2,("%lX: %d, %d=%s\n", watch, conn_w_ctx->fd, event_flags, event_flags==EVENT_FD_READ?"READ":"WRITE")); - - /* Add the file descriptor to the event loop */ - conn_w_ctx->fde = event_add_fd(conn_w_ctx->top->ev, conn_w_ctx, - conn_w_ctx->fd, event_flags, - sbus_conn_read_write_handler, - conn_w_ctx); - - /* Save the event to the watch object so it can be removed later */ - dbus_watch_set_data(conn_w_ctx->watch,conn_w_ctx->fde,NULL); - - return TRUE; -} - -/* - * toggle_connection_watch - * Hook for D-BUS to toggle the enabled/disabled state of - * an event in the mainloop - */ -static void sbus_toggle_conn_watch(DBusWatch *watch, void *data) -{ - if (dbus_watch_get_enabled(watch)) { - sbus_add_conn_watch(watch, data); - } else { - sbus_remove_watch(watch, data); - } -} - -/* - * dbus_connection_timeout_handler - * Callback for D-BUS to handle timed events - */ -static void sbus_conn_timeout_handler(struct event_context *ev, - struct timed_event *te, - struct timeval t, void *data) -{ - struct sbus_conn_timeout_ctx *conn_t_ctx; - conn_t_ctx = talloc_get_type(data, struct sbus_conn_timeout_ctx); - - dbus_timeout_handle(conn_t_ctx->timeout); -} - - -/* - * add_connection_timeout - * Hook for D-BUS to add time-based events to the mainloop - */ -static dbus_bool_t sbus_add_conn_timeout(DBusTimeout *timeout, void *data) -{ - struct sbus_conn_ctx *dt_ctx; - struct sbus_conn_timeout_ctx *conn_t_ctx; - struct timeval tv; - - if (!dbus_timeout_get_enabled(timeout)) - return TRUE; - - dt_ctx = talloc_get_type(data, struct sbus_conn_ctx); - - conn_t_ctx = talloc_zero(dt_ctx,struct sbus_conn_timeout_ctx); - conn_t_ctx->top = dt_ctx; - conn_t_ctx->timeout = timeout; - - tv = _dbus_timeout_get_interval_tv(dbus_timeout_get_interval(timeout)); - - struct timeval rightnow; - gettimeofday(&rightnow, NULL); - - conn_t_ctx->te = event_add_timed(conn_t_ctx->top->ev, conn_t_ctx, tv, - sbus_conn_timeout_handler, conn_t_ctx); - - /* Save the event to the watch object so it can be removed later */ - dbus_timeout_set_data(conn_t_ctx->timeout,conn_t_ctx->te,NULL); - - return TRUE; -} - -/* - * sbus_toggle_conn_timeout - * Hook for D-BUS to toggle the enabled/disabled state of a mainloop - * event - */ -void sbus_toggle_conn_timeout(DBusTimeout *timeout, void *data) -{ - if (dbus_timeout_get_enabled(timeout)) { - sbus_add_conn_timeout(timeout, data); - } else { - sbus_remove_timeout(timeout, data); - } -} - -/* dbus_connection_wakeup_main - * D-BUS makes a callback to the wakeup_main function when - * it has data available for dispatching. - * In order to avoid blocking, this function will create a now() - * timed event to perform the dispatch during the next iteration - * through the mainloop - */ -static void sbus_conn_wakeup_main(void *data) { - struct sbus_conn_ctx *dct_ctx; - struct timeval tv; - struct timed_event *te; - - dct_ctx = talloc_get_type(data, struct sbus_conn_ctx); - gettimeofday(&tv, NULL); - - /* D-BUS calls this function when it is time to do a dispatch */ - te = event_add_timed(dct_ctx->ev, dct_ctx, - tv, sbus_dispatch, dct_ctx); - if (te == NULL) { - DEBUG(0,("Could not add dispatch event!\n")); - exit(1); - } -} - -/* - * integrate_connection_with_event_loop - * Set up a D-BUS connection to use the libevents mainloop - * for handling file descriptor and timed events - */ -int sbus_add_connection(TALLOC_CTX *ctx, - struct event_context *ev, - DBusConnection *dbus_conn, - struct sbus_conn_ctx **dct_ctx, - int connection_type) -{ - dbus_bool_t dbret; - struct sbus_conn_ctx *dt_ctx; - - DEBUG(0,("Adding connection %lX\n", dbus_conn)); - dt_ctx = talloc_zero(ctx, struct sbus_conn_ctx); - dt_ctx->ev = ev; - dt_ctx->conn = dbus_conn; - dt_ctx->connection_type = connection_type; - dt_ctx->disconnect = 0; - /* This will be replaced on the first call to sbus_conn_add_method_ctx() */ - dt_ctx->method_ctx_list = NULL; - - /* - * Set the default destructor - * Connections can override this with - * sbus_conn_set_destructor - */ - sbus_conn_set_destructor(dt_ctx, NULL); - - /* Set up DBusWatch functions */ - dbret = dbus_connection_set_watch_functions(dt_ctx->conn, - sbus_add_conn_watch, - sbus_remove_watch, - sbus_toggle_conn_watch, - dt_ctx, NULL); - if (!dbret) { - DEBUG(0,("Error setting up D-BUS connection watch functions\n")); - return EIO; - } - - /* Set up DBusTimeout functions */ - dbret = dbus_connection_set_timeout_functions(dt_ctx->conn, - sbus_add_conn_timeout, - sbus_remove_timeout, - sbus_toggle_conn_timeout, - dt_ctx, NULL); - if (!dbret) { - DEBUG(0,("Error setting up D-BUS server timeout functions\n")); - /* FIXME: free resources ? */ - return EIO; - } - - /* Set up dispatch handler */ - dbus_connection_set_wakeup_main_function(dt_ctx->conn, - sbus_conn_wakeup_main, - dt_ctx, NULL); - - /* Set up any method_contexts passed in */ - - /* Attempt to dispatch immediately in case of opportunistic - * services connecting before the handlers were all up. - * If there are no messages to be dispatched, this will do - * nothing. - */ - sbus_conn_wakeup_main(dt_ctx); - - /* Return the new toplevel object */ - *dct_ctx = dt_ctx; - - return EOK; -} - -/*int sbus_new_connection(struct sbus_method_ctx *ctx, const char *address, - DBusConnection **connection, - sbus_conn_destructor_fn destructor)*/ -int sbus_new_connection(TALLOC_CTX *ctx, struct event_context *ev, const char *address, - struct sbus_conn_ctx **dct_ctx, - sbus_conn_destructor_fn destructor) -{ - DBusConnection *dbus_conn; - DBusError dbus_error; - int ret; - - dbus_error_init(&dbus_error); - - /* Open a shared D-BUS connection to the address */ - dbus_conn = dbus_connection_open(address, &dbus_error); - if (!dbus_conn) { - DEBUG(0, ("Failed to open connection: name=%s, message=%s\n", - dbus_error.name, dbus_error.message)); - return EIO; - } - - ret = sbus_add_connection(ctx, ev, dbus_conn, dct_ctx, SBUS_CONN_TYPE_SHARED); - if (ret != EOK) { - /* FIXME: release resources */ - } - - dbus_connection_set_exit_on_disconnect((*dct_ctx)->conn, FALSE); - - /* Set connection destructor */ - sbus_conn_set_destructor(*dct_ctx, destructor); - - return ret; -} - -/* - * sbus_conn_set_destructor - * Configures a callback to clean up this connection when it - * is finalized. - * @param dct_ctx The sbus_conn_ctx created - * when this connection was established - * @param destructor The destructor function that should be - * called when the connection is finalized. If passed NULL, - * this will reset the connection to the default destructor. - */ -void sbus_conn_set_destructor(struct sbus_conn_ctx *dct_ctx, - sbus_conn_destructor_fn destructor) { - if (!dct_ctx) { - return; - } - - dct_ctx->destructor = destructor; - /* TODO: Should we try to handle the talloc_destructor too? */ -} - -int sbus_default_connection_destructor(void *ctx) { - struct sbus_conn_ctx *dct_ctx; - dct_ctx = talloc_get_type(ctx, struct sbus_conn_ctx); - - DEBUG(3, ("Invoking default destructor on connection %lX\n", dct_ctx->conn)); - if (dct_ctx->connection_type == SBUS_CONN_TYPE_PRIVATE) { - /* Private connections must be closed explicitly */ - dbus_connection_close(dct_ctx->conn); - } else if (dct_ctx->connection_type == SBUS_CONN_TYPE_SHARED) { - /* Shared connections are destroyed when their last reference is removed */ - } - else { - /* Critical Error! */ - DEBUG(0,("Critical Error, connection_type is neither shared nor private!\n")); - return -1; - } - - /* Remove object path */ - /* TODO: Remove object paths */ - - - dbus_connection_unref(dct_ctx->conn); - return 0; -} - -/* - * sbus_get_connection - * Utility function to retreive the DBusConnection object - * from a sbus_conn_ctx - */ -DBusConnection *sbus_get_connection(struct sbus_conn_ctx *dct_ctx) { - return dct_ctx->conn; -} - -void sbus_disconnect (struct sbus_conn_ctx *dct_ctx) { - if (dct_ctx == NULL) { - return; - } - - DEBUG(2,("Disconnecting %lX\n", dct_ctx->conn)); - dbus_connection_ref(dct_ctx->conn); - dct_ctx->disconnect = 1; - - /* Invoke the custom destructor, if it exists */ - if(dct_ctx->destructor) { - dct_ctx->destructor(dct_ctx); - } - - /* Unregister object paths */ - sbus_unreg_object_paths(dct_ctx); - - /* Disable watch functions */ - dbus_connection_set_watch_functions(dct_ctx->conn, - NULL, NULL, NULL, - NULL, NULL); - /* Disable timeout functions */ - dbus_connection_set_timeout_functions(dct_ctx->conn, - NULL, NULL, NULL, - NULL, NULL); - - /* Disable dispatch status function */ - dbus_connection_set_dispatch_status_function(dct_ctx->conn, NULL, NULL, NULL); - - /* Disable wakeup main function */ - dbus_connection_set_wakeup_main_function(dct_ctx->conn, NULL, NULL, NULL); - - /* Finalize the connection */ - sbus_default_connection_destructor(dct_ctx); - dbus_connection_unref(dct_ctx->conn); - DEBUG(2,("Disconnected %lX\n", dct_ctx->conn)); -} - -/* messsage_handler - * Receive messages and process them - */ -static DBusHandlerResult message_handler(DBusConnection *conn, - DBusMessage *message, - void *user_data) -{ - struct sbus_method_ctx *ctx; - const char *method; - const char *path; - const char *msg_interface; - DBusMessage *reply = NULL; - int i, ret; - - ctx = talloc_get_type(user_data, struct sbus_method_ctx); - - method = dbus_message_get_member(message); - path = dbus_message_get_path(message); - msg_interface = dbus_message_get_interface(message); - - if (!method || !path || !msg_interface) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - /* Validate the method interface */ - if (strcmp(msg_interface, ctx->interface) != 0) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - /* Validate the D-BUS path */ - if (strcmp(path, ctx->path) == 0) { - for (i = 0; ctx->methods[i].method != NULL; i++) { - if (strcmp(method, ctx->methods[i].method) == 0) { - ret = ctx->methods[i].fn(message, ctx, &reply); - /* FIXME: check error */ - break; - } - } - /* FIXME: check if we didn't find any matching method */ - } - - DEBUG(2, ("Method %s complete. Reply was %srequested.\n", method, reply?"":"not ")); - - if (reply) { - dbus_connection_send(conn, reply, NULL); - dbus_message_unref(reply); - } - - return reply ? DBUS_HANDLER_RESULT_HANDLED : - DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -/* Adds a new D-BUS path message handler to the connection - * Note: this must be a unique path. - */ -int sbus_conn_add_method_ctx(struct sbus_conn_ctx *dct_ctx, struct sbus_method_ctx *method_ctx) { - DBusObjectPathVTable *connection_vtable; - dbus_bool_t dbret; - if (!method_ctx) { - return EINVAL; - } - - if (_method_list_contains_path(dct_ctx->method_ctx_list, method_ctx)) { - return EINVAL; - } - - DLIST_ADD(dct_ctx->method_ctx_list, method_ctx); - - /* Set up the vtable for the object path */ - connection_vtable = talloc_zero(dct_ctx, DBusObjectPathVTable); - if (method_ctx->message_handler) { - connection_vtable->message_function = method_ctx->message_handler; - } else { - connection_vtable->message_function = message_handler; - } - - dbret = dbus_connection_register_object_path(dct_ctx->conn, method_ctx->path, connection_vtable, method_ctx); - if (!dbret) { - return ENOMEM; - } - - return EOK; -} - -static int _method_list_contains_path(struct sbus_method_ctx *list, struct sbus_method_ctx *method) { - struct sbus_method_ctx *iter; - - if (!list || !method) { - return 0; /* FALSE */ - } - - iter = list; - while (iter != NULL) { - if (strcmp(iter->path, method->path) == 0) - return 1; /* TRUE */ - - iter = iter->next; - } - - return 0; /* FALSE */ -} - -static void sbus_unreg_object_paths(struct sbus_conn_ctx *dct_ctx) { - struct sbus_method_ctx *iter = dct_ctx->method_ctx_list; - struct sbus_method_ctx *purge; - - while(iter != NULL) { - dbus_connection_unregister_object_path(dct_ctx->conn, iter->path); - DLIST_REMOVE(dct_ctx->method_ctx_list, iter); - purge = iter; - iter = iter->next; - talloc_free(purge); - } -} - -void sbus_conn_set_private_data(struct sbus_conn_ctx *dct_ctx, void *private) { - dct_ctx->private = private; -} |