summaryrefslogtreecommitdiffstats
path: root/server/dbus/sssd_dbus_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/dbus/sssd_dbus_server.c')
-rw-r--r--server/dbus/sssd_dbus_server.c300
1 files changed, 209 insertions, 91 deletions
diff --git a/server/dbus/sssd_dbus_server.c b/server/dbus/sssd_dbus_server.c
index 288a33338..113866fa6 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;
}