summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2009-09-06 02:44:34 +0300
committerJohan Hedberg <johan.hedberg@nokia.com>2009-09-06 02:44:34 +0300
commit74624288fb67b31e99fdf9a44db19055340815f0 (patch)
treed31adf42499076d3013f76e1e7ec151df87a402f
parent86aeac39b244f9f9ca5ad22fa9a82118cfaed004 (diff)
downloadbluez-74624288fb67b31e99fdf9a44db19055340815f0.tar.gz
Use an idle callback for trusted device authorization
The caller of btd_request_authorization could assume that it's callback will be called in a separate mainloop iteration as opposed to from within the actual btd_request_authorization function. It's therefore better to use an idle callback to make the trusted device callback behavior similar to that of untrusted devices.
-rw-r--r--src/adapter.c60
1 files changed, 44 insertions, 16 deletions
diff --git a/src/adapter.c b/src/adapter.c
index 0ecf62ac8..048bfad75 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -93,6 +93,7 @@ struct service_auth {
service_auth_cb cb;
void *user_data;
struct btd_device *device;
+ struct btd_adapter *adapter;
};
struct btd_adapter {
@@ -116,6 +117,7 @@ struct btd_adapter {
DBusMessage *discovery_cancel; /* discovery cancel message request */
GSList *passkey_agents;
struct agent *agent; /* For the new API */
+ guint auth_idle_id; /* Ongoing authorization */
GSList *connections; /* Connected devices */
GSList *devices; /* Devices structure pointers */
GSList *mode_sessions; /* Request Mode sessions */
@@ -2388,6 +2390,9 @@ static void adapter_free(gpointer user_data)
debug("adapter_free(%p)", adapter);
+ if (adapter->auth_idle_id)
+ g_source_remove(adapter->auth_idle_id);
+
g_free(adapter->path);
g_free(adapter);
}
@@ -2878,6 +2883,18 @@ static void agent_auth_cb(struct agent *agent, DBusError *derr,
auth->cb(derr, auth->user_data);
}
+static gboolean auth_idle_cb(gpointer user_data)
+{
+ struct service_auth *auth = user_data;
+ struct btd_adapter *adapter = auth->adapter;
+
+ adapter->auth_idle_id = 0;
+
+ auth->cb(NULL, auth->user_data);
+
+ return FALSE;
+}
+
static int btd_adapter_authorize(struct btd_adapter *adapter,
const bdaddr_t *dst,
const char *uuid,
@@ -2900,38 +2917,43 @@ static int btd_adapter_authorize(struct btd_adapter *adapter,
if (!g_slist_find(adapter->connections, device))
return -ENOTCONN;
+ if (adapter->auth_idle_id)
+ return -EBUSY;
+
+ auth = g_try_new0(struct service_auth, 1);
+ if (!auth)
+ return -ENOMEM;
+
+ auth->cb = cb;
+ auth->user_data = user_data;
+ auth->device = device;
+ auth->adapter = adapter;
+
trusted = read_trust(&adapter->bdaddr, address, GLOBAL_TRUST);
if (trusted) {
- cb(NULL, user_data);
+ adapter->auth_idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
+ auth_idle_cb, auth,
+ g_free);
return 0;
}
- device = adapter_find_device(adapter, address);
- if (!device)
- return -EPERM;
-
agent = device_get_agent(device);
if (!agent)
agent = adapter->agent;
- if (!agent)
+ if (!agent) {
+ g_free(auth);
return -EPERM;
-
- auth = g_try_new0(struct service_auth, 1);
- if (!auth)
- return -ENOMEM;
-
- auth->cb = cb;
- auth->user_data = user_data;
- auth->device = device;
+ }
dev_path = device_get_path(device);
err = agent_authorize(agent, dev_path, uuid, agent_auth_cb, auth, g_free);
-
- if (err == 0)
+ if (err < 0)
+ g_free(auth);
+ else
device_set_authorizing(device, TRUE);
return err;
@@ -2987,6 +3009,12 @@ int btd_cancel_authorization(const bdaddr_t *src, const bdaddr_t *dst)
if (!device)
return -EPERM;
+ if (adapter->auth_idle_id) {
+ g_source_remove(adapter->auth_idle_id);
+ adapter->auth_idle_id = 0;
+ return 0;
+ }
+
/*
* FIXME: Cancel fails if authorization is requested to adapter's
* agent and in the meanwhile CreatePairedDevice is called.