diff options
author | Simo Sorce <ssorce@redhat.com> | 2008-10-24 19:09:44 +0200 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2008-10-27 10:02:38 -0400 |
commit | 6fe2bfce9fb9bb1564be8257cccc52bcec589de4 (patch) | |
tree | 1b9e603f7b08f8697b443e94a0e358b4fb00f07c /server/dbus/sssd_dbus_connection.c | |
parent | 054a931b01f98cf94b42f1ff1f48fbcb4928c869 (diff) | |
download | sssd-6fe2bfce9fb9bb1564be8257cccc52bcec589de4.tar.gz sssd-6fe2bfce9fb9bb1564be8257cccc52bcec589de4.tar.bz2 sssd-6fe2bfce9fb9bb1564be8257cccc52bcec589de4.zip |
D-BUS integration style changes.
Rework interfaces a bit to simplify and uniform function names so that they
use a well defined namespace (sssd_*).
Simplify headers file, split them into a private and a public one only.
Make static all file private functions.
Rename sssd_dbus_client.c to sssd_dbus_connection.c to reflect it's function,
as it is is used by both a server and a client.
Introduce a function table to know where to dipatch messages.
Fix coding style issues, and start pointing out where clean-up fucntions
are missing.
Diffstat (limited to 'server/dbus/sssd_dbus_connection.c')
-rw-r--r-- | server/dbus/sssd_dbus_connection.c | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/server/dbus/sssd_dbus_connection.c b/server/dbus/sssd_dbus_connection.c new file mode 100644 index 00000000..f1675ff3 --- /dev/null +++ b/server/dbus/sssd_dbus_connection.c @@ -0,0 +1,303 @@ +#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_connection_toplevel_context { + DBusConnection *conn; + struct event_context *ev; +}; + +struct dbus_connection_watch_context { + DBusWatch *watch; + int fd; + struct fd_event *fde; + struct dbus_connection_toplevel_context *top; +}; + +struct dbus_connection_timeout_context { + DBusTimeout *timeout; + struct timed_event *te; + struct dbus_connection_toplevel_context *top; +}; + +static void do_dispatch(struct event_context *ev, + struct timed_event *te, + struct timeval tv, void *data) +{ + struct timed_event *new_event; + DBusConnection *conn; + int ret; + + conn = (DBusConnection *)data; + + /* 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, ev, tv, do_dispatch, conn); + if (new_event == NULL) { + DEBUG(0,("Could not add dispatch event!\n")); + exit(1); + } + } +} + +/* + * dbus_connection_read_write_handler + * Callback for D-BUS to handle messages on a file-descriptor + */ + +static void dbus_connection_read_write_handler(struct event_context *ev, + struct fd_event *fde, + uint16_t flags, void *data) +{ + struct dbus_connection_watch_context *conn_w_ctx; + conn_w_ctx = talloc_get_type(data, struct dbus_connection_watch_context); + + 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 add_connection_watch(DBusWatch *watch, void *data) +{ + unsigned int flags; + unsigned int event_flags; + struct dbus_connection_toplevel_context *dt_ctx; + struct dbus_connection_watch_context *conn_w_ctx; + + if (!dbus_watch_get_enabled(watch)) { + return TRUE; + } + + dt_ctx = talloc_get_type(data, struct dbus_connection_toplevel_context); + + conn_w_ctx = talloc_zero(dt_ctx, struct dbus_connection_watch_context); + 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; + + /* 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, + dbus_connection_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 toggle_connection_watch(DBusWatch *watch, void *data) +{ + if (dbus_watch_get_enabled(watch)) { + add_connection_watch(watch, data); + } else { + remove_watch(watch, data); + } +} + +/* + * dbus_connection_timeout_handler + * Callback for D-BUS to handle timed events + */ +static void dbus_connection_timeout_handler(struct event_context *ev, + struct timed_event *te, + struct timeval t, void *data) +{ + struct dbus_connection_timeout_context *conn_t_ctx; + conn_t_ctx = talloc_get_type(data, struct dbus_connection_timeout_context); + + 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 add_connection_timeout(DBusTimeout *timeout, void *data) +{ + struct dbus_connection_toplevel_context *dt_ctx; + struct dbus_connection_timeout_context *conn_t_ctx; + struct timeval tv; + + if (!dbus_timeout_get_enabled(timeout)) + return TRUE; + + dt_ctx = talloc_get_type(data, struct dbus_connection_toplevel_context); + + conn_t_ctx = talloc_zero(dt_ctx,struct dbus_connection_timeout_context); + 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, + dbus_connection_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; +} + +/* + * toggle_connection_timeout + * Hook for D-BUS to toggle the enabled/disabled state of a mainloop + * event + */ +void toggle_connection_timeout(DBusTimeout *timeout, void *data) +{ + if (dbus_timeout_get_enabled(timeout)) { + add_connection_timeout(timeout, data); + } else { + 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 dbus_connection_wakeup_main(void *data) { + struct dbus_connection_toplevel_context *dct_ctx; + struct timeval tv; + struct timed_event *te; + dct_ctx = talloc_get_type(data, struct dbus_connection_toplevel_context); + 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->ev, + tv, do_dispatch, dct_ctx->conn); + 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 sssd_add_dbus_connection(struct sssd_dbus_ctx *ctx, + DBusConnection *dbus_conn) +{ + struct dbus_connection_toplevel_context *dt_ctx; + dbus_bool_t dbret; + + dt_ctx = talloc_zero(ctx, struct dbus_connection_toplevel_context); + dt_ctx->ev = ctx->ev; + dt_ctx->conn = dbus_conn; + + /* Set up DBusWatch functions */ + dbret = dbus_connection_set_watch_functions(dt_ctx->conn, + add_connection_watch, + remove_watch, + toggle_connection_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, + add_connection_timeout, + remove_timeout, + toggle_connection_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, + dbus_connection_wakeup_main, + dt_ctx, NULL); + + /* 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. + */ + dbus_connection_wakeup_main(dt_ctx); + + return EOK; +} + +int sssd_new_dbus_connection(struct sssd_dbus_ctx *ctx, const char *address, + DBusConnection **connection) +{ + DBusConnection *dbus_conn; + DBusError dbus_error; + int ret; + + dbus_error_init(&dbus_error); + 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 = sssd_add_dbus_connection(ctx, dbus_conn); + if (ret == EOK) { + *connection = dbus_conn; + } else { + /* FIXME: release resources */ + } + + return ret; +} |