diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java index a170cbccc..5e3973045 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java @@ -21,13 +21,19 @@ import org.briarproject.bramble.util.AndroidUtils; import java.io.Closeable; import java.io.IOException; import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Collection; import java.util.UUID; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Logger; import javax.annotation.Nullable; +import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_FINISHED; +import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_STARTED; import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED; import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED; import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE; @@ -37,8 +43,12 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERA import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE; import static android.bluetooth.BluetoothAdapter.STATE_OFF; import static android.bluetooth.BluetoothAdapter.STATE_ON; +import static android.bluetooth.BluetoothDevice.ACTION_FOUND; +import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE; +import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.bramble.util.LogUtils.logException; +import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress; @MethodsNotNullByDefault @ParametersNotNullByDefault @@ -182,6 +192,67 @@ class AndroidBluetoothPlugin extends BluetoothPlugin { } } + @Override + @Nullable + DuplexTransportConnection discoverAndConnect(String uuid) { + if (adapter == null) return null; + for (String address : discoverDevices()) { + try { + if (LOG.isLoggable(INFO)) + LOG.info("Connecting to " + scrubMacAddress(address)); + return connectTo(address, uuid); + } catch (IOException e) { + if (LOG.isLoggable(INFO)) { + LOG.info("Could not connect to " + + scrubMacAddress(address)); + } + } + } + LOG.info("Could not connect to any devices"); + return null; + } + + private Collection discoverDevices() { + Collection addresses = new ArrayList<>(); + BlockingQueue intents = new LinkedBlockingQueue<>(); + DiscoveryReceiver receiver = new DiscoveryReceiver(intents); + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_DISCOVERY_STARTED); + filter.addAction(ACTION_DISCOVERY_FINISHED); + filter.addAction(ACTION_FOUND); + appContext.registerReceiver(receiver, filter); + try { + if (adapter.startDiscovery()) { + while (true) { + Intent i = intents.take(); + String action = i.getAction(); + if (ACTION_DISCOVERY_STARTED.equals(action)) { + LOG.info("Discovery started"); + } else if (ACTION_DISCOVERY_FINISHED.equals(action)) { + LOG.info("Discovery finished"); + break; + } else if (ACTION_FOUND.equals(action)) { + BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE); + String address = d.getAddress(); + if (LOG.isLoggable(INFO)) + LOG.info("Discovered " + scrubMacAddress(address)); + if (!addresses.contains(address)) + addresses.add(address); + } + } + } else { + LOG.info("Could not start discovery"); + } + } catch (InterruptedException e) { + LOG.info("Interrupted while discovering devices"); + Thread.currentThread().interrupt(); + } finally { + adapter.cancelDiscovery(); + appContext.unregisterReceiver(receiver); + } + return addresses; + } + private void tryToClose(@Nullable Closeable c) { try { if (c != null) c.close(); @@ -207,4 +278,18 @@ class AndroidBluetoothPlugin extends BluetoothPlugin { } } } + + private static class DiscoveryReceiver extends BroadcastReceiver { + + private final BlockingQueue intents; + + private DiscoveryReceiver(BlockingQueue intents) { + this.intents = intents; + } + + @Override + public void onReceive(Context ctx, Intent intent) { + intents.add(intent); + } + } } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConstants.java index d329bff3f..078b824a8 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConstants.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/keyagreement/KeyAgreementConstants.java @@ -21,7 +21,7 @@ public interface KeyAgreementConstants { /** * The connection timeout in milliseconds. */ - long CONNECTION_TIMEOUT = 20 * 1000; + long CONNECTION_TIMEOUT = 40 * 1000; /** * The transport identifier for Bluetooth. diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java index 243548c0a..9610a905c 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java @@ -96,6 +96,9 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { abstract DuplexTransportConnection connectTo(String address, String uuid) throws IOException; + @Nullable + abstract DuplexTransportConnection discoverAndConnect(String uuid); + BluetoothPlugin(BluetoothConnectionLimiter connectionLimiter, Executor ioExecutor, SecureRandom secureRandom, Backoff backoff, DuplexPluginCallback callback, int maxLatency) { @@ -326,9 +329,6 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { @Override public KeyAgreementListener createKeyAgreementListener(byte[] commitment) { if (!isRunning()) return null; - // There's no point listening if we can't discover our own address - String address = getBluetoothAddress(); - if (address == null) return null; // No truncation necessary because COMMIT_LENGTH = 16 String uuid = UUID.nameUUIDFromBytes(commitment).toString(); if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid); @@ -346,7 +346,8 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { } BdfList descriptor = new BdfList(); descriptor.add(TRANSPORT_ID_BLUETOOTH); - descriptor.add(StringUtils.macToBytes(address)); + String address = getBluetoothAddress(); + if (address != null) descriptor.add(StringUtils.macToBytes(address)); return new BluetoothKeyAgreementListener(descriptor, ss); } @@ -354,18 +355,25 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { public DuplexTransportConnection createKeyAgreementConnection( byte[] commitment, BdfList descriptor) { if (!isRunning()) return null; - String address; - try { - address = parseAddress(descriptor); - } catch (FormatException e) { - LOG.info("Invalid address in key agreement descriptor"); - return null; - } // No truncation necessary because COMMIT_LENGTH = 16 String uuid = UUID.nameUUIDFromBytes(commitment).toString(); - if (LOG.isLoggable(INFO)) - LOG.info("Connecting to key agreement UUID " + uuid); - DuplexTransportConnection conn = connect(address, uuid); + DuplexTransportConnection conn; + if (descriptor.size() == 1) { + if (LOG.isLoggable(INFO)) + LOG.info("Discovering address for key agreement UUID " + uuid); + conn = discoverAndConnect(uuid); + } else { + String address; + try { + address = parseAddress(descriptor); + } catch (FormatException e) { + LOG.info("Invalid address in key agreement descriptor"); + return null; + } + if (LOG.isLoggable(INFO)) + LOG.info("Connecting to key agreement UUID " + uuid); + conn = connect(address, uuid); + } if (conn != null) connectionLimiter.keyAgreementConnectionOpened(conn); return conn; } diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java index c3652bfb9..c3fe9b028 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java @@ -108,6 +108,12 @@ class JavaBluetoothPlugin extends BluetoothPlugin { return wrapSocket((StreamConnection) Connector.open(url)); } + @Override + @Nullable + DuplexTransportConnection discoverAndConnect(String uuid) { + return null; // TODO + } + private String makeUrl(String address, String uuid) { return "btspp://" + address + ":" + uuid + ";name=RFCOMM"; }