diff options
| author | Marcel Holtmann <marcel@holtmann.org> | 2008-05-08 20:23:45 +0000 | 
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2008-05-08 20:23:45 +0000 | 
| commit | e7d668ac9e813bc9922ee7d771848bd8822d5d1f (patch) | |
| tree | 34e2fc7b1c064beaa52e5e05e9278be458be9fba /common/dbus.c | |
| parent | 44a204a75880c342c3ac9066072f102f773a539a (diff) | |
Move D-Bus watch functions into libgdbus
Diffstat (limited to 'common/dbus.c')
| -rw-r--r-- | common/dbus.c | 391 | 
1 files changed, 0 insertions, 391 deletions
diff --git a/common/dbus.c b/common/dbus.c deleted file mode 100644 index 4ea56c9f..00000000 --- a/common/dbus.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * - *  BlueZ - Bluetooth protocol stack for Linux - * - *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org> - * - * - *  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 2 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, write to the Free Software - *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <stdint.h> - -#include <glib.h> - -#include <dbus/dbus.h> - -#ifdef NEED_DBUS_WATCH_GET_UNIX_FD -#define dbus_watch_get_unix_fd dbus_watch_get_fd -#endif - -#ifdef HAVE_DBUS_GLIB -#include <dbus/dbus-glib-lowlevel.h> -#endif - -#include "dbus.h" -#include "logging.h" - -static guint listener_id = 0; -static GSList *name_listeners = NULL; - -struct name_callback { -	name_cb_t func; -	void *user_data; -	guint id; -}; - -struct name_data { -	DBusConnection *connection; -	char *name; -	GSList *callbacks; -}; - -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 (name == NULL && data->name == NULL) { -			if (connection == data->connection) -				return data; -		} else { -			if (strcmp(name, data->name) == 0) -				return data; -		} -	} - -	return NULL; -} - -static struct name_callback *name_callback_find(GSList *callbacks, -					name_cb_t func, void *user_data) -{ -	GSList *current; - -	for (current = callbacks; current != NULL; current = current->next) { -		struct name_callback *cb = current->data; -		if (cb->func == func && cb->user_data == user_data) -			return cb; -	} - -	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; - -	for (l = data->callbacks; l != NULL; l = l->next) -		g_free(l->data); - -	g_slist_free(data->callbacks); -	g_free(data->name); -	g_free(data); -} - -static int name_data_add(DBusConnection *connection, const char *name, -				name_cb_t func, void *user_data, guint id) -{ -	int first = 1; -	struct name_data *data = NULL; -	struct name_callback *cb = NULL; - -	cb = g_new(struct name_callback, 1); - -	cb->func = func; -	cb->user_data = user_data; -	cb->id = id; - -	data = name_data_find(connection, name); -	if (data) { -		first = 0; -		goto done; -	} - -	data = g_new0(struct name_data, 1); - -	data->connection = connection; -	data->name = g_strdup(name); - -	name_listeners = g_slist_append(name_listeners, data); - -done: -	data->callbacks = g_slist_append(data->callbacks, cb); -	return first; -} - -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(connection, name); -	if (!data) -		return; - -	cb = name_callback_find(data->callbacks, func, user_data); -	if (cb) { -		data->callbacks = g_slist_remove(data->callbacks, cb); -		g_free(cb); -	} - -	if (!data->callbacks) { -		name_listeners = g_slist_remove(name_listeners, data); -		name_data_free(data); -	} -} - -static gboolean add_match(DBusConnection *connection, const char *name) -{ -	DBusError err; -	char match_string[128]; - -	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); - -	if (dbus_error_is_set(&err)) { -		error("Adding match rule \"%s\" failed: %s", match_string, -				err.message); -		dbus_error_free(&err); -		return FALSE; -	} - -	return TRUE; -} - -static gboolean remove_match(DBusConnection *connection, const char *name) -{ -	DBusError err; -	char match_string[128]; - -	snprintf(match_string, sizeof(match_string), -			"interface=%s,member=NameOwnerChanged,arg0=%s", -			DBUS_INTERFACE_DBUS, name); - -	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 FALSE; -	} - -	return TRUE; -} - -static DBusHandlerResult name_exit_filter(DBusConnection *connection, -					DBusMessage *message, void *user_data) -{ -	GSList *l; -	struct name_data *data; -	char *name, *old, *new; - -	if (!dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, -							"NameOwnerChanged")) -		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - -	if (!dbus_message_get_args(message, NULL, -				DBUS_TYPE_STRING, &name, -				DBUS_TYPE_STRING, &old, -				DBUS_TYPE_STRING, &new, -				DBUS_TYPE_INVALID)) { -		error("Invalid arguments for NameOwnerChanged signal"); -		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -	} - -	/* We are not interested of service creations */ -	if (*new != '\0') -		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - -	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; -	} - -	for (l = data->callbacks; l != NULL; l = l->next) { -		struct name_callback *cb = l->data; -		cb->func(name, cb->user_data); -	} - -	name_listeners = g_slist_remove(name_listeners, data); -	name_data_free(data); - -	remove_match(connection, name); - -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -guint name_listener_add(DBusConnection *connection, const char *name, -					name_cb_t func, void *user_data) -{ -	int first; - -	if (!listener_id) { -		if (!dbus_connection_add_filter(connection, -					name_exit_filter, NULL, NULL)) { -			error("dbus_connection_add_filter() failed"); -			return 0; -		} -	} - -	listener_id++; -	first = name_data_add(connection, name, func, user_data, listener_id); -	/* The filter is already added if this is not the first callback -	 * registration for the name */ -	if (!first) -		return listener_id; - -	if (name) { -		debug("name_listener_add(%s)", name); - -		if (!add_match(connection, name)) { -			name_data_remove(connection, name, func, user_data); -			return 0; -		} -	} - -	return listener_id; -} - -int name_listener_remove(DBusConnection *connection, const char *name, -					name_cb_t func, void *user_data) -{ -	struct name_data *data; -	struct name_callback *cb; - -	data = name_data_find(connection, name); -	if (!data) { -		error("remove_name_listener: no listener for %s", name); -		return -1; -	} - -	cb = name_callback_find(data->callbacks, func, user_data); -	if (!cb) { -		error("No matching callback found for %s", name); -		return -1; -	} - -	data->callbacks = g_slist_remove(data->callbacks, cb); -	g_free(cb); - -	/* Don't remove the filter if other callbacks exist */ -	if (data->callbacks) -		return 0; - -	if (name) { -		debug("name_listener_remove(%s)", name); - -		if (!remove_match(connection, name)) -			return -1; -	} - -	name_data_remove(connection, name, func, user_data); - -	return 0; -} - -gboolean name_listener_id_remove(guint id) -{ -	struct name_data *data; -	struct name_callback *cb; -	GSList *ldata, *lcb; - -	for (ldata = name_listeners; ldata; ldata = ldata->next) { -		data = ldata->data; -		for (lcb = data->callbacks; lcb; lcb = lcb->next) { -			cb = lcb->data; -			if (cb->id == id) -				goto remove; -		} -	} - -	return FALSE; - -remove: -	data->callbacks = g_slist_remove(data->callbacks, cb); -	g_free(cb); - -	/* Don't remove the filter if other callbacks exist */ -	if (data->callbacks) -		return TRUE; - -	if (data->name) { -		if (!remove_match(data->connection, data->name)) -			return FALSE; -	} - -	name_listeners = g_slist_remove(name_listeners, data); -	name_data_free(data); - -	return TRUE; -} - -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; -}  | 
