diff options
Diffstat (limited to 'server/dbus')
-rw-r--r-- | server/dbus/sssd_dbus.h | 48 | ||||
-rw-r--r-- | server/dbus/sssd_dbus_client.h | 67 | ||||
-rw-r--r-- | server/dbus/sssd_dbus_common.c | 4 | ||||
-rw-r--r-- | server/dbus/sssd_dbus_common.h | 14 | ||||
-rw-r--r-- | server/dbus/sssd_dbus_connection.c (renamed from server/dbus/sssd_dbus_client.c) | 260 | ||||
-rw-r--r-- | server/dbus/sssd_dbus_private.h | 11 | ||||
-rw-r--r-- | server/dbus/sssd_dbus_server.c | 300 | ||||
-rw-r--r-- | server/dbus/sssd_dbus_server.h | 69 | ||||
-rw-r--r-- | server/dbus/tests/test_client.c | 126 |
9 files changed, 519 insertions, 380 deletions
diff --git a/server/dbus/sssd_dbus.h b/server/dbus/sssd_dbus.h new file mode 100644 index 00000000..00a665bc --- /dev/null +++ b/server/dbus/sssd_dbus.h @@ -0,0 +1,48 @@ +/* + SSSD + + SSSD - D-BUS interface + + Copyright (C) Stephen Gallagher 2008 + + 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 <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SSSD_DBUS_H_ +#define _SSSD_DBUS_H_ + +typedef int (*sssd_dbus_msg_handler_fn)(DBusMessage *msg, void *data, + DBusMessage **reply); + +struct sssd_dbus_method { + const char *method; + sssd_dbus_msg_handler_fn fn; +}; + +struct sssd_dbus_ctx { + struct event_context *ev; + char *name; + char *path; + struct sssd_dbus_method *methods; +}; + +/* Server Functions */ +int sssd_new_dbus_server(struct sssd_dbus_ctx *ctx, const char *address); + +/* Connection Functions */ +int sssd_new_dbus_connection(struct sssd_dbus_ctx *ctx, const char *address, + DBusConnection **connection); + + +#endif /* _SSSD_DBUS_H_*/ diff --git a/server/dbus/sssd_dbus_client.h b/server/dbus/sssd_dbus_client.h deleted file mode 100644 index 8e1bc876..00000000 --- a/server/dbus/sssd_dbus_client.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef CLIENT_DBUS_H_ -#define CLIENT_DBUS_H_ -/* - SSSD - - Service monitor - D-BUS features - - Copyright (C) Stephen Gallagher 2008 - - 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 <http://www.gnu.org/licenses/>. -*/ -#include "dbus/dbus.h" -#include "events.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; -}; -/* Functions */ -int integrate_connection_with_event_loop(struct event_context *event_ctx, - DBusConnection *dbus_conn); -void dbus_connection_wakeup_main_setup(struct dbus_connection_toplevel_context *dct_ctx); - -dbus_bool_t add_connection_watch(DBusWatch *watch, void *data); -void toggle_connection_watch(DBusWatch *watch, void *data); - -dbus_bool_t add_connection_timeout(DBusTimeout *timeout, void *data); -void toggle_connection_timeout(DBusTimeout *timeout, void *data); -void dbus_connection_wakeup_main(void *data); - -void dbus_connection_read_write_handler(struct event_context *ev, struct fd_event *fde, uint16_t flags, void *ptr); -void dbus_connection_timeout_handler(struct event_context *ev, struct timed_event *te, struct timeval t, void *data); -void dbus_connection_wakeup_main_handler(struct event_context *ev_ctx, - struct signal_event *se, int signum, - int count, void *_info, void *data); - -void do_dispatch(struct event_context *ev, - struct timed_event *te, - struct timeval t, void *ptr); - -const char* print_status(int status); -#endif /*CLIENT_DBUS_H_*/ diff --git a/server/dbus/sssd_dbus_common.c b/server/dbus/sssd_dbus_common.c index 140d2f1a..188192dd 100644 --- a/server/dbus/sssd_dbus_common.c +++ b/server/dbus/sssd_dbus_common.c @@ -1,6 +1,6 @@ #include <sys/time.h> -#include "dbus/sssd_dbus_common.h" #include "events.h" +#include "dbus/dbus.h" struct timeval _dbus_timeout_get_interval_tv(int interval) { struct timeval tv; @@ -37,4 +37,4 @@ void remove_timeout(DBusTimeout *timeout, void *data) { /* Freeing the event object will remove it from the event loop */ talloc_free(te); -}
\ No newline at end of file +} diff --git a/server/dbus/sssd_dbus_common.h b/server/dbus/sssd_dbus_common.h deleted file mode 100644 index e0683be8..00000000 --- a/server/dbus/sssd_dbus_common.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SSSD_DBUS_COMMON_H_ -#define SSSD_DBUS_COMMON_H_ - -#include "dbus/dbus.h" - -/* TODO: get this value from LDB */ -#define DBUS_ADDRESS "unix:path=/tmp/dbus-sgallagh.sock" - -/* Functions */ -struct timeval _dbus_timeout_get_interval_tv(int interval); -void remove_watch(DBusWatch *watch, void *data); -void remove_timeout(DBusTimeout *timeout, void *data); - -#endif /*SSSD_DBUS_COMMON_H_*/ diff --git a/server/dbus/sssd_dbus_client.c b/server/dbus/sssd_dbus_connection.c index 48f1ae45..f1675ff3 100644 --- a/server/dbus/sssd_dbus_client.c +++ b/server/dbus/sssd_dbus_connection.c @@ -1,40 +1,53 @@ -#include "dbus/sssd_dbus_common.h" -#include "dbus/sssd_dbus_client.h" -#include "util/util.h" #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; +}; -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, +static void do_dispatch(struct event_context *ev, struct timed_event *te, - struct timeval t, void *ptr) { + struct timeval tv, void *data) +{ struct timed_event *new_event; - DBusConnection *conn = (DBusConnection *)ptr; + DBusConnection *conn; + int ret; + + conn = (DBusConnection *)data; /* Dispatch only once each time through the mainloop to avoid * starving other features */ - if(dbus_connection_get_dispatch_status(conn) != DBUS_DISPATCH_COMPLETE) { + 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. */ - if(dbus_connection_get_dispatch_status(conn) != DBUS_DISPATCH_COMPLETE) { - new_event = event_add_timed(ev, ev, t, do_dispatch, conn); + 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); @@ -43,43 +56,25 @@ void do_dispatch(struct event_context *ev, } /* - * integrate_connection_with_event_loop - * Set up a D-BUS connection to use the libevents mainloop - * for handling file descriptor and timed events + * dbus_connection_read_write_handler + * Callback for D-BUS to handle messages on a file-descriptor */ -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; - } +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); - /* 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; + dbus_connection_ref(conn_w_ctx->top->conn); + if (flags & EVENT_FD_READ) { + dbus_watch_handle(conn_w_ctx->watch, DBUS_WATCH_READABLE); } - - /* 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; + if (flags & EVENT_FD_WRITE) { + dbus_watch_handle(conn_w_ctx->watch, DBUS_WATCH_WRITABLE); + } + dbus_connection_unref(conn_w_ctx->top->conn); } /* @@ -87,7 +82,8 @@ int integrate_connection_with_event_loop(struct event_context *event_ctx, * 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) { +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; @@ -118,8 +114,10 @@ dbus_bool_t add_connection_watch(DBusWatch *watch, void *data) { 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); + 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); @@ -127,24 +125,41 @@ dbus_bool_t add_connection_watch(DBusWatch *watch, void *data) { 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)) +static void toggle_connection_watch(DBusWatch *watch, void *data) +{ + if (dbus_watch_get_enabled(watch)) { add_connection_watch(watch, data); - else + } 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 */ -dbus_bool_t add_connection_timeout(DBusTimeout *timeout, void *data) { +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; @@ -177,41 +192,13 @@ dbus_bool_t add_connection_timeout(DBusTimeout *timeout, void *data) { * 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)) +void toggle_connection_timeout(DBusTimeout *timeout, void *data) +{ + if (dbus_timeout_get_enabled(timeout)) { add_connection_timeout(timeout, data); - else + } 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 @@ -221,7 +208,7 @@ void dbus_connection_timeout_handler(struct event_context *ev, struct timed_even * timed event to perform the dispatch during the next iteration * through the mainloop */ -void dbus_connection_wakeup_main(void *data) { +static void dbus_connection_wakeup_main(void *data) { struct dbus_connection_toplevel_context *dct_ctx; struct timeval tv; struct timed_event *te; @@ -229,9 +216,88 @@ void dbus_connection_wakeup_main(void *data) { 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); + 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; +} diff --git a/server/dbus/sssd_dbus_private.h b/server/dbus/sssd_dbus_private.h new file mode 100644 index 00000000..ae3540bd --- /dev/null +++ b/server/dbus/sssd_dbus_private.h @@ -0,0 +1,11 @@ +#ifndef _SSSD_DBUS_PRIVATE_H_ +#define _SSSD_DBUS_PRIVATE_H_ + +int sssd_add_dbus_connection(struct sssd_dbus_ctx *ctx, + DBusConnection *dbus_conn); + +struct timeval _dbus_timeout_get_interval_tv(int interval); +void remove_watch(DBusWatch *watch, void *data); +void remove_timeout(DBusTimeout *timeout, void *data); + +#endif /* _SSSD_DBUS_PRIVATE_H_ */ diff --git a/server/dbus/sssd_dbus_server.c b/server/dbus/sssd_dbus_server.c index 288a3333..113866fa 100644 --- a/server/dbus/sssd_dbus_server.c +++ b/server/dbus/sssd_dbus_server.c @@ -19,73 +19,50 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <sys/time.h> -#include "dbus/dbus.h" -#include "monitor.h" -#include "dbus/sssd_dbus_common.h" -#include "dbus/sssd_dbus_server.h" -#include "dbus/sssd_dbus_client.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_server_toplevel_context { + DBusServer *server; + struct sssd_dbus_ctx *sd_ctx; +}; + +struct dbus_server_watch_context { + DBusWatch *watch; + int fd; + struct fd_event *fde; + struct dbus_server_toplevel_context *top; +}; + +struct dbus_server_timeout_context { + DBusTimeout *timeout; + struct timed_event *te; + struct dbus_server_toplevel_context *top; +}; /* - * integrate_server_with_event_loop - * Set up a D-BUS server to use the libevents mainloop - * for handling file descriptor and timed events + * dbus_server_read_write_handler + * Callback for D-BUS to handle messages on a file-descriptor */ -int integrate_server_with_event_loop(struct event_context *event_ctx, - DBusServer *dbus_server, - void(*server_connection_setup)(DBusConnection *conn, struct event_context *)) { - struct dbus_server_toplevel_context *dt_ctx; - dt_ctx = talloc_zero(event_ctx, struct dbus_server_toplevel_context); - dt_ctx->ev = event_ctx; - dt_ctx->server = dbus_server; - dt_ctx->server_connection_setup = server_connection_setup; - - /* Set up D-BUS new connection handler */ - dbus_server_set_new_connection_function(dt_ctx->server, - new_connection_callback, dt_ctx, NULL); - - /* Set up DBusWatch functions */ - if (!dbus_server_set_watch_functions(dt_ctx->server, add_server_watch, - remove_watch, toggle_server_watch, dt_ctx, NULL)) { - DEBUG(0,("Error setting up D-BUS server watch functions")); - return -1; - } +static void dbus_server_read_write_handler(struct event_context *ev, + struct fd_event *fde, + uint16_t flags, void *data) +{ + struct dbus_server_watch_context *svw_ctx; + svw_ctx = talloc_get_type(data, struct dbus_server_watch_context); - /* Set up DBusTimeout functions */ - if (!dbus_server_set_timeout_functions(dt_ctx->server, add_server_timeout, - remove_timeout, toggle_server_timeout, dt_ctx, NULL)) { - DEBUG(0,("Error setting up D-BUS server timeout functions")); - return -1; + dbus_server_ref(svw_ctx->top->server); + if (flags & EVENT_FD_READ) { + dbus_watch_handle(svw_ctx->watch, DBUS_WATCH_READABLE); } - - return 0; -} - -/* - * new_connection_callback - * Actions to be run upon each new client connection - * Must either perform dbus_connection_ref() on the - * new connection or else close the connection with - * dbus_connection_close() - */ -void new_connection_callback(DBusServer *server, - DBusConnection *new_connection, void *data) { - - struct dbus_server_toplevel_context *dst_ctx; - dst_ctx = talloc_get_type(data,struct dbus_server_toplevel_context); - - if(integrate_connection_with_event_loop(dst_ctx->ev,new_connection) != 0) { - dbus_connection_close(new_connection); - DEBUG(0,("Closing connection (failed setup)")); - return; + if (flags & EVENT_FD_WRITE) { + dbus_watch_handle(svw_ctx->watch, DBUS_WATCH_WRITABLE); } - dbus_connection_ref(new_connection); - - /* Run connection setup function */ - DEBUG(3,("Got a connection\n")); - dst_ctx->server_connection_setup(new_connection, dst_ctx->ev); - DEBUG(3,("New connection set up.\n")); + dbus_server_unref(svw_ctx->top->server); } /* @@ -93,7 +70,8 @@ void new_connection_callback(DBusServer *server, * Set up hooks into the libevents mainloop for * D-BUS to add file descriptor-based events */ -dbus_bool_t add_server_watch(DBusWatch *watch, void *data) { +static dbus_bool_t add_server_watch(DBusWatch *watch, void *data) +{ unsigned int flags; unsigned int event_flags; struct dbus_server_toplevel_context *dt_ctx; @@ -121,11 +99,13 @@ dbus_bool_t add_server_watch(DBusWatch *watch, void *data) { if (flags & DBUS_WATCH_WRITABLE) { event_flags |= EVENT_FD_WRITE; } - svw_ctx->fde = event_add_fd(svw_ctx->top->ev, svw_ctx, svw_ctx->fd, - event_flags, dbus_server_read_write_handler, svw_ctx); + + svw_ctx->fde = event_add_fd(dt_ctx->sd_ctx->ev, svw_ctx, svw_ctx->fd, + event_flags, dbus_server_read_write_handler, + svw_ctx); /* Save the event to the watch object so it can be removed later */ - dbus_watch_set_data(svw_ctx->watch,svw_ctx->fde,NULL); + dbus_watch_set_data(svw_ctx->watch, svw_ctx->fde, NULL); return TRUE; } @@ -135,18 +115,30 @@ dbus_bool_t add_server_watch(DBusWatch *watch, void *data) { * Hook for D-BUS to toggle the enabled/disabled state of * an event in the mainloop */ -void toggle_server_watch(DBusWatch *watch, void *data) { - if (dbus_watch_get_enabled(watch)) +static void toggle_server_watch(DBusWatch *watch, void *data) +{ + if (dbus_watch_get_enabled(watch)) { add_server_watch(watch, data); - else + } else { remove_watch(watch, data); + } +} + +static void dbus_server_timeout_handler(struct event_context *ev, + struct timed_event *te, + struct timeval t, void *data) +{ + struct dbus_server_timeout_context *svt_ctx; + svt_ctx = talloc_get_type(data, struct dbus_server_timeout_context); + dbus_timeout_handle(svt_ctx->timeout); } /* * add_server_timeout * Hook for D-BUS to add time-based events to the mainloop */ -dbus_bool_t add_server_timeout(DBusTimeout *timeout, void *data) { +static dbus_bool_t add_server_timeout(DBusTimeout *timeout, void *data) +{ struct dbus_server_toplevel_context *dt_ctx; struct dbus_server_timeout_context *svt_ctx; struct timeval tv; @@ -162,11 +154,11 @@ dbus_bool_t add_server_timeout(DBusTimeout *timeout, void *data) { tv = _dbus_timeout_get_interval_tv(dbus_timeout_get_interval(timeout)); - svt_ctx->te = event_add_timed(svt_ctx->top->ev, svt_ctx, tv, - dbus_server_timeout_handler, svt_ctx); + svt_ctx->te = event_add_timed(dt_ctx->sd_ctx->ev, svt_ctx, tv, + dbus_server_timeout_handler, svt_ctx); /* Save the event to the watch object so it can be removed later */ - dbus_timeout_set_data(svt_ctx->timeout,svt_ctx->te,NULL); + dbus_timeout_set_data(svt_ctx->timeout, svt_ctx->te, NULL); return TRUE; } @@ -176,35 +168,161 @@ dbus_bool_t add_server_timeout(DBusTimeout *timeout, void *data) { * Hook for D-BUS to toggle the enabled/disabled state of a mainloop * event */ -void toggle_server_timeout(DBusTimeout *timeout, void *data) { - if (dbus_timeout_get_enabled(timeout)) +static void toggle_server_timeout(DBusTimeout *timeout, void *data) +{ + if (dbus_timeout_get_enabled(timeout)) { add_server_timeout(timeout, data); - else + } else { remove_timeout(timeout, data); + } } -/* - * dbus_server_read_write_handler - * Callback for D-BUS to handle messages on a file-descriptor +/* messsage_handler + * Receive messages and process them */ -void dbus_server_read_write_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *ptr) { - struct dbus_server_watch_context *svw_ctx; - svw_ctx = talloc_get_type(ptr,struct dbus_server_watch_context); +static DBusHandlerResult message_handler(DBusConnection *conn, + DBusMessage *message, + void *user_data) +{ + struct sssd_dbus_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 sssd_dbus_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->name) != 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 */ + } - dbus_server_ref(svw_ctx->top->server); - if (flags & EVENT_FD_READ) { - dbus_watch_handle(svw_ctx->watch, DBUS_WATCH_READABLE); + if (reply) { + dbus_connection_send(conn, reply, NULL); + dbus_message_unref(reply); } - if (flags & EVENT_FD_WRITE) { - dbus_watch_handle(svw_ctx->watch, DBUS_WATCH_WRITABLE); + + return reply ? DBUS_HANDLER_RESULT_HANDLED : + DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +/* + * new_connection_callback + * Actions to be run upon each new client connection + * Must either perform dbus_connection_ref() on the + * new connection or else close the connection with + * dbus_connection_close() + */ +static void new_connection_callback(DBusServer *server, DBusConnection *conn, + void *data) +{ + struct dbus_server_toplevel_context *dst_ctx; + DBusObjectPathVTable *monitor_vtable; + int ret; + + dst_ctx = talloc_get_type(data,struct dbus_server_toplevel_context); + + ret = sssd_add_dbus_connection(dst_ctx->sd_ctx, conn); + if (ret != 0) { + dbus_connection_close(conn); + DEBUG(0,("Closing connection (failed setup)")); + return; } - dbus_server_ref(svw_ctx->top->server); + + dbus_connection_ref(conn); + + DEBUG(3,("Got a connection\n")); + + monitor_vtable = talloc_zero(dst_ctx, DBusObjectPathVTable); + + DEBUG (3,("Initializing D-BUS methods.\n")); + monitor_vtable->message_function = message_handler; + + dbus_connection_register_object_path(conn, dst_ctx->sd_ctx->path, + monitor_vtable, dst_ctx->sd_ctx); + + DEBUG(3,("D-BUS method initialization complete.\n")); } -void dbus_server_timeout_handler(struct event_context *ev, struct timed_event *te, - struct timeval t, void *data) { - struct dbus_server_timeout_context *svt_ctx; - svt_ctx = talloc_get_type(data, struct dbus_server_timeout_context); - dbus_timeout_handle(svt_ctx->timeout); +/* + * dbus_new_server + * Set up a D-BUS server, integrate with the event loop + * for handling file descriptor and timed events + */ +int sssd_new_dbus_server(struct sssd_dbus_ctx *ctx, const char *address) +{ + struct dbus_server_toplevel_context *dt_ctx; + DBusServer *dbus_server; + DBusError dbus_error; + dbus_bool_t dbret; + + /* Set up D-BUS server */ + dbus_error_init(&dbus_error); + dbus_server = dbus_server_listen(address, &dbus_error); + if (!dbus_server) { + DEBUG(0,("dbus_server_listen failed! (name=%s, message=%s)\n", + dbus_error.name, dbus_error.message)); + return EIO; + } + + /* TODO: remove debug */ + DEBUG(2, ("D-BUS Server listening on %s\n", + dbus_server_get_address(dbus_server))); + + dt_ctx = talloc_zero(ctx, struct dbus_server_toplevel_context); + if (!dt_ctx) { + /* FIXME: free DBusServer resources */ + return ENOMEM; + } + dt_ctx->server = dbus_server; + dt_ctx->sd_ctx = ctx; + + /* Set up D-BUS new connection handler */ + /* FIXME: set free_data_function */ + dbus_server_set_new_connection_function(dt_ctx->server, + new_connection_callback, + dt_ctx, NULL); + + /* Set up DBusWatch functions */ + dbret = dbus_server_set_watch_functions(dt_ctx->server, add_server_watch, + remove_watch, toggle_server_watch, + dt_ctx, NULL); + if (!dbret) { + DEBUG(0, ("Error setting up D-BUS server watch functions")); + /* FIXME: free DBusServer resources */ + return EIO; + } + + /* Set up DBusTimeout functions */ + dbret = dbus_server_set_timeout_functions(dt_ctx->server, + add_server_timeout, + remove_timeout, + toggle_server_timeout, + dt_ctx, NULL); + if (!dbret) { + DEBUG(0,("Error setting up D-BUS server timeout functions")); + /* FIXME: free DBusServer resources */ + return EIO; + } + + return EOK; } diff --git a/server/dbus/sssd_dbus_server.h b/server/dbus/sssd_dbus_server.h deleted file mode 100644 index 85fc12c6..00000000 --- a/server/dbus/sssd_dbus_server.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - SSSD - - Service monitor - D-BUS features - - Copyright (C) Stephen Gallagher 2008 - - 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 <http://www.gnu.org/licenses/>. -*/ - -#ifndef MONITORDBUS_H_ -#define MONITORDBUS_H_ - -#include "dbus/dbus.h" -#include "monitor.h" -#include "events.h" -#include "sssd_dbus_common.h" - -/* Types */ -struct dbus_server_toplevel_context { - DBusServer *server; - struct event_context *ev; - void (*server_connection_setup)(DBusConnection *conn, struct event_context *); -}; - -struct dbus_server_watch_context { - DBusWatch *watch; - int fd; - struct fd_event *fde; - struct dbus_server_toplevel_context *top; -}; - -struct dbus_server_timeout_context { - DBusTimeout *timeout; - struct timed_event *te; - struct dbus_server_toplevel_context *top; -}; - -/* Functions */ -int integrate_server_with_event_loop( - struct event_context *event_ctx, - DBusServer *dbus_server, - void (*server_connection_setup)(DBusConnection *conn, struct event_context *) -); - -void new_connection_callback(DBusServer *server, - DBusConnection *new_connection, void *data); - -dbus_bool_t add_server_watch(DBusWatch *watch, void *data); -void toggle_server_watch(DBusWatch *watch, void *data); - -dbus_bool_t add_server_timeout(DBusTimeout *timeout, void *data); -void toggle_server_timeout(DBusTimeout *timeout, void *data); - -void dbus_server_read_write_handler(struct event_context *ev, struct fd_event *fde, uint16_t flags, void *ptr); -void dbus_server_timeout_handler(struct event_context *ev, struct timed_event *te, struct timeval t, void *data); - -#endif /*MONITORDBUS_H_*/ diff --git a/server/dbus/tests/test_client.c b/server/dbus/tests/test_client.c index 8a82284c..30401991 100644 --- a/server/dbus/tests/test_client.c +++ b/server/dbus/tests/test_client.c @@ -2,16 +2,27 @@ #include <stdio.h> #include <sys/time.h> #include "events.h" -#include "dbus/dbus.h" -#include "monitor.h" -#include "dbus/sssd_dbus_common.h" -#include "dbus/sssd_dbus_client.h" #include "util/util.h" +#include "dbus/dbus.h" +#include "dbus/sssd_dbus.h" -static void request_version_timed(struct event_context *ev, - DBusConnection *conn); +/* TODO: get this value from LDB */ +#define DBUS_ADDRESS "unix:path=/var/lib/sss/pipes/private/dbus" -static void print_version (DBusPendingCall *pending, void *ptr) { +/* Monitor Interface */ +#define MONITOR_DBUS_INTERFACE "org.freeipa.sssd.monitor" +#define MONITOR_DBUS_PATH "/org/freeipa/sssd/monitor" +#define MONITOR_METHOD_VERSION "getVersion" + +struct test_cli_ctx { + struct sssd_dbus_ctx *sd_ctx; + DBusConnection *conn; +}; + +static void request_version_timed(struct test_cli_ctx *ctx); + +static void print_version(DBusPendingCall *pending, void *data) +{ DBusMessage *reply; DBusError error; const char *version_string; @@ -25,25 +36,27 @@ static void print_version (DBusPendingCall *pending, void *ptr) { * until reply is valid. If reply is NULL here, something is seriously * wrong and we should bail out. */ - DEBUG(0,("Serious error. A reply callback was called but no reply was received")); + DEBUG(0, ("Serious error. A reply callback was called but no reply was received")); exit(3); } type = dbus_message_get_type(reply); - if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN) { - if(dbus_message_get_args(reply, &error, DBUS_TYPE_STRING, &version_string, DBUS_TYPE_INVALID)) { + switch (type) { + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + if (dbus_message_get_args(reply, &error, + DBUS_TYPE_STRING, + &version_string, + DBUS_TYPE_INVALID)) { fprintf(stdout, "Version: %s\n", version_string); fflush(stdout); - } - else { + } else { DEBUG(0, ("Error getting arguments in print_version")); } - } - else if (type == DBUS_MESSAGE_TYPE_ERROR) { - - } - else { + break; + case DBUS_MESSAGE_TYPE_ERROR: + break; + default: DEBUG(0, ("Received unexpected message")); exit(4); } @@ -51,22 +64,29 @@ static void print_version (DBusPendingCall *pending, void *ptr) { static void test_timed_handler(struct event_context *ev, struct timed_event *te, - struct timeval t, void *ptr) { - DBusConnection *conn; + struct timeval tv, void *data) +{ + struct test_cli_ctx *test_ctx; + struct sssd_dbus_ctx *ctx; DBusPendingCall *pending_reply; - DBusMessage *version_request; + DBusMessage *vmsg; DBusError error; - conn = (DBusConnection *) ptr; + dbus_bool_t dbret; + + test_ctx = talloc_get_type(data, struct test_cli_ctx); + ctx = test_ctx->sd_ctx; fprintf(stdout, "."); fflush(stdout); dbus_error_init(&error); - version_request = dbus_message_new_method_call( - NULL, MONITOR_DBUS_PATH, MONITOR_DBUS_INTERFACE, - MONITOR_METHOD_VERSION); + vmsg = dbus_message_new_method_call(NULL, + ctx->path, ctx->name, + MONITOR_METHOD_VERSION); - if(!dbus_connection_send_with_reply(conn, version_request, &pending_reply, -1)){ + dbret = dbus_connection_send_with_reply(test_ctx->conn, vmsg, + &pending_reply, -1); + if (!dbret) { /* Critical failure */ DEBUG(0,("Failed to send version_request")); exit(2); @@ -74,50 +94,76 @@ static void test_timed_handler(struct event_context *ev, dbus_pending_call_set_notify(pending_reply, print_version, NULL, NULL); - dbus_message_unref(version_request); + dbus_message_unref(vmsg); - request_version_timed(ev,conn); + request_version_timed(test_ctx); } -static void request_version_timed(struct event_context *ev, DBusConnection *conn) { +static void request_version_timed(struct test_cli_ctx *ctx) +{ struct timed_event *te = NULL; struct timeval tv; gettimeofday(&tv, NULL); tv.tv_sec += 5; tv.tv_usec = 0; - te = event_add_timed(ev, ev, tv, test_timed_handler, conn); + te = event_add_timed(ctx->sd_ctx->ev, ctx, tv, test_timed_handler, ctx); if (te == NULL) { DEBUG(0, ("failed to add event!\n")); exit(1); } } -int main (int argc, const char *argv[]) { - DBusError dbus_error; - DBusConnection *dbus_conn; +int main (int argc, const char *argv[]) +{ struct event_context *event_ctx; + struct sssd_dbus_ctx *ctx; + struct test_cli_ctx *test_ctx; + DBusConnection *dbus_conn; + int ret; event_ctx = event_context_init(talloc_autofree_context()); + if (!event_ctx) { + printf("Out of memory!?\n"); + exit(1); + } + + ctx = talloc_zero(event_ctx, struct sssd_dbus_ctx); + if (!ctx) { + printf("Out of memory!?\n"); + exit(1); + } + ctx->ev = event_ctx; + ctx->name = talloc_strdup(ctx, MONITOR_DBUS_INTERFACE); + ctx->path = talloc_strdup(ctx, MONITOR_DBUS_PATH); + if (!ctx->name || !ctx->path) { + printf("Out of memory!?\n"); + exit(1); + } + + ret = sssd_new_dbus_connection(ctx, DBUS_ADDRESS, &dbus_conn); + if (ret != EOK) { + exit(1); + } - dbus_error_init(&dbus_error); - dbus_conn = dbus_connection_open(DBUS_ADDRESS, &dbus_error); - if (dbus_conn == NULL) { - printf ("Error: name=%s, message=%s\n", dbus_error.name, dbus_error.message); + test_ctx = talloc(ctx, struct test_cli_ctx); + if (!test_ctx) { + printf("Out of memory!?\n"); exit(1); } + test_ctx->sd_ctx = ctx; + test_ctx->conn = dbus_conn; - integrate_connection_with_event_loop(event_ctx,dbus_conn); - dbus_connection_set_exit_on_disconnect (dbus_conn, TRUE); + dbus_connection_set_exit_on_disconnect(dbus_conn, TRUE); /* Set up a timed event to request the server version every * five seconds and print it to the screen. */ - request_version_timed(event_ctx,dbus_conn); + request_version_timed(test_ctx); /* Enter the main loop (and hopefully never return) */ event_loop_wait(event_ctx); talloc_free(event_ctx); return EXIT_SUCCESS; -}
\ No newline at end of file +} |