Diff between e77fbdfaed30fd2e2be9e9b2554ebdd00ca37703 and 23333ab922202ef3f5813511696f0f403157bc19

Changed Files

File Additions Deletions Status
obexd/src/bluetooth.c +10 -1 modified
obexd/src/dbus.h +2 -0 modified
obexd/src/manager.c +146 -0 modified
obexd/src/obex.c +0 -2 modified

Full Patch

diff --git a/obexd/src/bluetooth.c b/obexd/src/bluetooth.c
index 15ef0ae..d71de24 100644
--- a/obexd/src/bluetooth.c
+++ b/obexd/src/bluetooth.c
@@ -182,8 +182,17 @@ static gboolean connect_event(GIOChannel *io, GIOCondition cond, gpointer user_d
 	info("New connection from: %s, channel %u, fd %d", address,
 			raddr.rc_channel, nsk);
 
-	if (obex_session_start(nsk, server) < 0)
+	if (server->service == OBEX_OPUSH) {
+		if (obex_session_start(nsk, server) < 0)
+			close(nsk);
+
+		return TRUE;
+	}
+
+	if (request_service_authorization(server, nsk) < 0) {
 		close(nsk);
+		return TRUE;
+	}
 
 	return TRUE;
 }
diff --git a/obexd/src/dbus.h b/obexd/src/dbus.h
index 627019f..5c99354 100644
--- a/obexd/src/dbus.h
+++ b/obexd/src/dbus.h
@@ -41,6 +41,8 @@ void unregister_transfer(guint32 id);
 
 gint add_record(gchar *record);
 
+gint request_service_authorization(struct server *server, gint nsk);
+
 void register_session(guint32 id, struct obex_session *os);
 
 void unregister_session(guint32 id);
diff --git a/obexd/src/manager.c b/obexd/src/manager.c
index 4e832e3..f06f905 100644
--- a/obexd/src/manager.c
+++ b/obexd/src/manager.c
@@ -25,6 +25,7 @@
 #include <config.h>
 #endif
 
+#include <unistd.h>
 #include <string.h>
 #include <errno.h>
 #include <gdbus.h>
@@ -55,6 +56,11 @@ struct agent {
 
 static struct agent *agent = NULL;
 
+struct pending_request {
+	struct server *server;
+	gint nsk;
+};
+
 static void agent_free(struct agent *agent)
 {
 	g_free(agent->new_folder);
@@ -630,6 +636,146 @@ gint add_record(gchar *record)
 	return handle;
 }
 
+static void service_reply(DBusPendingCall *call, gpointer user_data)
+{
+	struct pending_request *pending = user_data;
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	DBusError derr;
+
+	dbus_error_init(&derr);
+	if (dbus_set_error_from_message(&derr, reply)) {
+		error("Replied with an error: %s, %s",
+				derr.name, derr.message);
+		dbus_error_free(&derr);
+		dbus_message_unref(reply);
+
+		close(pending->nsk);
+		g_free(pending);
+		return;
+	}
+
+	if (obex_session_start(pending->nsk, pending->server) < 0)
+		close(pending->nsk);
+
+	g_free(pending);
+
+	dbus_message_unref(reply);
+}
+
+static gboolean service_error(GIOChannel *io, GIOCondition cond,
+			gpointer user_data)
+{
+	gchar *adapter_path = user_data;
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call("org.bluez",
+					adapter_path,
+					"org.bluez.Service",
+					"CancelAuthorization");
+
+	dbus_connection_send_with_reply(system_conn, msg, NULL, -1);
+
+	dbus_message_unref(msg);
+
+	g_free(adapter_path);
+
+	return FALSE;
+}
+
+gint request_service_authorization(struct server *server, gint nsk)
+{
+	DBusMessage *msg, *reply;
+	DBusPendingCall *call;
+	GIOChannel *io;
+	struct sockaddr_rc src, dst;
+	socklen_t addrlen;
+	gchar address[18];
+	const gchar *paddr = address;
+	gchar *adapter_path, *path;
+	guint watch;
+	struct pending_request *pending;
+
+	if (system_conn == NULL)
+		return -1;
+
+	memset(&src, 0, sizeof(src));
+	memset(&dst, 0, sizeof(dst));
+	addrlen = sizeof(src);
+
+	if (getsockname(nsk, (struct sockaddr *) &src, &addrlen) < 0)
+		return -1;
+
+	ba2str(&src.rc_bdaddr, address);
+
+	msg = dbus_message_new_method_call("org.bluez", "/",
+			"org.bluez.Manager", "FindAdapter");
+
+	dbus_message_append_args(msg, DBUS_TYPE_STRING, &paddr,
+				DBUS_TYPE_INVALID);
+
+	reply = dbus_connection_send_with_reply_and_block(system_conn, msg,
+			-1, NULL);
+	if (reply == NULL) {
+		dbus_message_unref(msg);
+		return -1;
+	}
+
+	dbus_message_unref(msg);
+
+	dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+			DBUS_TYPE_INVALID);
+
+	adapter_path = g_strdup(path);
+
+	dbus_message_unref(reply);
+
+	if (getpeername(nsk, (struct sockaddr *) &dst, &addrlen) < 0) {
+		g_free(adapter_path);
+		return -1;
+	}
+
+	ba2str(&dst.rc_bdaddr, address);
+
+	msg = dbus_message_new_method_call("org.bluez", adapter_path,
+			"org.bluez.Service", "RequestAuthorization");
+
+	dbus_message_append_args(msg, DBUS_TYPE_STRING, &paddr,
+			DBUS_TYPE_UINT32, &server->handle,
+			DBUS_TYPE_INVALID);
+
+	if (!dbus_connection_send_with_reply(system_conn,
+					msg, &call, TIMEOUT)) {
+		g_free(adapter_path);
+		dbus_message_unref(msg);
+		return -EPERM;
+	}
+
+	dbus_message_unref(msg);
+
+	pending = g_new0(struct pending_request, 1);
+	pending->server = server;
+	pending->nsk = nsk;
+
+	if (!dbus_pending_call_set_notify(call, service_reply, pending, NULL)) {
+		close(nsk);
+		g_free(adapter_path);
+		g_free(pending);
+		return -EPERM;
+	}
+
+	dbus_pending_call_unref(call);
+
+	/* Catches errors before authorization response comes */
+	io = g_io_channel_unix_new(nsk);
+	watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
+			G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+			service_error, adapter_path, NULL);
+	g_io_channel_unref(io);
+
+	return 0;
+}
+
+
 void register_session(guint32 id, struct obex_session *os)
 {
 	gchar *path = g_strdup_printf("/session%u", id);
diff --git a/obexd/src/obex.c b/obexd/src/obex.c
index 0168f81..2ccebd1 100644
--- a/obexd/src/obex.c
+++ b/obexd/src/obex.c
@@ -223,8 +223,6 @@ static void cmd_connect(struct obex_session *os,
 		return;
 	}
 
-	/* FIXME: Request authorization */
-
 	register_session(cid, os);
 	emit_session_created(cid);