summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2006-08-18 22:11:58 +0000
committerJohan Hedberg <johan.hedberg@nokia.com>2006-08-18 22:11:58 +0000
commit85f475a02165dc506758e0a45e59a9be7f5e8583 (patch)
treeb263d36801ed5f489a5a15c14d0ad47e63141947
parentf3e65d0a38d2c5871ddc83347e8abd15bced1251 (diff)
First try at PasskeyAgent Cancel method
-rw-r--r--hcid/dbus-security.c113
-rw-r--r--hcid/dbus.c23
-rw-r--r--hcid/dbus.h24
-rw-r--r--hcid/hcid.h2
4 files changed, 127 insertions, 35 deletions
diff --git a/hcid/dbus-security.c b/hcid/dbus-security.c
index 3ad09f2e..c6609d81 100644
--- a/hcid/dbus-security.c
+++ b/hcid/dbus-security.c
@@ -41,12 +41,6 @@
#define TIMEOUT (30 * 1000) /* 30 seconds */
-struct pin_request {
- int dev;
- bdaddr_t sba;
- bdaddr_t bda;
-};
-
static struct passkey_agent *default_agent = NULL;
static void default_agent_exited(const char *name, void *data)
@@ -342,7 +336,7 @@ static struct service_data sec_services[] = {
static void passkey_agent_reply(DBusPendingCall *call, void *user_data)
{
- struct pin_request *req = (struct pin_request *) user_data;
+ struct pending_agent_request *req = user_data;
pin_code_reply_cp pr;
DBusMessage *message;
DBusError err;
@@ -394,15 +388,22 @@ done:
if (message)
dbus_message_unref(message);
- dbus_pending_call_unref(call);
+ req->agent->pending_requests = slist_remove(req->agent->pending_requests, req);
+
+ dbus_pending_call_cancel(req->call);
+ dbus_pending_call_unref(req->call);
+ dbus_connection_unref(req->conn);
+ free(req->path);
+ free(req);
}
-static int call_passkey_agent(DBusConnection *conn, struct passkey_agent *agent,
- int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba)
+static int call_passkey_agent(DBusConnection *conn,
+ struct passkey_agent *agent, int dev,
+ const char *path, bdaddr_t *sba,
+ bdaddr_t *dba)
{
DBusMessage *message = NULL;
- DBusPendingCall *pending = NULL;
- struct pin_request *req;
+ struct pending_agent_request *req = NULL;
char bda[18];
char *ptr = bda;
@@ -423,12 +424,18 @@ static int call_passkey_agent(DBusConnection *conn, struct passkey_agent *agent,
goto failed;
}
- req = malloc(sizeof(*req));
+ req = malloc(sizeof(struct pending_agent_request));
if (!req)
goto failed;
+ memset(req, 0, sizeof(struct pending_agent_request));
req->dev = dev;
bacpy(&req->sba, sba);
bacpy(&req->bda, dba);
+ req->agent = agent;
+ req->conn = dbus_connection_ref(conn);
+ req->path = strdup(path);
+ if (!req->path)
+ goto failed;
dbus_message_append_args(message,
DBUS_TYPE_STRING, &path,
@@ -436,12 +443,14 @@ static int call_passkey_agent(DBusConnection *conn, struct passkey_agent *agent,
DBUS_TYPE_INVALID);
if (dbus_connection_send_with_reply(conn, message,
- &pending, TIMEOUT) == FALSE) {
+ &req->call, TIMEOUT) == FALSE) {
error("D-Bus send failed");
goto failed;
}
- dbus_pending_call_set_notify(pending, passkey_agent_reply, req, free);
+ dbus_pending_call_set_notify(req->call, passkey_agent_reply, req, NULL);
+
+ agent->pending_requests = slist_append(agent->pending_requests, req);
dbus_message_unref(message);
@@ -451,6 +460,12 @@ failed:
if (message)
dbus_message_unref(message);
+ if (req) {
+ dbus_connection_unref(req->conn);
+ free(req->path);
+ free(req);
+ }
+
hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba);
return -1;
@@ -468,7 +483,8 @@ DBusHandlerResult handle_security_method(DBusConnection *conn, DBusMessage *msg,
return error_unknown_method(conn, msg);
}
-int handle_passkey_request(DBusConnection *conn, int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba)
+int handle_passkey_request(DBusConnection *conn, int dev, const char *path,
+ bdaddr_t *sba, bdaddr_t *dba)
{
struct passkey_agent *agent = default_agent;
struct hci_dbus_data *adapter = NULL;
@@ -496,3 +512,68 @@ int handle_passkey_request(DBusConnection *conn, int dev, const char *path, bdad
done:
return call_passkey_agent(conn, agent, dev, path, sba, dba);
}
+
+static void send_cancel_request(struct passkey_agent *agent, struct pending_agent_request *req)
+{
+ DBusMessage *message;
+ char address[18], *ptr = address;
+
+ message = dbus_message_new_method_call(agent->name, agent->path,
+ "org.bluez.PasskeyAgent", "Cancel");
+ if (message == NULL) {
+ error("Couldn't allocate D-Bus message");
+ return;
+ }
+
+ ba2str(&req->bda, address);
+
+ dbus_message_append_args(message,
+ DBUS_TYPE_STRING, &req->path,
+ DBUS_TYPE_STRING, &ptr,
+ DBUS_TYPE_INVALID);
+
+ dbus_message_set_no_reply(message, TRUE);
+
+ send_reply_and_unref(req->conn, message);
+
+ dbus_pending_call_cancel(req->call);
+ dbus_pending_call_unref(req->call);
+ dbus_connection_unref(req->conn);
+ free(req->path);
+ free(req);
+
+ debug("PasskeyAgent.Request(%s, %s) was canceled", req->path, address);
+}
+
+void cancel_passkey_agent_requests(struct slist *agents, const char *path, bdaddr_t *addr)
+{
+ struct slist *l, *next;
+
+ if (!default_agent)
+ return;
+
+ /* First check the default agent */
+ for (l = default_agent->pending_requests; l != NULL; l = next) {
+ struct pending_agent_request *req = l->data;
+ next = l->next;
+ if (!strcmp(path, req->path) && !bacmp(addr, &req->bda)) {
+ send_cancel_request(default_agent, req);
+ default_agent->pending_requests = slist_remove(default_agent->pending_requests,
+ req);
+ }
+ }
+
+ /* and then the adapter specific agents */
+ for (;agents != NULL; agents = agents->next) {
+ struct passkey_agent *agent = agents->data;
+ for (l = agent->pending_requests; l != NULL; l = next) {
+ struct pending_agent_request *req = l->data;
+ next = l->next;
+ if (!strcmp(path, req->path) && !bacmp(addr, &req->bda)) {
+ send_cancel_request(default_agent, req);
+ agent->pending_requests = slist_remove(agent->pending_requests, req);
+ }
+ }
+ }
+
+}
diff --git a/hcid/dbus.c b/hcid/dbus.c
index 5288290a..365af30e 100644
--- a/hcid/dbus.c
+++ b/hcid/dbus.c
@@ -672,12 +672,7 @@ int hcid_dbus_stop_device(uint16_t id)
static int pending_bonding_cmp(const void *p1, const void *p2)
{
- const bdaddr_t *peer1 = p1;
- const bdaddr_t *peer2 = p2;
-
- if (peer2)
- return bacmp(peer1, peer2);
- return -1;
+ return p2 ? bacmp(p1, p2) : -1;
}
void hcid_dbus_pending_bonding_add(bdaddr_t *sba, bdaddr_t *dba)
@@ -700,7 +695,7 @@ void hcid_dbus_pending_bonding_add(bdaddr_t *sba, bdaddr_t *dba)
pdata->pending_bondings = slist_append(pdata->pending_bondings, peer);
}
-void hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
+int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
{
char path[MAX_PATH_LENGTH], addr[18];
@@ -708,7 +703,7 @@ void hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, hci_devid(addr));
- handle_passkey_request(connection, dev, path, sba, &ci->bdaddr);
+ return handle_passkey_request(connection, dev, path, sba, &ci->bdaddr);
}
void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status)
@@ -752,11 +747,13 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const u
send_reply_and_unref(connection, message);
#endif
+ if (status)
+ cancel_passkey_agent_requests(pdata->passkey_agents, path, peer);
+
l = slist_find(pdata->pending_bondings, peer, pending_bonding_cmp);
if (l) {
- bdaddr_t *p = l->data;
- pdata->pending_bondings = slist_remove(pdata->pending_bondings, p);
- free(p);
+ pdata->pending_bondings = slist_remove(pdata->pending_bondings, l->data);
+ free(l->data);
if (!status) {
const char *name = "BondingCreated";
@@ -1380,7 +1377,7 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle
/* clean pending HCI cmds */
hci_req_queue_remove(pdata->dev_id, &dev->bdaddr);
- /* Check if there is a pending Bonding */
+ /* Check if there is a pending CreateBonding request */
if (pdata->bonding && (bacmp(&pdata->bonding->bdaddr, &dev->bdaddr) == 0)) {
#if 0
message = dev_signal_factory(pdata->dev_id, "BondingFailed",
@@ -1400,6 +1397,8 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle
pdata->requestor_name = NULL;
}
+ cancel_passkey_agent_requests(pdata->passkey_agents, path, &dev->bdaddr);
+
/* Sent the remote device disconnected signal */
message = dev_signal_factory(pdata->dev_id, "RemoteDeviceDisconnected",
DBUS_TYPE_STRING, &peer_addr,
diff --git a/hcid/dbus.h b/hcid/dbus.h
index c8ac1d3f..4671c482 100644
--- a/hcid/dbus.h
+++ b/hcid/dbus.h
@@ -95,6 +95,23 @@ struct active_conn_info {
uint16_t handle;
};
+struct passkey_agent {
+ char *addr;
+ char *name;
+ char *path;
+ struct slist *pending_requests;
+};
+
+struct pending_agent_request {
+ struct passkey_agent *agent;
+ int dev;
+ bdaddr_t sba;
+ bdaddr_t bda;
+ char *path;
+ DBusConnection *conn;
+ DBusPendingCall *call;
+};
+
struct hci_dbus_data {
uint16_t dev_id;
int up;
@@ -112,12 +129,6 @@ struct hci_dbus_data {
struct slist *pending_bondings;
};
-struct passkey_agent {
- char *addr;
- char *name;
- char *path;
-};
-
typedef int register_function_t(DBusConnection *conn, uint16_t id);
typedef int unregister_function_t(DBusConnection *conn, uint16_t id);
@@ -181,6 +192,7 @@ DBusHandlerResult simple_introspect(DBusConnection *conn, DBusMessage *msg, void
service_handler_func_t find_service_handler(struct service_data *services, DBusMessage *msg);
int handle_passkey_request(DBusConnection *conn, int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba);
+void cancel_passkey_agent_requests(struct slist *agents, const char *path, bdaddr_t *dba);
static inline DBusHandlerResult send_reply_and_unref(DBusConnection *conn, DBusMessage *reply)
{
diff --git a/hcid/hcid.h b/hcid/hcid.h
index 76c80906..c7208222 100644
--- a/hcid/hcid.h
+++ b/hcid/hcid.h
@@ -149,7 +149,7 @@ int hcid_dbus_unregister_device(uint16_t id);
int hcid_dbus_start_device(uint16_t id);
int hcid_dbus_stop_device(uint16_t id);
void hcid_dbus_pending_bonding_add(bdaddr_t *sba, bdaddr_t *dba);
-void hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci);
+int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci);
void hcid_dbus_inquiry_start(bdaddr_t *local);
void hcid_dbus_inquiry_complete(bdaddr_t *local);