summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2008-10-24 07:58:00 -0400
committerSimo Sorce <idra@samba.org>2008-10-24 07:58:00 -0400
commit054a931b01f98cf94b42f1ff1f48fbcb4928c869 (patch)
treebc5555e5e64145320693d5a26d709e3aa6a6ab41
parentc6fd412c0dd03782aa28c20f90bde0e22f720e7b (diff)
downloadsssd-054a931b01f98cf94b42f1ff1f48fbcb4928c869.tar.gz
sssd-054a931b01f98cf94b42f1ff1f48fbcb4928c869.tar.xz
sssd-054a931b01f98cf94b42f1ff1f48fbcb4928c869.zip
Integrate D-BUS support for use as IPC between parts.
Integrates DBUS with the event system so that it is asynchronous.
-rw-r--r--server/Makefile.in11
-rw-r--r--server/configure.ac2
-rw-r--r--server/dbus/sssd_dbus_client.c237
-rw-r--r--server/dbus/sssd_dbus_client.h67
-rw-r--r--server/dbus/sssd_dbus_common.c40
-rw-r--r--server/dbus/sssd_dbus_common.h14
-rw-r--r--server/dbus/sssd_dbus_server.c210
-rw-r--r--server/dbus/sssd_dbus_server.h69
-rw-r--r--server/dbus/tests/test_client.c123
-rw-r--r--server/monitor.c108
-rw-r--r--server/monitor.h27
-rw-r--r--server/server.mk26
12 files changed, 923 insertions, 11 deletions
diff --git a/server/Makefile.in b/server/Makefile.in
index 262e1c95b..f2d2c69fb 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -33,6 +33,9 @@ POPT_CFLAGS = @POPT_CFLAGS@
LDB_LIBS = @LDB_LIBS@
LDB_CFLAGS = @LDB_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+
LIBDL = @LIBDL@
SHLIBEXT = @SHLIBEXT@
@@ -42,11 +45,11 @@ SHLD = @SHLD@
SHLD_FLAGS = @SHLD_FLAGS@
LDFLAGS += @LDFLAGS@
-LIBS = @LIBS@ $(TALLOC_LIBS) $(TDB_LIBS) $(EVENTS_LIBS) $(POPT_LIBS) $(LDB_LIBS)
+LIBS = @LIBS@ $(TALLOC_LIBS) $(TDB_LIBS) $(EVENTS_LIBS) $(POPT_LIBS) $(LDB_LIBS) $(DBUS_LIBS)
PICFLAG = @PICFLAG@
CFLAGS += -g -I$(srcdir)/include -Iinclude -I$(srcdir) -I$(srcdir)/.. \
- $(POPT_CFLAGS) $(TALLOC_CFLAGS) $(TDB_CFLAGS) $(EVENTS_CFLAGS) $(LDB_FLAGS)\
+ $(POPT_CFLAGS) $(TALLOC_CFLAGS) $(TDB_CFLAGS) $(EVENTS_CFLAGS) $(LDB_CFLAGS) $(DBUS_CFLAGS)\
-DLIBDIR=\"$(libdir)\" -DSHLIBEXT=\"$(SHLIBEXT)\" -DUSE_MMAP=1 @CFLAGS@
MDLD = @MDLD@
@@ -56,7 +59,7 @@ OBJS = $(SERVER_OBJ) @LIBREPLACEOBJ@ $(EXTRA_OBJ)
headers = .h
-BINS = sbin/sssd
+BINS = sbin/sssd sbin/sssd-dbus-client
DIRS = sbin
@@ -77,7 +80,7 @@ clean::
distclean:: clean
rm -rf $(DIRS)
- rm -f config.log config.status config.cache include/config.h
+ rm -f config.log config.status config.cache config.h
rm -f Makefile
realdistclean:: distclean
diff --git a/server/configure.ac b/server/configure.ac
index b334d8fae..1b01a2ec2 100644
--- a/server/configure.ac
+++ b/server/configure.ac
@@ -37,6 +37,8 @@ m4_include(libldb.m4)
m4_include(libevents.m4)
m4_include(util/signal.m4)
+PKG_CHECK_MODULES(DBUS,dbus-1)
+
AC_SUBST(TESTS)
AC_SUBST(EXTRA_OBJ)
diff --git a/server/dbus/sssd_dbus_client.c b/server/dbus/sssd_dbus_client.c
new file mode 100644
index 000000000..48f1ae456
--- /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);
+ }
+}
diff --git a/server/dbus/sssd_dbus_client.h b/server/dbus/sssd_dbus_client.h
new file mode 100644
index 000000000..8e1bc876f
--- /dev/null
+++ b/server/dbus/sssd_dbus_client.h
@@ -0,0 +1,67 @@
+#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
new file mode 100644
index 000000000..140d2f1a7
--- /dev/null
+++ b/server/dbus/sssd_dbus_common.c
@@ -0,0 +1,40 @@
+#include <sys/time.h>
+#include "dbus/sssd_dbus_common.h"
+#include "events.h"
+
+struct timeval _dbus_timeout_get_interval_tv(int interval) {
+ struct timeval tv;
+ struct timeval rightnow;
+
+ gettimeofday(&rightnow,NULL);
+
+ tv.tv_sec = interval / 1000 + rightnow.tv_sec;
+ tv.tv_usec = (interval % 1000) * 1000 + rightnow.tv_usec;
+ return tv;
+}
+
+/*
+ * remove_watch
+ * Hook for D-BUS to remove file descriptor-based events
+ * from the libevents mainloop
+ */
+void remove_watch(DBusWatch *watch, void *data) {
+ struct fd_event *fde;
+ fde = talloc_get_type(dbus_watch_get_data(watch), struct fd_event);
+
+ /* Freeing the event object will remove it from the event loop */
+ talloc_free(fde);
+}
+
+
+/*
+ * remove_timeout
+ * Hook for D-BUS to remove time-based events from the mainloop
+ */
+void remove_timeout(DBusTimeout *timeout, void *data) {
+ struct timed_event *te;
+ te = talloc_get_type(dbus_timeout_get_data(timeout), struct timed_event);
+
+ /* 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
new file mode 100644
index 000000000..e0683be8f
--- /dev/null
+++ b/server/dbus/sssd_dbus_common.h
@@ -0,0 +1,14 @@
+#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_server.c b/server/dbus/sssd_dbus_server.c
new file mode 100644
index 000000000..288a33338
--- /dev/null
+++ b/server/dbus/sssd_dbus_server.c
@@ -0,0 +1,210 @@
+/*
+ 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 <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"
+
+/*
+ * integrate_server_with_event_loop
+ * Set up a D-BUS server to use the libevents mainloop
+ * for handling file descriptor and timed events
+ */
+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;
+ }
+
+ /* 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;
+ }
+
+ 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;
+ }
+ 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"));
+}
+
+/*
+ * add_server_watch
+ * 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) {
+ unsigned int flags;
+ unsigned int event_flags;
+ struct dbus_server_toplevel_context *dt_ctx;
+ struct dbus_server_watch_context *svw_ctx;
+
+ if (!dbus_watch_get_enabled(watch)) {
+ return FALSE;
+ }
+
+ dt_ctx = talloc_get_type(data, struct dbus_server_toplevel_context);
+
+ svw_ctx = talloc_zero(dt_ctx, struct dbus_server_watch_context);
+ svw_ctx->top = dt_ctx;
+ svw_ctx->watch = watch;
+
+ flags = dbus_watch_get_flags(watch);
+ svw_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;
+ }
+ svw_ctx->fde = event_add_fd(svw_ctx->top->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);
+
+ return TRUE;
+}
+
+/*
+ * server_watch_toggled
+ * 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))
+ add_server_watch(watch, data);
+ else
+ remove_watch(watch, data);
+}
+
+/*
+ * 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) {
+ struct dbus_server_toplevel_context *dt_ctx;
+ struct dbus_server_timeout_context *svt_ctx;
+ struct timeval tv;
+
+ if (!dbus_timeout_get_enabled(timeout))
+ return TRUE;
+
+ dt_ctx = talloc_get_type(data, struct dbus_server_toplevel_context);
+
+ svt_ctx = talloc_zero(dt_ctx,struct dbus_server_timeout_context);
+ svt_ctx->top = dt_ctx;
+ svt_ctx->timeout = timeout;
+
+ 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);
+
+ /* Save the event to the watch object so it can be removed later */
+ dbus_timeout_set_data(svt_ctx->timeout,svt_ctx->te,NULL);
+
+ return TRUE;
+}
+
+/*
+ * server_timeout_toggled
+ * 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))
+ add_server_timeout(timeout, data);
+ else
+ remove_timeout(timeout, data);
+}
+
+/*
+ * dbus_server_read_write_handler
+ * Callback for D-BUS to handle messages on a file-descriptor
+ */
+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);
+
+ dbus_server_ref(svw_ctx->top->server);
+ if (flags & EVENT_FD_READ) {
+ dbus_watch_handle(svw_ctx->watch, DBUS_WATCH_READABLE);
+ }
+ if (flags & EVENT_FD_WRITE) {
+ dbus_watch_handle(svw_ctx->watch, DBUS_WATCH_WRITABLE);
+ }
+ dbus_server_ref(svw_ctx->top->server);
+}
+
+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);
+}
diff --git a/server/dbus/sssd_dbus_server.h b/server/dbus/sssd_dbus_server.h
new file mode 100644
index 000000000..85fc12c6a
--- /dev/null
+++ b/server/dbus/sssd_dbus_server.h
@@ -0,0 +1,69 @@
+/*
+ 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
new file mode 100644
index 000000000..8a82284c8
--- /dev/null
+++ b/server/dbus/tests/test_client.c
@@ -0,0 +1,123 @@
+#include <stdlib.h>
+#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"
+
+static void request_version_timed(struct event_context *ev,
+ DBusConnection *conn);
+
+static void print_version (DBusPendingCall *pending, void *ptr) {
+ DBusMessage *reply;
+ DBusError error;
+ const char *version_string;
+ int type;
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+ if (!reply) {
+ /* reply should never be null. This function shouldn't be called
+ * 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"));
+ 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)) {
+ fprintf(stdout, "Version: %s\n", version_string);
+ fflush(stdout);
+ }
+ else {
+ DEBUG(0, ("Error getting arguments in print_version"));
+ }
+ }
+ else if (type == DBUS_MESSAGE_TYPE_ERROR) {
+
+ }
+ else {
+ DEBUG(0, ("Received unexpected message"));
+ exit(4);
+ }
+}
+
+static void test_timed_handler(struct event_context *ev,
+ struct timed_event *te,
+ struct timeval t, void *ptr) {
+ DBusConnection *conn;
+ DBusPendingCall *pending_reply;
+ DBusMessage *version_request;
+ DBusError error;
+ conn = (DBusConnection *) ptr;
+
+ 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);
+
+ if(!dbus_connection_send_with_reply(conn, version_request, &pending_reply, -1)){
+ /* Critical failure */
+ DEBUG(0,("Failed to send version_request"));
+ exit(2);
+ }
+
+ dbus_pending_call_set_notify(pending_reply, print_version, NULL, NULL);
+
+ dbus_message_unref(version_request);
+
+ request_version_timed(ev,conn);
+}
+
+static void request_version_timed(struct event_context *ev, DBusConnection *conn) {
+ 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);
+ 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;
+ struct event_context *event_ctx;
+
+ event_ctx = event_context_init(talloc_autofree_context());
+
+ 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);
+ exit(1);
+ }
+
+ integrate_connection_with_event_loop(event_ctx,dbus_conn);
+ 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);
+
+ /* 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
diff --git a/server/monitor.c b/server/monitor.c
index 2d3283fd3..45b21cd56 100644
--- a/server/monitor.c
+++ b/server/monitor.c
@@ -27,12 +27,9 @@
#include "util/util.h"
#include "service.h"
#include "confdb/confdb.h"
-
-struct mt_ctx {
- struct event_context *ev;
- struct confdb_ctx *cdb;
- char **services;
-};
+#include "dbus/dbus.h"
+#include "dbus/sssd_dbus_server.h"
+#include "dbus/sssd_dbus_client.h"
struct mt_srv {
const char *name;
@@ -139,6 +136,11 @@ int start_monitor(TALLOC_CTX *mem_ctx,
return EINVAL;
}
+ /* Initialize D-BUS Server
+ * The monitor will act as a D-BUS server for all
+ * SSSD processes */
+ monitor_dbus_init(event_ctx);
+
for (i = 0; ctx->services[i]; i++) {
srv = talloc_zero(ctx, struct mt_srv);
@@ -160,3 +162,97 @@ int start_monitor(TALLOC_CTX *mem_ctx,
return EOK;
}
+
+
+/*
+ * monitor_dbus_init
+ * Set up the monitor service as a D-BUS Server
+ */
+int monitor_dbus_init(struct event_context *event_ctx) {
+ DBusError dbus_error;
+ DBusServer *dbus_server;
+
+ /* Set up D-BUS server */
+ dbus_error_init(&dbus_error);
+ dbus_server = dbus_server_listen(DBUS_ADDRESS, &dbus_error);
+ if (dbus_server == NULL) {
+ DEBUG(0,("Error: name=%s, message=%s\n", dbus_error.name,
+ dbus_error.message));
+ }
+
+ /* TODO: remove debug */
+ DEBUG(2,("Server listening on %s\n", dbus_server_get_address(dbus_server)));
+
+ integrate_server_with_event_loop(event_ctx, dbus_server, monitor_dbus_method_init);
+
+ return 0;
+}
+
+/* monitor_messsage_handler
+ * Receive messages and process them
+ */
+DBusHandlerResult monitor_message_handler(DBusConnection *conn,
+ DBusMessage *message, void *user_data) {
+ const char *method;
+ const char *path;
+ const char *msg_interface;
+ DBusMessage *reply = NULL;
+
+ 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, MONITOR_DBUS_INTERFACE) != 0)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ /* Validate the D-BUS path */
+ if (strcmp(path, MONITOR_DBUS_PATH) == 0) {
+ /* TODO Fill in methods */
+ if(strcmp(method,MONITOR_METHOD_VERSION) == 0) {
+ reply = dbus_get_monitor_version(message);
+ }
+ }
+
+ if(reply) {
+ dbus_connection_send(conn,reply, NULL);
+ dbus_message_unref(reply);
+ }
+
+ return reply ? DBUS_HANDLER_RESULT_HANDLED :
+ DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/* dbus_get_monitor_version
+ * Return the monitor version over D-BUS
+ */
+DBusMessage *dbus_get_monitor_version(DBusMessage *message) {
+ DBusMessage *reply;
+ const char *version = MONITOR_VERSION;
+
+ reply = dbus_message_new_method_return(message);
+ dbus_message_append_args(reply,DBUS_TYPE_STRING, &version, DBUS_TYPE_INVALID);
+
+ return reply;
+}
+
+/* monitor_dbus_method_init
+ * Initialize D-BUS methods on the monitor
+ * Sets up a callback to monitor_message_handler
+ */
+void monitor_dbus_method_init(DBusConnection *conn, struct event_context *event_ctx) {
+ DBusObjectPathVTable *monitor_vtable;
+ monitor_vtable = talloc_zero(event_ctx, DBusObjectPathVTable);
+
+ DEBUG (3,("Initializing D-BUS methods.\n"));
+ monitor_vtable->message_function = monitor_message_handler;
+
+ dbus_connection_register_object_path(
+ conn, MONITOR_DBUS_PATH,
+ monitor_vtable, event_ctx);
+
+ DEBUG(3,("D-BUS method initialization complete.\n"));
+}
diff --git a/server/monitor.h b/server/monitor.h
index 17094a851..074c5a81c 100644
--- a/server/monitor.h
+++ b/server/monitor.h
@@ -1,3 +1,30 @@
+#ifndef MONITOR_H_
+#define MONITOR_H_
+
+#include "talloc.h"
+#include "service_task.h"
+#include "dbus/dbus.h"
+
+#define MONITOR_VERSION "0.1"
+#define MONITOR_DBUS_INTERFACE "org.freeipa.sssd.monitor"
+#define MONITOR_DBUS_PATH "/org/freeipa/sssd/monitor"
+
+/* D-BUS Methods */
+#define MONITOR_METHOD_VERSION "getVersion"
+
+struct mt_ctx {
+ struct event_context *ev;
+ struct confdb_ctx *cdb;
+ char **services;
+};
+
int start_monitor(TALLOC_CTX *mem_ctx,
struct event_context *event_ctx,
struct confdb_ctx *cdb);
+int monitor_dbus_init(struct event_context *event_ctx);
+void monitor_dbus_method_init(DBusConnection *conn, struct event_context *event_ctx);
+DBusHandlerResult monitor_message_handler(DBusConnection *conn,
+ DBusMessage *message, void *user_data);
+DBusMessage *dbus_get_monitor_version(DBusMessage *message);
+
+#endif /* MONITOR_H */
diff --git a/server/server.mk b/server/server.mk
index 8558c7311..655b4fe31 100644
--- a/server/server.mk
+++ b/server/server.mk
@@ -1,4 +1,26 @@
-SERVER_OBJ = server.o monitor.o process.o service.o service_task.o util/debug.o util/signal.o util/become_daemon.o confdb/confdb.o nss/nsssrv.o nss/nsssrv_packet.o nss/nsssrv_cmd.o nss/nsssrv_ldb.o
+SERVER_OBJ = \
+ server.o \
+ monitor.o \
+ process.o \
+ service.o \
+ service_task.o \
+ util/debug.o \
+ util/signal.o \
+ util/become_daemon.o \
+ confdb/confdb.o \
+ nss/nsssrv.o \
+ nss/nsssrv_packet.o \
+ nss/nsssrv_cmd.o \
+ nss/nsssrv_ldb.o \
+ dbus/sssd_dbus_server.o \
+ dbus/sssd_dbus_client.o \
+ dbus/sssd_dbus_common.o
+
+CLIENT_OBJ = \
+ dbus/sssd_dbus_common.o \
+ dbus/sssd_dbus_client.o \
+ util/debug.o \
+ dbus/tests/test_client.o
install:: all
${INSTALLCMD} -d $(DESTDIR)$(sbindir)
@@ -10,3 +32,5 @@ clean::
sbin/sssd: $(SERVER_OBJ)
$(CC) -o sbin/sssd $(SERVER_OBJ) $(LDFLAGS) $(LIBS)
+sbin/sssd-dbus-client: $(CLIENT_OBJ)
+ $(CC) -o sbin/sssd-dbus-client $(CLIENT_OBJ) $(LDFLAGS) $(LIBS)