diff options
| -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;  } | 
