From ce1a57c2b4be522c84b75c996300311be6a27337 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Tue, 27 Oct 2020 12:21:57 +0000 Subject: [PATCH 1/5] Prefer Bluetooth for adding contacts. --- .../keyagreement/KeyAgreementConnector.java | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java index 79bb700aa..444b667fd 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java @@ -8,6 +8,8 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementListener; import org.briarproject.bramble.api.keyagreement.Payload; import org.briarproject.bramble.api.keyagreement.TransportDescriptor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.plugin.BluetoothConstants; +import org.briarproject.bramble.api.plugin.LanTcpConstants; import org.briarproject.bramble.api.plugin.Plugin; import org.briarproject.bramble.api.plugin.PluginManager; import org.briarproject.bramble.api.plugin.TransportId; @@ -19,7 +21,9 @@ import org.briarproject.bramble.api.record.RecordWriterFactory; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; @@ -28,8 +32,10 @@ import java.util.logging.Logger; import javax.annotation.Nullable; +import static java.util.Arrays.asList; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.CONNECTION_TIMEOUT; import static org.briarproject.bramble.util.LogUtils.logException; @@ -41,7 +47,10 @@ class KeyAgreementConnector { } private static final Logger LOG = - Logger.getLogger(KeyAgreementConnector.class.getName()); + getLogger(KeyAgreementConnector.class.getName()); + + private static final List PREFERRED_TRANSPORTS = + asList(BluetoothConstants.ID, LanTcpConstants.ID); private final Callbacks callbacks; private final KeyAgreementCrypto keyAgreementCrypto; @@ -105,24 +114,33 @@ class KeyAgreementConnector { this.alice = alice; aliceLatch.countDown(); - // Start connecting over supported transports + // Start connecting over best available transport if (LOG.isLoggable(INFO)) { LOG.info("Starting outgoing BQP connections as " + (alice ? "Alice" : "Bob")); } + Map descriptors = new HashMap<>(); for (TransportDescriptor d : remotePayload.getTransportDescriptors()) { - Plugin p = pluginManager.getPlugin(d.getId()); - if (p instanceof DuplexPlugin) { + descriptors.put(d.getId(), d); + } + for (TransportId id : PREFERRED_TRANSPORTS) { + TransportDescriptor d = descriptors.get(id); + Plugin p = pluginManager.getPlugin(id); + if (d != null && p instanceof DuplexPlugin) { if (LOG.isLoggable(INFO)) - LOG.info("Connecting via " + d.getId()); + LOG.info("Connecting via " + id); DuplexPlugin plugin = (DuplexPlugin) p; byte[] commitment = remotePayload.getCommitment(); BdfList descriptor = d.getDescriptor(); connectionChooser.submit(new ReadableTask(new ConnectorTask( plugin, commitment, descriptor, alice))); + break; } } + // TODO: If we don't have any transports in common with the peer, + // warn the user and give up (#1224) + // Get chosen connection try { KeyAgreementConnection chosen = From 948212103cc4a88d4d588a52e11e8e7acda73189 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Tue, 27 Oct 2020 12:31:32 +0000 Subject: [PATCH 2/5] Require Bluetooth permissions if device supports Bluetooth. --- .../keyagreement/KeyAgreementActivity.java | 111 +++++++++++------- briar-android/src/main/res/values/strings.xml | 1 + 2 files changed, 68 insertions(+), 44 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java index 568ed219b..ae6c74f93 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java @@ -26,7 +26,6 @@ import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener; import org.briarproject.briar.android.keyagreement.IntroFragment.IntroScreenSeenListener; import org.briarproject.briar.android.keyagreement.KeyAgreementFragment.KeyAgreementEventListener; -import org.briarproject.briar.android.util.UiUtils; import java.util.logging.Logger; @@ -55,6 +54,7 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA_LOCATION; +import static org.briarproject.briar.android.util.UiUtils.getGoToSettingsListener; @MethodsNotNullByDefault @ParametersNotNullByDefault @@ -133,6 +133,8 @@ public abstract class KeyAgreementActivity extends BriarActivity implements private Permission locationPermission = Permission.UNKNOWN; private BluetoothDecision bluetoothDecision = BluetoothDecision.UNKNOWN; private BroadcastReceiver bluetoothReceiver = null; + private Plugin wifiPlugin = null, bluetoothPlugin = null; + private BluetoothAdapter bt = null; @Override public void injectActivity(ActivityComponent component) { @@ -152,6 +154,9 @@ public abstract class KeyAgreementActivity extends BriarActivity implements IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED); bluetoothReceiver = new BluetoothStateReceiver(); registerReceiver(bluetoothReceiver, filter); + wifiPlugin = pluginManager.getPlugin(LanTcpConstants.ID); + bluetoothPlugin = pluginManager.getPlugin(BluetoothConstants.ID); + bt = BluetoothAdapter.getDefaultAdapter(); } @Override @@ -187,6 +192,7 @@ public abstract class KeyAgreementActivity extends BriarActivity implements showQrCodeFragmentIfAllowed(); } + @SuppressWarnings("StatementWithEmptyBody") private void showQrCodeFragmentIfAllowed() { if (isResumed && continueClicked && areEssentialPermissionsGranted()) { if (isWifiReady() && isBluetoothReady()) { @@ -200,6 +206,8 @@ public abstract class KeyAgreementActivity extends BriarActivity implements } if (bluetoothDecision == BluetoothDecision.UNKNOWN) { requestBluetoothDiscoverable(); + } else if (bluetoothDecision == BluetoothDecision.REFUSED) { + // Ask again when the user clicks "continue" } else if (shouldEnableBluetooth()) { LOG.info("Enabling Bluetooth plugin"); hasEnabledBluetooth = true; @@ -210,55 +218,50 @@ public abstract class KeyAgreementActivity extends BriarActivity implements } private boolean areEssentialPermissionsGranted() { - // If the camera permission has been granted, and the location - // permission has been granted or permanently denied, we can continue return cameraPermission == Permission.GRANTED && (locationPermission == Permission.GRANTED || - locationPermission == Permission.PERMANENTLY_DENIED); + !isBluetoothSupported()); + } + + private boolean isBluetoothSupported() { + return bt != null && bluetoothPlugin != null; } private boolean isWifiReady() { - Plugin p = pluginManager.getPlugin(LanTcpConstants.ID); - if (p == null) return true; // Continue without wifi - State state = p.getState(); + if (wifiPlugin == null) return true; // Continue without wifi + State state = wifiPlugin.getState(); // Wait for plugin to become enabled return state == ACTIVE || state == INACTIVE; } private boolean isBluetoothReady() { - if (bluetoothDecision == BluetoothDecision.UNKNOWN || - bluetoothDecision == BluetoothDecision.WAITING) { - // Wait for decision - return false; - } - if (bluetoothDecision == BluetoothDecision.NO_ADAPTER - || bluetoothDecision == BluetoothDecision.REFUSED) { + if (!isBluetoothSupported()) { // Continue without Bluetooth return true; } - BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter(); - if (bt == null) return true; // Continue without Bluetooth + if (bluetoothDecision == BluetoothDecision.UNKNOWN || + bluetoothDecision == BluetoothDecision.WAITING || + bluetoothDecision == BluetoothDecision.REFUSED) { + // Wait for user to accept + return false; + } if (bt.getScanMode() != SCAN_MODE_CONNECTABLE_DISCOVERABLE) { // Wait for adapter to become discoverable return false; } - Plugin p = pluginManager.getPlugin(BluetoothConstants.ID); - if (p == null) return true; // Continue without Bluetooth // Wait for plugin to become active - return p.getState() == ACTIVE; + return bluetoothPlugin.getState() == ACTIVE; } private boolean shouldEnableWifi() { if (hasEnabledWifi) return false; - Plugin p = pluginManager.getPlugin(LanTcpConstants.ID); - if (p == null) return false; - State state = p.getState(); + if (wifiPlugin == null) return false; + State state = wifiPlugin.getState(); return state == STARTING_STOPPING || state == DISABLED; } private void requestBluetoothDiscoverable() { - BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter(); - if (bt == null) { + if (!isBluetoothSupported()) { bluetoothDecision = BluetoothDecision.NO_ADAPTER; showQrCodeFragmentIfAllowed(); } else { @@ -277,9 +280,8 @@ public abstract class KeyAgreementActivity extends BriarActivity implements private boolean shouldEnableBluetooth() { if (bluetoothDecision != BluetoothDecision.ACCEPTED) return false; if (hasEnabledBluetooth) return false; - Plugin p = pluginManager.getPlugin(BluetoothConstants.ID); - if (p == null) return false; - State state = p.getState(); + if (!isBluetoothSupported()) return false; + State state = bluetoothPlugin.getState(); return state == STARTING_STOPPING || state == DISABLED; } @@ -298,6 +300,9 @@ public abstract class KeyAgreementActivity extends BriarActivity implements @Override public void showNextScreen() { continueClicked = true; + if (bluetoothDecision == BluetoothDecision.REFUSED) { + bluetoothDecision = BluetoothDecision.UNKNOWN; // Ask again + } if (checkPermissions()) showQrCodeFragmentIfAllowed(); } @@ -341,17 +346,17 @@ public abstract class KeyAgreementActivity extends BriarActivity implements private boolean checkPermissions() { if (areEssentialPermissionsGranted()) return true; - // If the camera permission has been permanently denied, ask the + // If an essential permission has been permanently denied, ask the // user to change the setting if (cameraPermission == Permission.PERMANENTLY_DENIED) { - Builder builder = new Builder(this, R.style.BriarDialogTheme); - builder.setTitle(R.string.permission_camera_title); - builder.setMessage(R.string.permission_camera_denied_body); - builder.setPositiveButton(R.string.ok, - UiUtils.getGoToSettingsListener(this)); - builder.setNegativeButton(R.string.cancel, - (dialog, which) -> supportFinishAfterTransition()); - builder.show(); + showDenialDialog(R.string.permission_camera_title, + R.string.permission_camera_denied_body); + return false; + } + if (isBluetoothSupported() && + locationPermission == Permission.PERMANENTLY_DENIED) { + showDenialDialog(R.string.permission_location_title, + R.string.permission_location_denied_body); return false; } // Should we show the rationale for one or both permissions? @@ -371,6 +376,16 @@ public abstract class KeyAgreementActivity extends BriarActivity implements return false; } + private void showDenialDialog(@StringRes int title, @StringRes int body) { + Builder builder = new Builder(this, R.style.BriarDialogTheme); + builder.setTitle(title); + builder.setMessage(body); + builder.setPositiveButton(R.string.ok, getGoToSettingsListener(this)); + builder.setNegativeButton(R.string.cancel, + (dialog, which) -> supportFinishAfterTransition()); + builder.show(); + } + private void showRationale(@StringRes int title, @StringRes int body) { Builder builder = new Builder(this, R.style.BriarDialogTheme); builder.setTitle(title); @@ -381,8 +396,13 @@ public abstract class KeyAgreementActivity extends BriarActivity implements } private void requestPermissions() { - ActivityCompat.requestPermissions(this, - new String[] {CAMERA, ACCESS_FINE_LOCATION}, + String[] permissions; + if (isBluetoothSupported()) { + permissions = new String[] {CAMERA, ACCESS_FINE_LOCATION}; + } else { + permissions = new String[] {CAMERA}; + } + ActivityCompat.requestPermissions(this, permissions, REQUEST_PERMISSION_CAMERA_LOCATION); } @@ -399,12 +419,15 @@ public abstract class KeyAgreementActivity extends BriarActivity implements } else { cameraPermission = Permission.PERMANENTLY_DENIED; } - if (gotPermission(ACCESS_FINE_LOCATION, permissions, grantResults)) { - locationPermission = Permission.GRANTED; - } else if (shouldShowRationale(ACCESS_FINE_LOCATION)) { - locationPermission = Permission.SHOW_RATIONALE; - } else { - locationPermission = Permission.PERMANENTLY_DENIED; + if (isBluetoothSupported()) { + if (gotPermission(ACCESS_FINE_LOCATION, permissions, + grantResults)) { + locationPermission = Permission.GRANTED; + } else if (shouldShowRationale(ACCESS_FINE_LOCATION)) { + locationPermission = Permission.SHOW_RATIONALE; + } else { + locationPermission = Permission.PERMANENTLY_DENIED; + } } // If a permission dialog has been shown, showing the QR code fragment // on this call path would cause a crash due to diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index 8951beb2a..b603ca30f 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -589,6 +589,7 @@ Camera and location To scan the QR code, Briar needs access to the camera.\n\nTo discover Bluetooth devices, Briar needs permission to access your location.\n\nBriar does not store your location or share it with anyone. You have denied access to the camera, but adding contacts requires using the camera.\n\nPlease consider granting access. + You have denied access to your location, but Briar needs this permission to discover Bluetooth devices.\n\nPlease consider granting access. QR code Show QR code fullscreen From 0caa522f07bf67b67d854c21ac70e4ada4ca330f Mon Sep 17 00:00:00 2001 From: akwizgran Date: Tue, 27 Oct 2020 17:37:22 +0000 Subject: [PATCH 3/5] Remove error message, return to intro fragment when retrying. --- .../keyagreement/ContactExchangeActivity.java | 7 ++----- .../ContactExchangeErrorFragment.java | 19 +++++++++++++------ briar-android/src/main/res/values/strings.xml | 1 - 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeActivity.java index f18c41f75..222fba77b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeActivity.java @@ -9,7 +9,6 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.briar.R; import org.briarproject.briar.android.activity.ActivityComponent; -import org.briarproject.briar.android.fragment.BaseFragment; import javax.annotation.Nullable; import javax.inject.Inject; @@ -114,9 +113,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity { return getString(R.string.exchanging_contact_details); } - protected void showErrorFragment() { - String errorMsg = getString(R.string.connection_error_explanation); - BaseFragment f = ContactExchangeErrorFragment.newInstance(errorMsg); - showNextFragment(f); + private void showErrorFragment() { + showNextFragment(new ContactExchangeErrorFragment()); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeErrorFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeErrorFragment.java index 733b50a6a..2ed8ce6e4 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeErrorFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ContactExchangeErrorFragment.java @@ -1,5 +1,6 @@ package org.briarproject.briar.android.keyagreement; +import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -18,7 +19,10 @@ import org.briarproject.briar.android.util.UiUtils; import javax.inject.Inject; import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; +import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; +import static android.view.View.GONE; import static org.briarproject.briar.android.util.UiUtils.onSingleLinkClick; @MethodsNotNullByDefault @@ -58,13 +62,12 @@ public class ContactExchangeErrorFragment extends BaseFragment { View v = inflater.inflate(R.layout.fragment_error_contact_exchange, container, false); - // set humanized error message + // set optional error message TextView explanation = v.findViewById(R.id.errorMessage); Bundle args = getArguments(); - if (args == null) { - throw new IllegalArgumentException("Use newInstance()"); - } - explanation.setText(args.getString(ERROR_MSG)); + String errorMessage = args == null ? null : args.getString(ERROR_MSG); + if (errorMessage == null) explanation.setVisibility(GONE); + else explanation.setText(args.getString(ERROR_MSG)); // make feedback link clickable TextView sendFeedback = v.findViewById(R.id.sendFeedback); @@ -73,7 +76,11 @@ public class ContactExchangeErrorFragment extends BaseFragment { // buttons Button tryAgain = v.findViewById(R.id.tryAgainButton); tryAgain.setOnClickListener(view -> { - if (getActivity() != null) getActivity().onBackPressed(); + // Recreate the activity so we return to the intro fragment + FragmentActivity activity = requireActivity(); + Intent i = new Intent(activity, ContactExchangeActivity.class); + i.setFlags(FLAG_ACTIVITY_CLEAR_TOP); + activity.startActivity(i); }); Button cancel = v.findViewById(R.id.cancelButton); cancel.setOnClickListener(view -> finish()); diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index b603ca30f..66cd51313 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -210,7 +210,6 @@ Connecting to device\u2026 Authenticating with device\u2026 Could not connect to your contact - Please check that you\'re both connected to the same Wi-Fi network. If this problem persists, please send feedback to help us improve the app. From e0f381a97318e4083721311f1889975c7c8e76ef Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 29 Oct 2020 11:48:10 +0000 Subject: [PATCH 4/5] Try all transports in order of preference. --- .../api/plugin/duplex/DuplexPlugin.java | 4 +- .../keyagreement/KeyAgreementConnector.java | 48 ++++++++++--------- .../plugin/bluetooth/BluetoothPlugin.java | 15 ++---- .../bramble/plugin/tcp/LanTcpPlugin.java | 2 +- .../bramble/plugin/tcp/TcpPlugin.java | 2 +- .../bramble/plugin/tor/TorPlugin.java | 2 +- .../bramble/plugin/tcp/LanTcpPluginTest.java | 2 +- .../bramble/plugin/modem/ModemPlugin.java | 2 +- 8 files changed, 37 insertions(+), 40 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java index f37a8b5fe..9e14e7ab5 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/duplex/DuplexPlugin.java @@ -41,12 +41,10 @@ public interface DuplexPlugin extends Plugin { /** * Attempts to connect to the remote peer specified in the given descriptor. * Returns null if no connection can be established. - * - * @param alice True if the local party is Alice */ @Nullable DuplexTransportConnection createKeyAgreementConnection( - byte[] remoteCommitment, BdfList descriptor, boolean alice); + byte[] remoteCommitment, BdfList descriptor); /** * Returns true if the plugin supports rendezvous connections. diff --git a/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java index 444b667fd..23af3589e 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/keyagreement/KeyAgreementConnector.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.keyagreement; +import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.crypto.KeyAgreementCrypto; import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.data.BdfList; @@ -114,7 +115,7 @@ class KeyAgreementConnector { this.alice = alice; aliceLatch.countDown(); - // Start connecting over best available transport + // Start connecting over supported transports in order of preference if (LOG.isLoggable(INFO)) { LOG.info("Starting outgoing BQP connections as " + (alice ? "Alice" : "Bob")); @@ -123,24 +124,26 @@ class KeyAgreementConnector { for (TransportDescriptor d : remotePayload.getTransportDescriptors()) { descriptors.put(d.getId(), d); } + List> transports = new ArrayList<>(); for (TransportId id : PREFERRED_TRANSPORTS) { TransportDescriptor d = descriptors.get(id); Plugin p = pluginManager.getPlugin(id); if (d != null && p instanceof DuplexPlugin) { if (LOG.isLoggable(INFO)) LOG.info("Connecting via " + id); - DuplexPlugin plugin = (DuplexPlugin) p; - byte[] commitment = remotePayload.getCommitment(); - BdfList descriptor = d.getDescriptor(); - connectionChooser.submit(new ReadableTask(new ConnectorTask( - plugin, commitment, descriptor, alice))); - break; + transports.add(new Pair<>((DuplexPlugin) p, d.getDescriptor())); } } // TODO: If we don't have any transports in common with the peer, // warn the user and give up (#1224) + if (!transports.isEmpty()) { + byte[] commitment = remotePayload.getCommitment(); + connectionChooser.submit(new ReadableTask(new ConnectorTask( + transports, commitment))); + } + // Get chosen connection try { KeyAgreementConnection chosen = @@ -166,17 +169,13 @@ class KeyAgreementConnector { private class ConnectorTask implements Callable { - private final DuplexPlugin plugin; + private final List> transports; private final byte[] commitment; - private final BdfList descriptor; - private final boolean alice; - private ConnectorTask(DuplexPlugin plugin, byte[] commitment, - BdfList descriptor, boolean alice) { - this.plugin = plugin; + private ConnectorTask(List> transports, + byte[] commitment) { + this.transports = transports; this.commitment = commitment; - this.descriptor = descriptor; - this.alice = alice; } @Nullable @@ -184,13 +183,18 @@ class KeyAgreementConnector { public KeyAgreementConnection call() throws Exception { // Repeat attempts until we connect, get stopped, or get interrupted while (!stopped) { - DuplexTransportConnection conn = - plugin.createKeyAgreementConnection(commitment, - descriptor, alice); - if (conn != null) { - if (LOG.isLoggable(INFO)) - LOG.info(plugin.getId() + ": Outgoing connection"); - return new KeyAgreementConnection(conn, plugin.getId()); + for (Pair pair : transports) { + if (stopped) return null; + DuplexPlugin plugin = pair.getFirst(); + BdfList descriptor = pair.getSecond(); + DuplexTransportConnection conn = + plugin.createKeyAgreementConnection(commitment, + descriptor); + if (conn != null) { + if (LOG.isLoggable(INFO)) + LOG.info(plugin.getId() + ": Outgoing connection"); + return new KeyAgreementConnection(conn, plugin.getId()); + } } // Wait 2s before retry (to circumvent transient failures) Thread.sleep(2000); 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 7c1ee4b59..f90469d56 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 @@ -430,22 +430,17 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { @Override public DuplexTransportConnection createKeyAgreementConnection( - byte[] commitment, BdfList descriptor, boolean alice) { + byte[] commitment, BdfList descriptor) { if (getState() != ACTIVE) return null; // No truncation necessary because COMMIT_LENGTH = 16 String uuid = UUID.nameUUIDFromBytes(commitment).toString(); DuplexTransportConnection conn; if (descriptor.size() == 1) { - if (alice) { - if (LOG.isLoggable(INFO)) { - LOG.info("Discovering address for key agreement UUID " + - uuid); - } - conn = discoverAndConnect(uuid); - } else { - LOG.info("No address in key agreement descriptor"); - return null; + if (LOG.isLoggable(INFO)) { + LOG.info("Discovering address for key agreement UUID " + + uuid); } + conn = discoverAndConnect(uuid); } else { String address; try { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java index 235ac5cb9..87706b7e5 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java @@ -376,7 +376,7 @@ class LanTcpPlugin extends TcpPlugin { @Override public DuplexTransportConnection createKeyAgreementConnection( - byte[] commitment, BdfList descriptor, boolean alice) { + byte[] commitment, BdfList descriptor) { ServerSocket ss = state.getServerSocket(true); if (ss == null) return null; InterfaceAddress local = getLocalInterfaceAddress(ss.getInetAddress()); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java index 53ada12c1..f67121685 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java @@ -367,7 +367,7 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener { @Override public DuplexTransportConnection createKeyAgreementConnection( - byte[] commitment, BdfList descriptor, boolean alice) { + byte[] commitment, BdfList descriptor) { throw new UnsupportedOperationException(); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java index a2ba04ed2..5fc93f885 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java @@ -708,7 +708,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { @Override public DuplexTransportConnection createKeyAgreementConnection( - byte[] commitment, BdfList descriptor, boolean alice) { + byte[] commitment, BdfList descriptor) { throw new UnsupportedOperationException(); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java index 59f3b1923..cd560e3a6 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java @@ -276,7 +276,7 @@ public class LanTcpPluginTest extends BrambleTestCase { descriptor.add(local.getPort()); // Connect to the port DuplexTransportConnection d = plugin.createKeyAgreementConnection( - new byte[COMMIT_LENGTH], descriptor, true); + new byte[COMMIT_LENGTH], descriptor); assertNotNull(d); // Check that the connection was accepted assertTrue(latch.await(5, SECONDS)); diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java index 4d2ee0e1e..53a668f20 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java @@ -198,7 +198,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback { @Override public DuplexTransportConnection createKeyAgreementConnection( - byte[] commitment, BdfList descriptor, boolean alice) { + byte[] commitment, BdfList descriptor) { throw new UnsupportedOperationException(); } From 12a8907c8bebf261837b381347f340a535b74cdd Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 29 Oct 2020 14:34:10 +0000 Subject: [PATCH 5/5] Ignore missing location permission on API < 23 where it's not needed. --- .../briar/android/keyagreement/KeyAgreementActivity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java index ae6c74f93..a2795b2a0 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java @@ -45,6 +45,7 @@ import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE; import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED; import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.os.Build.VERSION.SDK_INT; import static java.util.logging.Level.INFO; import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull; @@ -219,7 +220,7 @@ public abstract class KeyAgreementActivity extends BriarActivity implements private boolean areEssentialPermissionsGranted() { return cameraPermission == Permission.GRANTED && - (locationPermission == Permission.GRANTED || + (SDK_INT < 23 || locationPermission == Permission.GRANTED || !isBluetoothSupported()); }