All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ] agent: Detect when ongoing request is already in progress
@ 2019-12-27 18:42 Luiz Augusto von Dentz
  0 siblings, 0 replies; only message in thread
From: Luiz Augusto von Dentz @ 2019-12-27 18:42 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This detects when a agent request is already pending for the same device
which could happen when there are 2 or more adapters in the system and
they are trying to pair with each other.
---
 src/adapter.c |   5 +-
 src/agent.c   | 128 ++++++++++++++++++++++++++++++++------------------
 src/agent.h   |   2 +-
 src/device.c  |  12 +++++
 4 files changed, 97 insertions(+), 50 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index cef25616f..63cc5c576 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -6454,7 +6454,6 @@ static gboolean process_auth_queue(gpointer user_data)
 	while (!g_queue_is_empty(adapter->auths)) {
 		struct service_auth *auth = adapter->auths->head->data;
 		struct btd_device *device = auth->device;
-		const char *dev_path;
 
 		/* Wait services to be resolved before asking authorization */
 		if (auth->svc_id > 0)
@@ -6477,9 +6476,7 @@ static gboolean process_auth_queue(gpointer user_data)
 			goto next;
 		}
 
-		dev_path = device_get_path(device);
-
-		if (agent_authorize_service(auth->agent, dev_path, auth->uuid,
+		if (agent_authorize_service(auth->agent, device, auth->uuid,
 					agent_auth_cb, adapter, NULL) < 0) {
 			auth->cb(&err, auth->user_data);
 			goto next;
diff --git a/src/agent.c b/src/agent.c
index 183e2f190..e0ffcd22f 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -76,6 +76,7 @@ struct agent {
 
 struct agent_request {
 	agent_request_type_t type;
+	struct btd_device *device; /* Weak reference */
 	struct agent *agent;
 	DBusMessage *msg;
 	DBusPendingCall *call;
@@ -296,6 +297,7 @@ static struct agent *agent_create( const char *name, const char *path,
 }
 
 static struct agent_request *agent_request_new(struct agent *agent,
+						struct btd_device *device,
 						agent_request_type_t type,
 						void *cb,
 						void *user_data,
@@ -306,6 +308,7 @@ static struct agent_request *agent_request_new(struct agent *agent,
 	req = g_new0(struct agent_request, 1);
 
 	req->agent = agent;
+	req->device = device;
 	req->type = type;
 	req->cb = cb;
 	req->user_data = user_data;
@@ -381,10 +384,10 @@ done:
 }
 
 static int agent_call_authorize_service(struct agent_request *req,
-						const char *device_path,
 						const char *uuid)
 {
 	struct agent *agent = req->agent;
+	const char *path;
 
 	req->msg = dbus_message_new_method_call(agent->owner, agent->path,
 					AGENT_INTERFACE, "AuthorizeService");
@@ -393,8 +396,10 @@ static int agent_call_authorize_service(struct agent_request *req,
 		return -ENOMEM;
 	}
 
+	path = device_get_path(req->device);
+
 	dbus_message_append_args(req->msg,
-				DBUS_TYPE_OBJECT_PATH, &device_path,
+				DBUS_TYPE_OBJECT_PATH, &path,
 				DBUS_TYPE_STRING, &uuid,
 				DBUS_TYPE_INVALID);
 
@@ -406,23 +411,50 @@ static int agent_call_authorize_service(struct agent_request *req,
 	}
 
 	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
+
+	DBG("authorize service request was sent for %s", path);
+
 	return 0;
 }
 
-int agent_authorize_service(struct agent *agent, const char *path,
+static int agent_has_request(struct agent *agent, struct btd_device *device,
+						agent_request_type_t type)
+{
+	if (!agent->request)
+		return 0;
+
+	if (agent->request->type != type)
+		return -EBUSY;
+
+	/* Check if request pending is for the same address */
+	if (bacmp(device_get_address(agent->request->device),
+			btd_adapter_get_address(device_get_adapter(device))))
+		return -EBUSY;
+
+	/* It must match in either direction */
+	if (bacmp(device_get_address(device),
+			btd_adapter_get_address(
+			device_get_adapter(agent->request->device))))
+		return -EBUSY;
+
+	return -EINPROGRESS;
+}
+
+int agent_authorize_service(struct agent *agent, struct btd_device *device,
 				const char *uuid, agent_cb cb,
 				void *user_data, GDestroyNotify destroy)
 {
 	struct agent_request *req;
 	int err;
 
-	if (agent->request)
-		return -EBUSY;
+	err = agent_has_request(agent, device, AGENT_REQUEST_AUTHORIZE_SERVICE);
+	if (err)
+		return err;
 
-	req = agent_request_new(agent, AGENT_REQUEST_AUTHORIZE_SERVICE, cb,
-							user_data, destroy);
+	req = agent_request_new(agent, device, AGENT_REQUEST_AUTHORIZE_SERVICE,
+						cb, user_data, destroy);
 
-	err = agent_call_authorize_service(req, path, uuid);
+	err = agent_call_authorize_service(req, uuid);
 	if (err < 0) {
 		agent_request_free(req, FALSE);
 		return -ENOMEM;
@@ -430,8 +462,6 @@ int agent_authorize_service(struct agent *agent, const char *path,
 
 	agent->request = req;
 
-	DBG("authorize service request was sent for %s", path);
-
 	return 0;
 }
 
@@ -494,10 +524,10 @@ done:
 	agent_unref(agent);
 }
 
-static int pincode_request_new(struct agent_request *req, const char *device_path,
-				dbus_bool_t secure)
+static int pincode_request_new(struct agent_request *req, dbus_bool_t secure)
 {
 	struct agent *agent = req->agent;
+	const char *path;
 
 	/* TODO: Add a new method or a new param to Agent interface to request
 		secure pin. */
@@ -509,7 +539,9 @@ static int pincode_request_new(struct agent_request *req, const char *device_pat
 		return -ENOMEM;
 	}
 
-	dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path,
+	path = device_get_path(req->device);
+
+	dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &path,
 					DBUS_TYPE_INVALID);
 
 	if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg,
@@ -527,16 +559,15 @@ int agent_request_pincode(struct agent *agent, struct btd_device *device,
 				void *user_data, GDestroyNotify destroy)
 {
 	struct agent_request *req;
-	const char *dev_path = device_get_path(device);
 	int err;
 
 	if (agent->request)
 		return -EBUSY;
 
-	req = agent_request_new(agent, AGENT_REQUEST_PINCODE, cb,
+	req = agent_request_new(agent, device, AGENT_REQUEST_PINCODE, cb,
 							user_data, destroy);
 
-	err = pincode_request_new(req, dev_path, secure);
+	err = pincode_request_new(req, secure);
 	if (err < 0)
 		goto failed;
 
@@ -591,10 +622,10 @@ done:
 	agent_request_free(req, TRUE);
 }
 
-static int passkey_request_new(struct agent_request *req,
-				const char *device_path)
+static int passkey_request_new(struct agent_request *req)
 {
 	struct agent *agent = req->agent;
+	const char *path;
 
 	req->msg = dbus_message_new_method_call(agent->owner, agent->path,
 					AGENT_INTERFACE, "RequestPasskey");
@@ -603,7 +634,9 @@ static int passkey_request_new(struct agent_request *req,
 		return -ENOMEM;
 	}
 
-	dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path,
+	path = device_get_path(req->device);
+
+	dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &path,
 					DBUS_TYPE_INVALID);
 
 	if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg,
@@ -621,7 +654,6 @@ int agent_request_passkey(struct agent *agent, struct btd_device *device,
 				GDestroyNotify destroy)
 {
 	struct agent_request *req;
-	const char *dev_path = device_get_path(device);
 	int err;
 
 	if (agent->request)
@@ -630,10 +662,10 @@ int agent_request_passkey(struct agent *agent, struct btd_device *device,
 	DBG("Calling Agent.RequestPasskey: name=%s, path=%s",
 			agent->owner, agent->path);
 
-	req = agent_request_new(agent, AGENT_REQUEST_PASSKEY, cb,
+	req = agent_request_new(agent, device, AGENT_REQUEST_PASSKEY, cb,
 							user_data, destroy);
 
-	err = passkey_request_new(req, dev_path);
+	err = passkey_request_new(req);
 	if (err < 0)
 		goto failed;
 
@@ -647,10 +679,10 @@ failed:
 }
 
 static int confirmation_request_new(struct agent_request *req,
-					const char *device_path,
 					uint32_t passkey)
 {
 	struct agent *agent = req->agent;
+	const char *path;
 
 	req->msg = dbus_message_new_method_call(agent->owner, agent->path,
 				AGENT_INTERFACE, "RequestConfirmation");
@@ -659,8 +691,10 @@ static int confirmation_request_new(struct agent_request *req,
 		return -ENOMEM;
 	}
 
+	path = device_get_path(req->device);
+
 	dbus_message_append_args(req->msg,
-				DBUS_TYPE_OBJECT_PATH, &device_path,
+				DBUS_TYPE_OBJECT_PATH, &path,
 				DBUS_TYPE_UINT32, &passkey,
 				DBUS_TYPE_INVALID);
 
@@ -680,19 +714,19 @@ int agent_request_confirmation(struct agent *agent, struct btd_device *device,
 				void *user_data, GDestroyNotify destroy)
 {
 	struct agent_request *req;
-	const char *dev_path = device_get_path(device);
 	int err;
 
-	if (agent->request)
-		return -EBUSY;
+	err = agent_has_request(agent, device, AGENT_REQUEST_CONFIRMATION);
+	if (err)
+		return err;
 
 	DBG("Calling Agent.RequestConfirmation: name=%s, path=%s, passkey=%06u",
 			agent->owner, agent->path, passkey);
 
-	req = agent_request_new(agent, AGENT_REQUEST_CONFIRMATION, cb,
+	req = agent_request_new(agent, device, AGENT_REQUEST_CONFIRMATION, cb,
 				user_data, destroy);
 
-	err = confirmation_request_new(req, dev_path, passkey);
+	err = confirmation_request_new(req, passkey);
 	if (err < 0)
 		goto failed;
 
@@ -705,10 +739,10 @@ failed:
 	return err;
 }
 
-static int authorization_request_new(struct agent_request *req,
-						const char *device_path)
+static int authorization_request_new(struct agent_request *req)
 {
 	struct agent *agent = req->agent;
+	const char *path;
 
 	req->msg = dbus_message_new_method_call(agent->owner, agent->path,
 				AGENT_INTERFACE, "RequestAuthorization");
@@ -717,8 +751,10 @@ static int authorization_request_new(struct agent_request *req,
 		return -ENOMEM;
 	}
 
+	path = device_get_path(req->device);
+
 	dbus_message_append_args(req->msg,
-				DBUS_TYPE_OBJECT_PATH, &device_path,
+				DBUS_TYPE_OBJECT_PATH, &path,
 				DBUS_TYPE_INVALID);
 
 	if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg,
@@ -737,19 +773,19 @@ int agent_request_authorization(struct agent *agent, struct btd_device *device,
 						GDestroyNotify destroy)
 {
 	struct agent_request *req;
-	const char *dev_path = device_get_path(device);
 	int err;
 
-	if (agent->request)
-		return -EBUSY;
+	err = agent_has_request(agent, device, AGENT_REQUEST_AUTHORIZATION);
+	if (err)
+		return err;
 
 	DBG("Calling Agent.RequestAuthorization: name=%s, path=%s",
 						agent->owner, agent->path);
 
-	req = agent_request_new(agent, AGENT_REQUEST_AUTHORIZATION, cb,
+	req = agent_request_new(agent, device, AGENT_REQUEST_AUTHORIZATION, cb,
 				user_data, destroy);
 
-	err = authorization_request_new(req, dev_path);
+	err = authorization_request_new(req);
 	if (err < 0)
 		goto failed;
 
@@ -838,10 +874,10 @@ done:
 }
 
 static int display_pincode_request_new(struct agent_request *req,
-					const char *device_path,
 					const char *pincode)
 {
 	struct agent *agent = req->agent;
+	const char *path;
 
 	req->msg = dbus_message_new_method_call(agent->owner, agent->path,
 					AGENT_INTERFACE, "DisplayPinCode");
@@ -850,8 +886,10 @@ static int display_pincode_request_new(struct agent_request *req,
 		return -ENOMEM;
 	}
 
+	path = device_get_path(req->device);
+
 	dbus_message_append_args(req->msg,
-					DBUS_TYPE_OBJECT_PATH, &device_path,
+					DBUS_TYPE_OBJECT_PATH, &path,
 					DBUS_TYPE_STRING, &pincode,
 					DBUS_TYPE_INVALID);
 
@@ -872,19 +910,19 @@ int agent_display_pincode(struct agent *agent, struct btd_device *device,
 				void *user_data, GDestroyNotify destroy)
 {
 	struct agent_request *req;
-	const char *dev_path = device_get_path(device);
 	int err;
 
-	if (agent->request)
-		return -EBUSY;
+	err = agent_has_request(agent, device, AGENT_REQUEST_DISPLAY_PINCODE);
+	if (err)
+		return err;
 
 	DBG("Calling Agent.DisplayPinCode: name=%s, path=%s, pincode=%s",
 					agent->owner, agent->path, pincode);
 
-	req = agent_request_new(agent, AGENT_REQUEST_DISPLAY_PINCODE, cb,
-							user_data, destroy);
+	req = agent_request_new(agent, device, AGENT_REQUEST_DISPLAY_PINCODE,
+				cb, user_data, destroy);
 
-	err = display_pincode_request_new(req, dev_path, pincode);
+	err = display_pincode_request_new(req, pincode);
 	if (err < 0)
 		goto failed;
 
diff --git a/src/agent.h b/src/agent.h
index f14d14325..1438b9e6d 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -45,7 +45,7 @@ void agent_unref(struct agent *agent);
 
 struct agent *agent_get(const char *owner);
 
-int agent_authorize_service(struct agent *agent, const char *path,
+int agent_authorize_service(struct agent *agent, struct btd_device *device,
 				const char *uuid, agent_cb cb,
 				void *user_data, GDestroyNotify destroy);
 
diff --git a/src/device.c b/src/device.c
index 0eec7c922..f7f0bc789 100644
--- a/src/device.c
+++ b/src/device.c
@@ -6166,6 +6166,12 @@ int device_confirm_passkey(struct btd_device *device, uint8_t type,
 						confirm_cb, auth, NULL);
 
 	if (err < 0) {
+		if (err == -EINPROGRESS) {
+			/* Already in progress */
+			confirm_cb(auth->agent, NULL, auth);
+			return 0;
+		}
+
 		error("Failed requesting authentication");
 		device_auth_req_free(device);
 	}
@@ -6213,6 +6219,12 @@ int device_notify_pincode(struct btd_device *device, gboolean secure,
 	err = agent_display_pincode(auth->agent, device, pincode,
 					display_pincode_cb, auth, NULL);
 	if (err < 0) {
+		if (err == -EINPROGRESS) {
+			/* Already in progress */
+			display_pincode_cb(auth->agent, NULL, auth);
+			return 0;
+		}
+
 		error("Failed requesting authentication");
 		device_auth_req_free(device);
 	}
-- 
2.21.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2019-12-27 18:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-27 18:42 [PATCH BlueZ] agent: Detect when ongoing request is already in progress Luiz Augusto von Dentz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.