diff options
| -rw-r--r-- | common/dbus.c | 385 | ||||
| -rw-r--r-- | common/dbus.h | 11 | ||||
| -rw-r--r-- | cups/Makefile.am | 4 | ||||
| -rw-r--r-- | cups/main.c | 5 | ||||
| -rw-r--r-- | daemon/Makefile.am | 16 | ||||
| -rw-r--r-- | daemon/echo.c | 448 | ||||
| -rw-r--r-- | daemon/echo.service | 4 | ||||
| -rw-r--r-- | daemon/main.c | 5 | ||||
| -rw-r--r-- | gdbus/gdbus.h | 21 | ||||
| -rw-r--r-- | gdbus/mainloop.c | 280 | ||||
| -rw-r--r-- | hcid/dbus-common.c | 5 | 
11 files changed, 316 insertions, 868 deletions
| diff --git a/common/dbus.c b/common/dbus.c index beb97a07..4ea56c9f 100644 --- a/common/dbus.c +++ b/common/dbus.c @@ -48,35 +48,9 @@  #include "dbus.h"  #include "logging.h" -#define DISPATCH_TIMEOUT	0 -  static guint listener_id = 0;  static GSList *name_listeners = NULL; -#ifndef HAVE_DBUS_GLIB -typedef struct { -	uint32_t id; -	DBusTimeout *timeout; -} timeout_handler_t; - -struct watch_info { -	guint watch_id; -	GIOChannel *io; -	DBusConnection *conn; -}; - -struct server_info { -	guint watch_id; -	GIOChannel *io; -	DBusServer *server; -}; -#endif - -struct disconnect_data { -	void (*disconnect_cb)(void *); -	void *user_data; -}; -  struct name_callback {  	name_cb_t func;  	void *user_data; @@ -415,362 +389,3 @@ int name_listener_indicate_disconnect(DBusConnection *connection)  	return 0;  } - -static DBusHandlerResult disconnect_filter(DBusConnection *conn, -						DBusMessage *msg, void *data) -{ -	struct disconnect_data *dc_data = data; - -	if (dbus_message_is_signal(msg, -			DBUS_INTERFACE_LOCAL, "Disconnected") == TRUE) { -		error("Got disconnected from the system message bus"); -		dbus_connection_unref(conn); -		dc_data->disconnect_cb(dc_data->user_data); -	} - -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -#ifndef HAVE_DBUS_GLIB -static dbus_int32_t server_slot = -1; - -static gboolean server_func(GIOChannel *chan, GIOCondition cond, gpointer data) -{ -	DBusWatch *watch = data; -	int flags = 0; - -	if (cond & G_IO_IN)  flags |= DBUS_WATCH_READABLE; -	if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; -	if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP; -	if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR; - -	dbus_watch_handle(watch, flags); - -	return TRUE; -} - -static dbus_bool_t add_server(DBusWatch *watch, void *data) -{ -	GIOCondition cond = G_IO_HUP | G_IO_ERR; -	DBusServer *server = data; -	struct server_info *info; -	int fd, flags; - -	if (!dbus_watch_get_enabled(watch)) -		return TRUE; - -	info = g_new(struct server_info, 1); - -	fd = dbus_watch_get_unix_fd(watch); -	info->io = g_io_channel_unix_new(fd); -	info->server = dbus_server_ref(server); - -	dbus_watch_set_data(watch, info, NULL); - -	flags = dbus_watch_get_flags(watch); - -	if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN; -	if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT; - -	info->watch_id = g_io_add_watch(info->io, cond, server_func, watch); - -	return TRUE; -} - -static void remove_server(DBusWatch *watch, void *data) -{ -	struct server_info *info = dbus_watch_get_data(watch); - -	dbus_watch_set_data(watch, NULL, NULL); - -	if (info) { -		g_source_remove(info->watch_id); -		g_io_channel_unref(info->io); -		dbus_server_unref(info->server); -		g_free(info); -	} -} - -static void server_toggled(DBusWatch *watch, void *data) -{ -	/* Because we just exit on OOM, enable/disable is -	 * no different from add/remove */ -	if (dbus_watch_get_enabled(watch)) -		add_server(watch, data); -	else -		remove_server(watch, data); -} - -static gboolean message_dispatch_cb(void *data) -{ -	DBusConnection *connection = data; - -	dbus_connection_ref(connection); - -	/* Dispatch messages */ -	while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS); - -	dbus_connection_unref(connection); - -	return FALSE; -} - -static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data) -{ -	DBusWatch *watch = data; -	struct watch_info *info = dbus_watch_get_data(watch); -	int flags = 0; - -	if (cond & G_IO_IN)  flags |= DBUS_WATCH_READABLE; -	if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; -	if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP; -	if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR; - -	dbus_watch_handle(watch, flags); - -	if (dbus_connection_get_dispatch_status(info->conn) == DBUS_DISPATCH_DATA_REMAINS) -		g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, info->conn); - -	return TRUE; -} - -static dbus_bool_t add_watch(DBusWatch *watch, void *data) -{ -	GIOCondition cond = G_IO_HUP | G_IO_ERR; -	DBusConnection *conn = data; -	struct watch_info *info; -	int fd, flags; - -	if (!dbus_watch_get_enabled(watch)) -		return TRUE; - -	info = g_new(struct watch_info, 1); - -	fd = dbus_watch_get_unix_fd(watch); -	info->io = g_io_channel_unix_new(fd); -	info->conn = dbus_connection_ref(conn); - -	dbus_watch_set_data(watch, info, NULL); - -	flags = dbus_watch_get_flags(watch); - -	if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN; -	if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT; - -	info->watch_id = g_io_add_watch(info->io, cond, watch_func, watch); - -	return TRUE; -} - -static void remove_watch(DBusWatch *watch, void *data) -{ -	struct watch_info *info = dbus_watch_get_data(watch); - -	dbus_watch_set_data(watch, NULL, NULL); - -	if (info) { -		g_source_remove(info->watch_id); -		g_io_channel_unref(info->io); -		dbus_connection_unref(info->conn); -		g_free(info); -	} -} - -static void watch_toggled(DBusWatch *watch, void *data) -{ -	/* Because we just exit on OOM, enable/disable is -	 * no different from add/remove */ -	if (dbus_watch_get_enabled(watch)) -		add_watch(watch, data); -	else -		remove_watch(watch, data); -} - -static gboolean timeout_handler_dispatch(gpointer data) -{ -	timeout_handler_t *handler = data; - -	/* if not enabled should not be polled by the main loop */ -	if (dbus_timeout_get_enabled(handler->timeout) != TRUE) -		return FALSE; - -	dbus_timeout_handle(handler->timeout); - -	return FALSE; -} - -static void timeout_handler_free(void *data) -{ -	timeout_handler_t *handler = data; -	if (!handler) -		return; - -	g_source_remove(handler->id); -	g_free(handler); -} - -static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) -{ -	timeout_handler_t *handler; - -	if (!dbus_timeout_get_enabled(timeout)) -		return TRUE; - -	handler = g_new0(timeout_handler_t, 1); - -	handler->timeout = timeout; -	handler->id = g_timeout_add(dbus_timeout_get_interval(timeout), -					timeout_handler_dispatch, handler); - -	dbus_timeout_set_data(timeout, handler, timeout_handler_free); - -	return TRUE; -} - -static void remove_timeout(DBusTimeout *timeout, void *data) -{ -} - -static void timeout_toggled(DBusTimeout *timeout, void *data) -{ -	if (dbus_timeout_get_enabled(timeout)) -		add_timeout(timeout, data); -	else -		remove_timeout(timeout, data); -} - -static void dispatch_status_cb(DBusConnection *conn, -				DBusDispatchStatus new_status, void *data) -{ -	if (!dbus_connection_get_is_connected(conn)) -		return; - -	if (new_status == DBUS_DISPATCH_DATA_REMAINS) -		g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data); -} -#endif - -void setup_dbus_server_with_main_loop(DBusServer *server) -{ -#ifdef HAVE_DBUS_GLIB -	debug("Using D-Bus GLib server setup"); - -	dbus_server_setup_with_g_main(server, NULL); -#else -	dbus_server_allocate_data_slot(&server_slot); -	if (server_slot < 0) -		return; - -	dbus_server_set_data(server, server_slot, server, NULL); - -	dbus_server_set_watch_functions(server, add_server, remove_server, -						server_toggled, server, NULL); - -	dbus_server_set_timeout_functions(server, add_timeout, remove_timeout, -						timeout_toggled, server, NULL); -#endif -} - -void setup_dbus_with_main_loop(DBusConnection *conn) -{ -#ifdef HAVE_DBUS_GLIB -	debug("Using D-Bus GLib connection setup"); - -	dbus_connection_setup_with_g_main(conn, NULL); -#else -	dbus_connection_set_watch_functions(conn, add_watch, remove_watch, -						watch_toggled, conn, NULL); - -	dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, -						timeout_toggled, conn, NULL); - -	dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb, -								conn, NULL); -#endif -} - -DBusConnection *init_dbus(const char *name, -				void (*disconnect_cb)(void *), void *user_data) -{ -	struct disconnect_data *dc_data; -	DBusConnection *conn; -	DBusError err; - -	dbus_error_init(&err); - -	conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - -	if (dbus_error_is_set(&err)) { -		error("Can't connect to system message bus: %s", err.message); -		dbus_error_free(&err); -		return NULL; -	} - -	setup_dbus_with_main_loop(conn); - -	if (name) { -		dbus_error_init(&err); - -		if (dbus_bus_request_name(conn, name, 0, &err) != -				DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) { -			error("Could not become the primary owner of %s", name); -			dbus_connection_unref(conn); -			return NULL; -		} - -		if (dbus_error_is_set(&err)) { -			error("Can't get bus name %s: %s", name, err.message); -			dbus_error_free(&err); -			dbus_connection_unref(conn); -			return NULL; -		} -	} - -	if (!disconnect_cb) -		return conn; - -	dc_data = g_new(struct disconnect_data, 1); - -	dc_data->disconnect_cb = disconnect_cb; -	dc_data->user_data = user_data; - -	dbus_connection_set_exit_on_disconnect(conn, FALSE); - -	if (!dbus_connection_add_filter(conn, disconnect_filter, -				dc_data, g_free)) { -		error("Can't add D-Bus disconnect filter"); -		g_free(dc_data); -		dbus_connection_unref(conn); -		return NULL; -	} - -	return conn; -} - -DBusConnection *init_dbus_direct(const char *address) -{ -	DBusConnection *conn; -	DBusError err; - -	dbus_error_init(&err); - -	conn = dbus_connection_open(address, &err); - -	if (dbus_error_is_set(&err)) { -		error("Can't connect to message server: %s", err.message); -		dbus_error_free(&err); -		return NULL; -	} - -	setup_dbus_with_main_loop(conn); - -	dbus_connection_set_exit_on_disconnect(conn, FALSE); - -	return conn; -} - -DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, -				void (*disconnect_cb)(void *), void *user_data) -{ -	return init_dbus(name, disconnect_cb, user_data); -} diff --git a/common/dbus.h b/common/dbus.h index 94244eb6..5976a479 100644 --- a/common/dbus.h +++ b/common/dbus.h @@ -27,17 +27,6 @@  #include <dbus/dbus.h>  #include <glib.h> -void setup_dbus_server_with_main_loop(DBusServer *server); -void setup_dbus_with_main_loop(DBusConnection *conn); - -DBusConnection *init_dbus(const char *name, -				void (*disconnect_cb)(void *), void *user_data); - -DBusConnection *init_dbus_direct(const char *address); - -DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, -				void (*disconnect_cb)(void *), void *user_data); -  typedef void (*name_cb_t)(const char *name, void *user_data);  guint name_listener_add(DBusConnection *connection, const char *name, diff --git a/cups/Makefile.am b/cups/Makefile.am index 853c436d..f01665ee 100644 --- a/cups/Makefile.am +++ b/cups/Makefile.am @@ -7,10 +7,10 @@ cups_PROGRAMS = bluetooth  bluetooth_SOURCES = main.c cups.h sdp.c spp.c hcrp.c  bluetooth_LDADD = $(top_builddir)/common/libhelper.a \ -			@DBUS_LIBS@ @GLIB_LIBS@ @BLUEZ_LIBS@  +		@GDBUS_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@   endif -AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ +AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@  INCLUDES = -I$(top_srcdir)/common diff --git a/cups/main.c b/cups/main.c index ac77e85d..b36b2074 100644 --- a/cups/main.c +++ b/cups/main.c @@ -38,10 +38,9 @@  #include <bluetooth/sdp.h>  #include <bluetooth/sdp_lib.h> -#include <glib.h> +#include <gdbus.h>  #include "cups.h" -#include "dbus.h"  #include "sdp-xml.h"  extern int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel); @@ -456,7 +455,7 @@ static gboolean list_printers(void)  	char *adapter, *match;  	guint len; -	conn = init_dbus(NULL, NULL, NULL); +	conn = dbus_bus_system_setup_with_main_loop("org.bluez", NULL, NULL);  	if (conn == NULL)  		return FALSE; diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 8b2bba31..e2a16be2 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -1,12 +1,5 @@ -noinst_PROGRAMS = bluetoothd passkey-agent auth-agent \ -					bluetoothd-service-echo - -bluetoothd_service_echo_SOURCES = echo.c - -bluetoothd_service_echo_LDADD = \ -	$(top_builddir)/common/libhelper.a \ -	@GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ +noinst_PROGRAMS = bluetoothd passkey-agent auth-agent  if CONFIGFILES  dbusdir = $(sysconfdir)/dbus-1/system.d @@ -21,7 +14,7 @@ bluetoothd_SOURCES = main.c system.h \  bluetoothd_LDADD = \  	$(top_builddir)/common/libhelper.a \  	$(top_builddir)/sdpd/libsdpserver.a \ -	@GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ +	@GDBUS_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@  passkey_agent_SOURCES = passkey-agent.c @@ -31,11 +24,10 @@ auth_agent_SOURCES = auth-agent.c  auth_agent_LDADD = @DBUS_LIBS@ -AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ +AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@  INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/sdpd -EXTRA_DIST = bluetooth.conf echo.service \ -			test-manager test-database +EXTRA_DIST = bluetooth.conf test-manager test-database  MAINTAINERCLEANFILES = Makefile.in diff --git a/daemon/echo.c b/daemon/echo.c deleted file mode 100644 index 09ceef31..00000000 --- a/daemon/echo.c +++ /dev/null @@ -1,448 +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 <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <sys/socket.h> - -#include <bluetooth/bluetooth.h> -#include <bluetooth/rfcomm.h> -#include <bluetooth/sdp.h> -#include <bluetooth/sdp_lib.h> - -#include <glib.h> - -#include <dbus/dbus.h> - -#include "dbus.h" -#include "logging.h" - -struct auth_data { -	DBusConnection *conn; -	GIOChannel *io; -	char *address; -}; - -static gboolean session_event(GIOChannel *chan, -					GIOCondition cond, gpointer data) -{ -	unsigned char buf[672]; -	gsize len, written; -	GIOError err; - -	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) -		return FALSE; - -	err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); -	if (err == G_IO_ERROR_AGAIN) -		return TRUE; - -	g_io_channel_write(chan, (const gchar *) buf, len, &written); - -	return TRUE; -} - -static void cancel_authorization(DBusConnection *conn, const char *address) -{ -	DBusMessage *msg; -	const char *string = ""; - -	info("Canceling authorization for %s", address); - -	msg = dbus_message_new_method_call("org.bluez", "/org/bluez", -			"org.bluez.Database", "CancelAuthorizationRequest"); -	if (!msg) { -		error("Allocation of method message failed"); -		return; -	} - -	dbus_message_append_args(msg, DBUS_TYPE_STRING, &address, -				DBUS_TYPE_STRING, &string, DBUS_TYPE_INVALID); - -	dbus_connection_send(conn, msg, NULL); - -	dbus_message_unref(msg); -} - -static void authorization_callback(DBusPendingCall *call, void *data) -{ -	DBusMessage *reply = dbus_pending_call_steal_reply(call); -	struct auth_data *auth = data; -	DBusError err; - -	dbus_error_init(&err); - -	if (dbus_set_error_from_message(&err, reply)) { -		error("Access denied: %s", err.message); -		if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) -			cancel_authorization(auth->conn, auth->address); -		dbus_error_free(&err); -	} else { -		info("Accepting incoming connection"); -		g_io_add_watch(auth->io, -				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, -							session_event, NULL); -	} - -	g_io_channel_unref(auth->io); - -	dbus_message_unref(reply); -} - -static void authorization_free(void *data) -{ -	struct auth_data *auth = data; - -	g_free(auth->address); -	g_free(auth); -} - -static int request_authorization(DBusConnection *conn, -					GIOChannel *io, const char *address) -{ -	DBusMessage *msg; -	DBusPendingCall *pending; -	struct auth_data *auth; -	const char *string = ""; - -	info("Requesting authorization for %s", address); - -	auth = g_try_malloc0(sizeof(*auth)); -	if (!auth) { -		error("Allocation of auth object failed"); -		return -1; -	} - -	msg = dbus_message_new_method_call("org.bluez", "/org/bluez", -				"org.bluez.Database", "RequestAuthorization"); -	if (!msg) { -		error("Allocation of method message failed"); -		g_free(auth); -		return -1; -	} - -	dbus_message_append_args(msg, DBUS_TYPE_STRING, &address, -				DBUS_TYPE_STRING, &string, DBUS_TYPE_INVALID); - -	if (dbus_connection_send_with_reply(conn, msg, &pending, -1) == FALSE) { -		error("Sending of authorization request failed"); -		dbus_message_unref(msg); -		g_free(auth); -		return -1; -	} - -	auth->conn = conn; -	auth->io = io; -	auth->address = g_strdup(address); - -	dbus_pending_call_set_notify(pending, authorization_callback, -						auth, authorization_free); - -	dbus_pending_call_unref(pending); - -	dbus_message_unref(msg); - -	return 0; -} - -static gboolean connect_event(GIOChannel *chan, -					GIOCondition cond, gpointer data) -{ -	DBusConnection *conn = data; -	GIOChannel *io; -	struct sockaddr_rc addr; -	socklen_t optlen; -	char address[18]; -	int sk, nsk; - -	sk = g_io_channel_unix_get_fd(chan); - -	memset(&addr, 0, sizeof(addr)); -	optlen = sizeof(addr); - -	nsk = accept(sk, (struct sockaddr *) &addr, &optlen); -	if (nsk < 0) -		return TRUE; - -	io = g_io_channel_unix_new(nsk); -	g_io_channel_set_close_on_unref(io, TRUE); - -	ba2str(&addr.rc_bdaddr, address); - -	if (request_authorization(conn, io, address) < 0) { -		close(nsk); -		return TRUE; -	} - -	return TRUE; -} - -static GIOChannel *setup_rfcomm(DBusConnection *conn, uint8_t channel) -{ -	GIOChannel *io; -	struct sockaddr_rc addr; -	int sk; - -	sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); -	if (sk < 0) -		return NULL; - -	memset(&addr, 0, sizeof(addr)); -	addr.rc_family = AF_BLUETOOTH; -	bacpy(&addr.rc_bdaddr, BDADDR_ANY); -	addr.rc_channel = channel; - -	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { -		close(sk); -		return NULL; -	} - -	if (listen(sk, 10) < 0) { -		close(sk); -		return NULL; -	} - -	io = g_io_channel_unix_new(sk); -	g_io_channel_set_close_on_unref(io, TRUE); - -	g_io_add_watch(io, G_IO_IN, connect_event, conn); - -	return io; -} - -static int setup_sdp(DBusConnection *conn, uint8_t channel) -{ -	DBusMessage *msg, *reply; -	DBusError err; -	sdp_record_t *record; -	sdp_buf_t buf; -	sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto; -	uuid_t root_uuid, l2cap, rfcomm, spp; -	sdp_profile_desc_t profile[1]; -	sdp_list_t *proto[2]; -	sdp_data_t *chan; - -	record = sdp_record_alloc(); -	if (!record) { -		error("Allocation of service record failed"); -		return -1; -	} - -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); -	root = sdp_list_append(NULL, &root_uuid); -	sdp_set_browse_groups(record, root); - -	sdp_uuid16_create(&l2cap, L2CAP_UUID); -	proto[0] = sdp_list_append(NULL, &l2cap); -	apseq    = sdp_list_append(NULL, proto[0]); - -	chan = sdp_data_alloc(SDP_UINT8, &channel); -	sdp_uuid16_create(&rfcomm, RFCOMM_UUID); -	proto[1] = sdp_list_append(NULL, &rfcomm); -	proto[1] = sdp_list_append(proto[1], chan); -	apseq    = sdp_list_append(apseq, proto[1]); - -	aproto   = sdp_list_append(NULL, apseq); -	sdp_set_access_protos(record, aproto); - -	sdp_uuid16_create(&spp, SERIAL_PORT_SVCLASS_ID); -	svclass = sdp_list_append(NULL, &spp); -	sdp_set_service_classes(record, svclass); - -	sdp_uuid16_create(&profile[0].uuid, SERIAL_PORT_PROFILE_ID); -	profile[0].version = 0x0100; -	pfseq = sdp_list_append(NULL, &profile[0]); -	sdp_set_profile_descs(record, pfseq); - -	sdp_set_info_attr(record, "Echo service", NULL, NULL); - -	if (sdp_gen_record_pdu(record, &buf) < 0) { -		error("Generation of service record failed"); -		sdp_record_free(record); -		return -1; -	} - -	sdp_data_free(chan); -	sdp_list_free(root, NULL); -	sdp_list_free(apseq, NULL); -	sdp_list_free(pfseq, NULL); -	sdp_list_free(aproto, NULL); -	sdp_list_free(svclass, NULL); -	sdp_list_free(proto[0], NULL); -	sdp_list_free(proto[1], NULL); - -	sdp_record_free(record); - -	msg = dbus_message_new_method_call("org.bluez", "/org/bluez", -				"org.bluez.Database", "AddServiceRecord"); -	if (!msg) { -		error("Allocation of method message failed"); -		return -1; -	} - -	dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, -				&buf.data, buf.data_size, DBUS_TYPE_INVALID); - -	dbus_error_init(&err); - -	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); - -	dbus_message_unref(msg); - -	free(buf.data); - -	if (!reply) { -		error("Registration of service record failed"); -		error("%s", err.message); -		dbus_error_free(&err); -		return -1; -	} - -	dbus_message_unref(reply); - -	dbus_connection_flush(conn); - -	return 0; -} - -static int register_standalone(DBusConnection *conn) -{ -	DBusMessage *msg, *reply; -	DBusError err; -	const char *ident = "echo", *name = "Echo service", *desc = ""; - -	info("Registering service"); - -	msg = dbus_message_new_method_call("org.bluez", "/org/bluez", -				"org.bluez.Database", "RegisterService"); -	if (!msg) { -		error("Allocation of method message failed"); -		return -1; -	} - -	dbus_message_append_args(msg, DBUS_TYPE_STRING, &ident, -				DBUS_TYPE_STRING, &name, -				DBUS_TYPE_STRING, &desc, DBUS_TYPE_INVALID); - -	dbus_error_init(&err); - -	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); - -	dbus_message_unref(msg); - -	if (!reply) { -		error("Registration of service failed"); -		error("%s", err.message); -		dbus_error_free(&err); -		return -1; -	} - -	dbus_message_unref(reply); - -	dbus_connection_flush(conn); - -	return 0; -} - -static GMainLoop *main_loop = NULL; - -static void sig_term(int sig) -{ -	g_main_loop_quit(main_loop); -} - -int main(int argc, char *argv[]) -{ -	DBusConnection *conn; -	GIOChannel *io; -	struct sigaction sa; -	char *addr; - -	start_logging("echo", "Bluetooth echo service ver %s", VERSION); - -	memset(&sa, 0, sizeof(sa)); -	sa.sa_flags = SA_NOCLDSTOP; -	sa.sa_handler = sig_term; -	sigaction(SIGTERM, &sa, NULL); -	sigaction(SIGINT,  &sa, NULL); - -	sa.sa_handler = SIG_IGN; -	sigaction(SIGCHLD, &sa, NULL); -	sigaction(SIGPIPE, &sa, NULL); - -	enable_debug(); - -	addr = getenv("BLUETOOTHD_ADDRESS"); -	if (!addr) { -		error("No D-Bus server address available"); -		exit(1); -	} - -	debug("Bluetooth daemon at %s", addr); - -	main_loop = g_main_loop_new(NULL, FALSE); - -	if (argc > 1 && !strcmp(argv[1], "-s")) -		conn = init_dbus_direct(addr); -	else -		conn = init_dbus(NULL, NULL, NULL); - -	if (!conn) { -		error("Connection to bus failed"); -		g_main_loop_unref(main_loop); -		exit(1); -	} - -	io = setup_rfcomm(conn, 23); -	if (!io) { -		error("Creation of server channel failed"); -		dbus_connection_unref(conn); -		g_main_loop_unref(main_loop); -		exit(1); -	} - -	setup_sdp(conn, 23); - -	if (argc > 1 && !strcmp(argv[1], "-s")) -		register_standalone(conn); - -	g_main_loop_run(main_loop); - -	g_io_channel_unref(io); - -	dbus_connection_unref(conn); - -	g_main_loop_unref(main_loop); - -	info("Exit"); - -	stop_logging(); - -	return 0; -} diff --git a/daemon/echo.service b/daemon/echo.service deleted file mode 100644 index bd13d649..00000000 --- a/daemon/echo.service +++ /dev/null @@ -1,4 +0,0 @@ -[Bluetooth Service] -Identifier=echo -Name=Echo service -Description=Bluetooth RFCOMM based Echo service diff --git a/daemon/main.c b/daemon/main.c index 94eba19a..be731b14 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -37,6 +37,8 @@  #include <dbus/dbus.h> +#include <gdbus.h> +  #include "dbus-helper.h"  #include "dbus.h" @@ -56,7 +58,8 @@ static DBusConnection *system_bus = NULL;  static int setup_dbus(void)  { -	system_bus = init_dbus("org.bluez", NULL, NULL); +	system_bus = dbus_bus_system_setup_with_main_loop("org.bluez", +								NULL, NULL);  	if (!system_bus)  		return -1; diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h index 71377516..d749d5e2 100644 --- a/gdbus/gdbus.h +++ b/gdbus/gdbus.h @@ -20,3 +20,24 @@   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA   *   */ + +#ifndef __GDBUS_H +#define __GDBUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <dbus/dbus.h> +#include <glib.h> + +void setup_dbus_with_main_loop(DBusConnection *conn); + +DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, +				void (*disconnect_cb)(void *), void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif /* __GDBUS_H */ diff --git a/gdbus/mainloop.c b/gdbus/mainloop.c index f08299f0..e8e7e0af 100644 --- a/gdbus/mainloop.c +++ b/gdbus/mainloop.c @@ -25,8 +25,9 @@  #include <config.h>  #endif -#include <glib.h> +#include <stdint.h> +#include <glib.h>  #include <dbus/dbus.h>  #ifdef NEED_DBUS_WATCH_GET_UNIX_FD @@ -38,3 +39,280 @@  #endif  #include "gdbus.h" + +#define DISPATCH_TIMEOUT  0 + +#define info(fmt...) +#define error(fmt...) +#define debug(fmt...) + +#ifndef HAVE_DBUS_GLIB +typedef struct { +	uint32_t id; +	DBusTimeout *timeout; +} timeout_handler_t; + +struct watch_info { +	guint watch_id; +	GIOChannel *io; +	DBusConnection *conn; +}; + +struct server_info { +	guint watch_id; +	GIOChannel *io; +	DBusServer *server; +}; +#endif + +struct disconnect_data { +	void (*disconnect_cb)(void *); +	void *user_data; +}; + +static DBusHandlerResult disconnect_filter(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	struct disconnect_data *dc_data = data; + +	if (dbus_message_is_signal(msg, +			DBUS_INTERFACE_LOCAL, "Disconnected") == TRUE) { +		error("Got disconnected from the system message bus"); +		dbus_connection_unref(conn); +		dc_data->disconnect_cb(dc_data->user_data); +	} + +	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +#ifndef HAVE_DBUS_GLIB +static gboolean message_dispatch_cb(void *data) +{ +	DBusConnection *connection = data; + +	dbus_connection_ref(connection); + +	/* Dispatch messages */ +	while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS); + +	dbus_connection_unref(connection); + +	return FALSE; +} + +static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data) +{ +	DBusWatch *watch = data; +	struct watch_info *info = dbus_watch_get_data(watch); +	int flags = 0; + +	if (cond & G_IO_IN)  flags |= DBUS_WATCH_READABLE; +	if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; +	if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP; +	if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR; + +	dbus_watch_handle(watch, flags); + +	if (dbus_connection_get_dispatch_status(info->conn) == DBUS_DISPATCH_DATA_REMAINS) +		g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, info->conn); + +	return TRUE; +} + +static dbus_bool_t add_watch(DBusWatch *watch, void *data) +{ +	GIOCondition cond = G_IO_HUP | G_IO_ERR; +	DBusConnection *conn = data; +	struct watch_info *info; +	int fd, flags; + +	if (!dbus_watch_get_enabled(watch)) +		return TRUE; + +	info = g_new(struct watch_info, 1); + +	fd = dbus_watch_get_unix_fd(watch); +	info->io = g_io_channel_unix_new(fd); +	info->conn = dbus_connection_ref(conn); + +	dbus_watch_set_data(watch, info, NULL); + +	flags = dbus_watch_get_flags(watch); + +	if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN; +	if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT; + +	info->watch_id = g_io_add_watch(info->io, cond, watch_func, watch); + +	return TRUE; +} + +static void remove_watch(DBusWatch *watch, void *data) +{ +	struct watch_info *info = dbus_watch_get_data(watch); + +	dbus_watch_set_data(watch, NULL, NULL); + +	if (info) { +		g_source_remove(info->watch_id); +		g_io_channel_unref(info->io); +		dbus_connection_unref(info->conn); +		g_free(info); +	} +} + +static void watch_toggled(DBusWatch *watch, void *data) +{ +	/* Because we just exit on OOM, enable/disable is +	 * no different from add/remove */ +	if (dbus_watch_get_enabled(watch)) +		add_watch(watch, data); +	else +		remove_watch(watch, data); +} + +static gboolean timeout_handler_dispatch(gpointer data) +{ +	timeout_handler_t *handler = data; + +	/* if not enabled should not be polled by the main loop */ +	if (dbus_timeout_get_enabled(handler->timeout) != TRUE) +		return FALSE; + +	dbus_timeout_handle(handler->timeout); + +	return FALSE; +} + +static void timeout_handler_free(void *data) +{ +	timeout_handler_t *handler = data; +	if (!handler) +		return; + +	g_source_remove(handler->id); +	g_free(handler); +} + +static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) +{ +	timeout_handler_t *handler; + +	if (!dbus_timeout_get_enabled(timeout)) +		return TRUE; + +	handler = g_new0(timeout_handler_t, 1); + +	handler->timeout = timeout; +	handler->id = g_timeout_add(dbus_timeout_get_interval(timeout), +					timeout_handler_dispatch, handler); + +	dbus_timeout_set_data(timeout, handler, timeout_handler_free); + +	return TRUE; +} + +static void remove_timeout(DBusTimeout *timeout, void *data) +{ +} + +static void timeout_toggled(DBusTimeout *timeout, void *data) +{ +	if (dbus_timeout_get_enabled(timeout)) +		add_timeout(timeout, data); +	else +		remove_timeout(timeout, data); +} + +static void dispatch_status_cb(DBusConnection *conn, +				DBusDispatchStatus new_status, void *data) +{ +	if (!dbus_connection_get_is_connected(conn)) +		return; + +	if (new_status == DBUS_DISPATCH_DATA_REMAINS) +		g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data); +} +#endif + +void setup_dbus_with_main_loop(DBusConnection *conn) +{ +#ifdef HAVE_DBUS_GLIB +	debug("Using D-Bus GLib connection setup"); + +	dbus_connection_setup_with_g_main(conn, NULL); +#else +	dbus_connection_set_watch_functions(conn, add_watch, remove_watch, +						watch_toggled, conn, NULL); + +	dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, +						timeout_toggled, conn, NULL); + +	dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb, +								conn, NULL); +#endif +} + +static DBusConnection *init_dbus(const char *name, +				void (*disconnect_cb)(void *), void *user_data) +{ +	struct disconnect_data *dc_data; +	DBusConnection *conn; +	DBusError err; + +	dbus_error_init(&err); + +	conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + +	if (dbus_error_is_set(&err)) { +		error("Can't connect to system message bus: %s", err.message); +		dbus_error_free(&err); +		return NULL; +	} + +	setup_dbus_with_main_loop(conn); + +	if (name) { +		dbus_error_init(&err); + +		if (dbus_bus_request_name(conn, name, 0, &err) != +				DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) { +			error("Could not become the primary owner of %s", name); +			dbus_connection_unref(conn); +			return NULL; +		} + +		if (dbus_error_is_set(&err)) { +			error("Can't get bus name %s: %s", name, err.message); +			dbus_error_free(&err); +			dbus_connection_unref(conn); +			return NULL; +		} +	} + +	if (!disconnect_cb) +		return conn; + +	dc_data = g_new(struct disconnect_data, 1); + +	dc_data->disconnect_cb = disconnect_cb; +	dc_data->user_data = user_data; + +	dbus_connection_set_exit_on_disconnect(conn, FALSE); + +	if (!dbus_connection_add_filter(conn, disconnect_filter, +				dc_data, g_free)) { +		error("Can't add D-Bus disconnect filter"); +		g_free(dc_data); +		dbus_connection_unref(conn); +		return NULL; +	} + +	return conn; +} + +DBusConnection *dbus_bus_system_setup_with_main_loop(const char *name, +				void (*disconnect_cb)(void *), void *user_data) +{ +	return init_dbus(name, disconnect_cb, user_data); +} diff --git a/hcid/dbus-common.c b/hcid/dbus-common.c index 20453c82..8a8a721a 100644 --- a/hcid/dbus-common.c +++ b/hcid/dbus-common.c @@ -49,6 +49,8 @@  #include <dbus/dbus.h> +#include <gdbus.h> +  #include "hcid.h"  #include "dbus.h"  #include "dbus-helper.h" @@ -336,7 +338,8 @@ int hcid_dbus_init(void)  {  	DBusConnection *conn; -	conn = init_dbus(BLUEZ_NAME, disconnect_callback, NULL); +	conn = dbus_bus_system_setup_with_main_loop(BLUEZ_NAME, +						disconnect_callback, NULL);  	if (!conn)  		return -1; | 
