summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/sbus/sssd_dbus_common.c149
-rw-r--r--server/sbus/sssd_dbus_private.h12
2 files changed, 124 insertions, 37 deletions
diff --git a/server/sbus/sssd_dbus_common.c b/server/sbus/sssd_dbus_common.c
index 76cb3c20..1aec664d 100644
--- a/server/sbus/sssd_dbus_common.c
+++ b/server/sbus/sssd_dbus_common.c
@@ -8,6 +8,34 @@
/* =Watches=============================================================== */
+/* DBUS may ask us to add a watch to a file descriptor that already had a watch
+ * associated. Need to check if that's the case */
+static struct sbus_watch_ctx *fd_to_watch(struct sbus_watch_ctx *list, int fd)
+{
+ struct sbus_watch_ctx *watch_iter;
+
+ watch_iter = list;
+ while (watch_iter != NULL) {
+ if (watch_iter->fd == fd) {
+ return watch_iter;
+ }
+
+ watch_iter = watch_iter->next;
+ }
+
+ return NULL;
+}
+
+static int watch_destructor(void *mem)
+{
+ struct sbus_watch_ctx *watch;
+
+ watch = talloc_get_type(mem, struct sbus_watch_ctx);
+ DLIST_REMOVE(watch->conn->watch_list, watch);
+
+ return 0;
+}
+
/*
* watch_handler
* Callback for D-BUS to handle messages on a file-descriptor
@@ -34,12 +62,16 @@ static void sbus_watch_handler(struct tevent_context *ev,
/* Fire if readable */
if (flags & TEVENT_FD_READ) {
- dbus_watch_handle(watch->dbus_watch, DBUS_WATCH_READABLE);
+ if (watch->dbus_read_watch) {
+ dbus_watch_handle(watch->dbus_read_watch, DBUS_WATCH_READABLE);
+ }
}
/* Fire if writeable */
if (flags & TEVENT_FD_WRITE) {
- dbus_watch_handle(watch->dbus_watch, DBUS_WATCH_WRITABLE);
+ if (watch->dbus_write_watch) {
+ dbus_watch_handle(watch->dbus_write_watch, DBUS_WATCH_WRITABLE);
+ }
}
/* Release reference once done */
@@ -61,28 +93,49 @@ dbus_bool_t sbus_add_watch(DBusWatch *dbus_watch, void *data)
uint16_t event_flags;
struct sbus_connection *conn;
struct sbus_watch_ctx *watch;
+ dbus_bool_t enabled;
int fd;
conn = talloc_get_type(data, struct sbus_connection);
- watch = talloc_zero(conn, struct sbus_watch_ctx);
- if (!watch) {
- DEBUG(0, ("Outr of Memory!\n"));
- return FALSE;
- }
- watch->dbus_watch = dbus_watch;
- watch->conn = conn;
-
#ifdef HAVE_DBUS_WATCH_GET_UNIX_FD
fd = dbus_watch_get_unix_fd(dbus_watch);
#else
fd = dbus_watch_get_fd(dbus_watch);
#endif
+ watch = fd_to_watch(conn->watch_list, fd);
+ if (!watch) {
+ /* does not exist, allocate new one */
+ watch = talloc_zero(conn, struct sbus_watch_ctx);
+ if (!watch) {
+ DEBUG(0, ("Out of Memory!\n"));
+ return FALSE;
+ }
+ watch->conn = conn;
+ watch->fd = fd;
+ }
+
+ enabled = dbus_watch_get_enabled(dbus_watch);
flags = dbus_watch_get_flags(dbus_watch);
- event_flags = 0;
- if (dbus_watch_get_enabled(dbus_watch)) {
+ /* Save the event to the watch object so it can be found later */
+ if (flags & DBUS_WATCH_READABLE) {
+ watch->dbus_read_watch = dbus_watch;
+ }
+ if (flags & DBUS_WATCH_WRITABLE) {
+ watch->dbus_write_watch = dbus_watch;
+ }
+ dbus_watch_set_data(dbus_watch, watch, NULL);
+
+ if (watch->fde) {
+ /* pre-existing event, just toggle flags */
+ sbus_toggle_watch(dbus_watch, data);
+ return TRUE;
+ }
+
+ event_flags = 0;
+ if (enabled) {
if (flags & DBUS_WATCH_READABLE) {
event_flags |= TEVENT_FD_READ;
}
@@ -91,22 +144,24 @@ dbus_bool_t sbus_add_watch(DBusWatch *dbus_watch, void *data)
}
}
- DEBUG(8, ("%p: %d, %d=%s/%s\n",
- dbus_watch, fd, flags,
- ((event_flags & TEVENT_FD_READ)?"R":"-"),
- ((event_flags & TEVENT_FD_WRITE)?"W":"-")));
-
/* Add the file descriptor to the event loop */
watch->fde = tevent_add_fd(conn->ev,
watch, fd, event_flags,
sbus_watch_handler, watch);
if (!watch->fde) {
DEBUG(0, ("Failed to set up fd event!\n"));
+ talloc_zfree(watch);
return FALSE;
}
- /* Save the event to the watch object so it can be removed later */
- dbus_watch_set_data(dbus_watch, watch, NULL);
+ DLIST_ADD(conn->watch_list, watch);
+ talloc_set_destructor((TALLOC_CTX *)watch, watch_destructor);
+
+ DEBUG(8, ("%p/%p (%d), %s/%s (%s)\n",
+ watch, dbus_watch, fd,
+ ((flags & DBUS_WATCH_READABLE)?"R":"-"),
+ ((flags & DBUS_WATCH_WRITABLE)?"W":"-"),
+ enabled?"enabled":"disabled"));
return TRUE;
}
@@ -119,21 +174,23 @@ dbus_bool_t sbus_add_watch(DBusWatch *dbus_watch, void *data)
void sbus_toggle_watch(DBusWatch *dbus_watch, void *data)
{
struct sbus_watch_ctx *watch;
- uint16_t event_flags = 0;
unsigned int flags;
+ dbus_bool_t enabled;
void *watch_data;
+ int fd;
+
+ enabled = dbus_watch_get_enabled(dbus_watch);
+ flags = dbus_watch_get_flags(dbus_watch);
watch_data = dbus_watch_get_data(dbus_watch);
watch = talloc_get_type(watch_data, struct sbus_watch_ctx);
if (!watch) {
- DEBUG(0, ("Watch does not carry watch context?!\n"));
- /* TODO: abort ? */
+ DEBUG(2, ("[%p] does not carry watch context?!\n", dbus_watch));
+ /* abort ? */
return;
}
- flags = dbus_watch_get_flags(dbus_watch);
-
- if (dbus_watch_get_enabled(dbus_watch)) {
+ if (enabled) {
if (flags & DBUS_WATCH_READABLE) {
TEVENT_FD_READABLE(watch->fde);
}
@@ -150,12 +207,17 @@ void sbus_toggle_watch(DBusWatch *dbus_watch, void *data)
}
if (debug_level >= 8) {
- event_flags = tevent_fd_get_flags(watch->fde);
+#ifdef HAVE_DBUS_WATCH_GET_UNIX_FD
+ fd = dbus_watch_get_unix_fd(dbus_watch);
+#else
+ fd = dbus_watch_get_fd(dbus_watch);
+#endif
}
- DEBUG(8, ("%p: %p, %d=%s/%s\n",
- dbus_watch, watch, flags,
- ((event_flags & TEVENT_FD_READ)?"R":"-"),
- ((event_flags & TEVENT_FD_WRITE)?"W":"-")));
+ DEBUG(8, ("%p/%p (%d), %s/%s (%s)\n",
+ watch, dbus_watch, fd,
+ ((flags & DBUS_WATCH_READABLE)?"R":"-"),
+ ((flags & DBUS_WATCH_WRITABLE)?"W":"-"),
+ enabled?"enabled":"disabled"));
}
/*
@@ -165,17 +227,32 @@ void sbus_toggle_watch(DBusWatch *dbus_watch, void *data)
*/
void sbus_remove_watch(DBusWatch *dbus_watch, void *data)
{
- void *watch;
+ struct sbus_watch_ctx *watch;
+ void *watch_data;
+
+ watch_data = dbus_watch_get_data(dbus_watch);
+ watch = talloc_get_type(watch_data, struct sbus_watch_ctx);
- DEBUG(8, ("%p\n", dbus_watch));
+ DEBUG(8, ("%p/%p\n", watch, dbus_watch));
- watch = dbus_watch_get_data(dbus_watch);
+ if (!watch) {
+ DEBUG(2, ("DBUS trying to remove unknown watch!\n"));
+ return;
+ }
/* remove dbus watch data */
dbus_watch_set_data(dbus_watch, NULL, NULL);
- /* Freeing the event object will remove it from the event loop */
- talloc_free(watch);
+ /* check which watch to remove, or free if none left */
+ if (watch->dbus_read_watch == dbus_watch) {
+ watch->dbus_read_watch = NULL;
+ }
+ if (watch->dbus_write_watch == dbus_watch) {
+ watch->dbus_write_watch = NULL;
+ }
+ if (!watch->dbus_read_watch && !watch->dbus_write_watch) {
+ talloc_free(watch);
+ }
}
/* =Timeouts============================================================== */
@@ -225,7 +302,7 @@ dbus_bool_t sbus_add_timeout(DBusTimeout *dbus_timeout, void *data)
timeout = talloc_zero(conn, struct sbus_timeout_ctx);
if (!timeout) {
- DEBUG(0, ("Outr of Memory!\n"));
+ DEBUG(0, ("Out of Memory!\n"));
return FALSE;
}
timeout->dbus_timeout = dbus_timeout;
diff --git a/server/sbus/sssd_dbus_private.h b/server/sbus/sssd_dbus_private.h
index 79cae230..1f6578c2 100644
--- a/server/sbus/sssd_dbus_private.h
+++ b/server/sbus/sssd_dbus_private.h
@@ -11,6 +11,7 @@ enum dbus_conn_type {
};
struct sbus_interface_p;
+struct sbus_watch_ctx;
struct sbus_connection {
struct tevent_context *ev;
@@ -39,14 +40,23 @@ struct sbus_connection {
struct sbus_interface *server_intf;
sbus_server_conn_init_fn srv_init_fn;
void *srv_init_data;
+
+ /* watches list */
+ struct sbus_watch_ctx *watch_list;
};
/* =Watches=============================================================== */
struct sbus_watch_ctx {
- DBusWatch *dbus_watch;
+ struct sbus_watch_ctx *prev, *next;
+
struct sbus_connection *conn;
+
struct tevent_fd *fde;
+ int fd;
+
+ DBusWatch *dbus_read_watch;
+ DBusWatch *dbus_write_watch;
};
dbus_bool_t sbus_add_watch(DBusWatch *watch, void *data);