diff options
author | Stephen Gallagher <sgallagh@redhat.com> | 2008-10-24 07:58:00 -0400 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2008-10-24 07:58:00 -0400 |
commit | 054a931b01f98cf94b42f1ff1f48fbcb4928c869 (patch) | |
tree | bc5555e5e64145320693d5a26d709e3aa6a6ab41 /server/dbus/sssd_dbus_client.c | |
parent | c6fd412c0dd03782aa28c20f90bde0e22f720e7b (diff) | |
download | sssd-054a931b01f98cf94b42f1ff1f48fbcb4928c869.tar.gz sssd-054a931b01f98cf94b42f1ff1f48fbcb4928c869.tar.bz2 sssd-054a931b01f98cf94b42f1ff1f48fbcb4928c869.zip |
Integrate D-BUS support for use as IPC between parts.
Integrates DBUS with the event system so that it is asynchronous.
Diffstat (limited to 'server/dbus/sssd_dbus_client.c')
-rw-r--r-- | server/dbus/sssd_dbus_client.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/server/dbus/sssd_dbus_client.c b/server/dbus/sssd_dbus_client.c new file mode 100644 index 00000000..48f1ae45 --- /dev/null +++ b/server/dbus/sssd_dbus_client.c @@ -0,0 +1,237 @@ +#include "dbus/sssd_dbus_common.h" +#include "dbus/sssd_dbus_client.h" +#include "util/util.h" +#include <sys/time.h> +#include "events.h" + +const char* print_status(int status) { + switch (status){ + case DBUS_DISPATCH_DATA_REMAINS: + return "DBUS_DISPATCH_DATA_REMAINS"; + case DBUS_DISPATCH_COMPLETE: + return "DBUS_DISPATCH_COMPLETE"; + case DBUS_DISPATCH_NEED_MEMORY: + return "DBUS_DISPATCH_NEED_MEMORY"; + default: + return "ERROR"; + } +} + +void do_dispatch(struct event_context *ev, + struct timed_event *te, + struct timeval t, void *ptr) { + struct timed_event *new_event; + DBusConnection *conn = (DBusConnection *)ptr; + + /* Dispatch only once each time through the mainloop to avoid + * starving other features + */ + if(dbus_connection_get_dispatch_status(conn) != 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. + */ + if(dbus_connection_get_dispatch_status(conn) != DBUS_DISPATCH_COMPLETE) { + new_event = event_add_timed(ev, ev, t, do_dispatch, conn); + if (new_event == 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 integrate_connection_with_event_loop(struct event_context *event_ctx, + DBusConnection *dbus_conn) { + struct dbus_connection_toplevel_context *dt_ctx; + dt_ctx = talloc_zero(event_ctx, struct dbus_connection_toplevel_context); + dt_ctx->ev = event_ctx; + dt_ctx->conn = dbus_conn; + + /* Set up DBusWatch functions */ + if (!dbus_connection_set_watch_functions(dt_ctx->conn, add_connection_watch, + remove_watch, toggle_connection_watch, dt_ctx, NULL)) { + DEBUG(0,("Error setting up D-BUS connection watch functions\n")); + return -1; + } + + /* Set up DBusTimeout functions */ + if (!dbus_connection_set_timeout_functions(dt_ctx->conn, add_connection_timeout, + remove_timeout, toggle_connection_timeout, dt_ctx, NULL)) { + DEBUG(0,("Error setting up D-BUS server timeout functions\n")); + return -1; + } + + /* 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 0; +} + +/* + * add_connection_watch + * Set up hooks into the libevents mainloop for + * D-BUS to add file descriptor-based events + */ +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 + */ +void toggle_connection_watch(DBusWatch *watch, void *data) { + if (dbus_watch_get_enabled(watch)) + add_connection_watch(watch, data); + else + remove_watch(watch, data); +} + +/* + * add_connection_timeout + * Hook for D-BUS to add time-based events to the mainloop + */ +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_read_write_handler + * Callback for D-BUS to handle messages on a file-descriptor + */ + +void dbus_connection_read_write_handler(struct event_context *ev, struct fd_event *fde, + uint16_t flags, void *ptr) { + struct dbus_connection_watch_context *conn_w_ctx; + conn_w_ctx = talloc_get_type(ptr,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_ref(conn_w_ctx->top->conn); +} +/* + * dbus_connection_timeout_handler + * Callback for D-BUS to handle timed events + */ +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); +} + +/* 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 + */ +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); + } +} |