diff options
Diffstat (limited to 'common/dbus.c')
-rw-r--r-- | common/dbus.c | 123 |
1 files changed, 81 insertions, 42 deletions
diff --git a/common/dbus.c b/common/dbus.c index 17f340b6..1b5f7db8 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -80,19 +80,27 @@ struct name_callback { }; struct name_data { + DBusConnection *connection; char *name; GSList *callbacks; }; -static struct name_data *name_data_find(const char *name) +static struct name_data *name_data_find(DBusConnection *connection, + const char *name) { GSList *current; for (current = name_listeners; current != NULL; current = current->next) { struct name_data *data = current->data; - if (strcmp(name, data->name) == 0) - return data; + + if (name == NULL && data->name == NULL) { + if (connection == data->connection) + return data; + } else { + if (strcmp(name, data->name) == 0) + return data; + } } return NULL; @@ -112,6 +120,22 @@ static struct name_callback *name_callback_find(GSList *callbacks, return NULL; } +static void name_data_call_and_free(struct name_data *data) +{ + GSList *l; + + for (l = data->callbacks; l != NULL; l = l->next) { + struct name_callback *cb = l->data; + if (cb->func) + cb->func(data->name, cb->user_data); + g_free(cb); + } + + g_slist_free(data->callbacks); + g_free(data->name); + g_free(data); +} + static void name_data_free(struct name_data *data) { GSList *l; @@ -124,7 +148,8 @@ static void name_data_free(struct name_data *data) g_free(data); } -static int name_data_add(const char *name, name_cb_t func, void *user_data) +static int name_data_add(DBusConnection *connection, + const char *name, name_cb_t func, void *user_data) { int first = 1; struct name_data *data = NULL; @@ -135,7 +160,7 @@ static int name_data_add(const char *name, name_cb_t func, void *user_data) cb->func = func; cb->user_data = user_data; - data = name_data_find(name); + data = name_data_find(connection, name); if (data) { first = 0; goto done; @@ -143,6 +168,7 @@ static int name_data_add(const char *name, name_cb_t func, void *user_data) data = g_new0(struct name_data, 1); + data->connection = connection; data->name = g_strdup(name); name_listeners = g_slist_append(name_listeners, data); @@ -152,12 +178,13 @@ done: return first; } -static void name_data_remove(const char *name, name_cb_t func, void *user_data) +static void name_data_remove(DBusConnection *connection, + const char *name, name_cb_t func, void *user_data) { struct name_data *data; struct name_callback *cb = NULL; - data = name_data_find(name); + data = name_data_find(connection, name); if (!data) return; @@ -197,7 +224,7 @@ static DBusHandlerResult name_exit_filter(DBusConnection *connection, if (*new != '\0') return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - data = name_data_find(name); + data = name_data_find(connection, name); if (!data) { error("Got NameOwnerChanged signal for %s which has no listeners", name); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -222,56 +249,51 @@ int name_listener_add(DBusConnection *connection, const char *name, int first; if (!name_listener_initialized) { - if (!dbus_connection_add_filter(connection, name_exit_filter, NULL, NULL)) { + if (!dbus_connection_add_filter(connection, + name_exit_filter, NULL, NULL)) { error("dbus_connection_add_filter() failed"); return -1; } name_listener_initialized = 1; } - if (!name) - return -1; - - first = name_data_add(name, func, user_data); + first = name_data_add(connection, name, func, user_data); /* The filter is already added if this is not the first callback * registration for the name */ if (!first) return 0; - debug("name_listener_add(%s)", name); + if (name) { + debug("name_listener_add(%s)", name); - snprintf(match_string, sizeof(match_string), - "interface=%s,member=NameOwnerChanged,arg0=%s", - DBUS_INTERFACE_DBUS, name); + snprintf(match_string, sizeof(match_string), + "interface=%s,member=NameOwnerChanged,arg0=%s", + DBUS_INTERFACE_DBUS, name); - dbus_error_init(&err); - dbus_bus_add_match(connection, match_string, &err); + dbus_error_init(&err); + dbus_bus_add_match(connection, match_string, &err); - if (dbus_error_is_set(&err)) { - error("Adding match rule \"%s\" failed: %s", match_string, - err.message); - dbus_error_free(&err); - name_data_remove(name, func, user_data); - return -1; + if (dbus_error_is_set(&err)) { + error("Adding match rule \"%s\" failed: %s", + match_string, err.message); + dbus_error_free(&err); + name_data_remove(connection, name, func, user_data); + return -1; + } } return 0; } int name_listener_remove(DBusConnection *connection, const char *name, - name_cb_t func, void *user_data) + name_cb_t func, void *user_data) { struct name_data *data; struct name_callback *cb; DBusError err; char match_string[128]; - if (!name) - return -1; - - debug("name_listener_remove(%s)", name); - - data = name_data_find(name); + data = name_data_find(connection, name); if (!data) { error("remove_name_listener: no listener for %s", name); return -1; @@ -290,27 +312,44 @@ int name_listener_remove(DBusConnection *connection, const char *name, if (data->callbacks) return 0; - snprintf(match_string, sizeof(match_string), - "interface=%s,member=NameOwnerChanged,arg0=%s", - DBUS_INTERFACE_DBUS, name); + if (name) { + debug("name_listener_remove(%s)", name); - dbus_error_init(&err); - dbus_bus_remove_match(connection, match_string, &err); + snprintf(match_string, sizeof(match_string), + "interface=%s,member=NameOwnerChanged,arg0=%s", + DBUS_INTERFACE_DBUS, name); - if (dbus_error_is_set(&err)) { - error("Removing owner match rule for %s failed: %s", + dbus_error_init(&err); + + dbus_bus_remove_match(connection, match_string, &err); + + if (dbus_error_is_set(&err)) { + error("Removing owner match rule for %s failed: %s", name, err.message); - dbus_error_free(&err); - return -1; + dbus_error_free(&err); + return -1; + } } - name_data_remove(name, func, user_data); + name_data_remove(connection, name, func, user_data); return 0; } int name_listener_indicate_disconnect(DBusConnection *connection) { + struct name_data *data; + + data = name_data_find(connection, NULL); + if (!data) { + error("name_listener_indicate_disconnect: no listener found"); + return -1; + } + + debug("name_listener_indicate_disconnect"); + + name_data_call_and_free(data); + return 0; } |