diff options
-rw-r--r-- | hcid/dbus-common.c | 4 | ||||
-rw-r--r-- | hcid/dbus-test.c | 115 | ||||
-rw-r--r-- | hcid/dbus.c | 6 | ||||
-rw-r--r-- | hcid/dbus.h | 2 |
4 files changed, 77 insertions, 50 deletions
diff --git a/hcid/dbus-common.c b/hcid/dbus-common.c index b1ece10d..74e2d3ae 100644 --- a/hcid/dbus-common.c +++ b/hcid/dbus-common.c @@ -219,8 +219,6 @@ int name_listener_add(DBusConnection *connection, const char *name, char match_string[128]; int first; - debug("name_listener_add(%s)", name); - if (!name_listener_initialized) { if (!dbus_connection_add_filter(connection, name_exit_filter, NULL, NULL)) { error("dbus_connection_add_filter() failed"); @@ -235,6 +233,8 @@ int name_listener_add(DBusConnection *connection, const char *name, if (!first) return 0; + debug("name_listener_add(%s)", name); + snprintf(match_string, sizeof(match_string), "interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name); diff --git a/hcid/dbus-test.c b/hcid/dbus-test.c index 74ab8abf..a18a5005 100644 --- a/hcid/dbus-test.c +++ b/hcid/dbus-test.c @@ -164,47 +164,6 @@ static gboolean audit_in_progress(void) return FALSE; } -static void process_audits_list(void) -{ - while (audits) { - struct adapter *adapter; - struct audit *audit; - int sk; - - audit = audits->data; - - adapter = NULL; - - dbus_connection_get_object_path_data(audit->conn, - audit->adapter_path, - (void *) &adapter); - - if (!adapter) { - audits = slist_remove(audits, audit); - name_listener_remove(audit->conn, audit->requestor, - (name_cb_t) audit_requestor_exited, audit); - audit_free(audit); - continue; - } - - sk = l2raw_connect(adapter->address, &audit->peer); - if (sk < 0) { - send_audit_status(audit, "AuditRemoteDeviceFailed"); - audits = slist_remove(audits, audit); - name_listener_remove(audit->conn, audit->requestor, - (name_cb_t) audit_requestor_exited, audit); - audit_free(audit); - continue; - } - - audit->io = g_io_channel_unix_new(sk); - audit->io_id = g_io_add_watch(audit->io, - G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR, - (GIOFunc) l2raw_connect_complete, audit); - return; - } -} - static gboolean l2raw_input_timer(struct audit *audit) { error("l2raw_input_timer: Timed out while waiting for input"); @@ -325,9 +284,10 @@ failed: audits = slist_remove(audits, audit); name_listener_remove(audit->conn, audit->requestor, (name_cb_t) audit_requestor_exited, audit); - audit_free(audit); - process_audits_list(); + process_audits_list(audit->adapter_path); + + audit_free(audit); return FALSE; } @@ -408,6 +368,7 @@ static DBusHandlerResult audit_remote_device(DBusConnection *conn, const char *address; struct audit *audit; struct adapter *adapter = data; + gboolean queue; dbus_error_init(&err); dbus_message_get_args(msg, &err, @@ -425,9 +386,6 @@ static DBusHandlerResult audit_remote_device(DBusConnection *conn, str2ba(address, &peer); str2ba(adapter->address, &local); - if (adapter->disc_active) - return error_discover_in_progress(conn, msg); - pending_remote_name_cancel(adapter); if (adapter->bonding) @@ -436,9 +394,18 @@ static DBusHandlerResult audit_remote_device(DBusConnection *conn, if (slist_find(adapter->pin_reqs, &peer, pin_req_cmp)) return error_bonding_in_progress(conn, msg); + /* Just return if an audit for the same device is already queued */ + if (slist_find(audits, &peer, audit_addr_cmp)) + return DBUS_HANDLER_RESULT_HANDLED; + if (!read_l2cap_info(&local, &peer, NULL, NULL, NULL, NULL)) return error_audit_already_exists(conn, msg); + if (adapter->disc_active || (adapter->pdisc_active && !adapter->pinq_idle)) + queue = TRUE; + else + queue = audit_in_progress(); + reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -449,7 +416,7 @@ static DBusHandlerResult audit_remote_device(DBusConnection *conn, return DBUS_HANDLER_RESULT_NEED_MEMORY; } - if (!audit_in_progress()) { + if (!queue) { int sk; sk = l2raw_connect(adapter->address, &peer); @@ -639,3 +606,57 @@ DBusHandlerResult handle_test_method(DBusConnection *conn, DBusMessage *msg, voi return error_unknown_method(conn, msg); } + +void process_audits_list(const char *adapter_path) +{ + struct slist *l, *next; + + for (l = audits; l != NULL; l = next) { + struct adapter *adapter; + struct audit *audit; + int sk; + + audit = l->data; + next = l->next; + + if (strcmp(adapter_path, audit->adapter_path)) + continue; + + if (audit->io) + return; + + adapter = NULL; + + dbus_connection_get_object_path_data(audit->conn, + audit->adapter_path, + (void *) &adapter); + + if (!adapter) { + audits = slist_remove(audits, audit); + name_listener_remove(audit->conn, audit->requestor, + (name_cb_t) audit_requestor_exited, audit); + audit_free(audit); + continue; + } + + if (adapter->disc_active || (adapter->pdisc_active && !adapter->pinq_idle)) + continue; + + sk = l2raw_connect(adapter->address, &audit->peer); + if (sk < 0) { + send_audit_status(audit, "AuditRemoteDeviceFailed"); + audits = slist_remove(audits, audit); + name_listener_remove(audit->conn, audit->requestor, + (name_cb_t) audit_requestor_exited, audit); + audit_free(audit); + continue; + } + + audit->io = g_io_channel_unix_new(sk); + audit->io_id = g_io_add_watch(audit->io, + G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR, + (GIOFunc) l2raw_connect_complete, audit); + return; + } +} + diff --git a/hcid/dbus.c b/hcid/dbus.c index 689ce46f..89de4054 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -1058,7 +1058,8 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local) id = hci_devid(local_addr); if (id < 0) { error("No matching device id for %s", local_addr); - goto done; + bt_free(local_addr); + return; } snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); @@ -1141,6 +1142,9 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local) } done: + /* Proceed with any queued up audits */ + process_audits_list(path); + bt_free(local_addr); } diff --git a/hcid/dbus.h b/hcid/dbus.h index 8ae3bdb8..2d6dda62 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -209,6 +209,8 @@ int l2raw_connect(const char *local, const bdaddr_t *remote); int check_address(const char *addr); +void process_audits_list(const char *adapter_path); + DBusHandlerResult handle_test_method(DBusConnection *conn, DBusMessage *msg, void *data); DBusHandlerResult handle_security_method(DBusConnection *conn, DBusMessage *msg, void *data); |