mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 14:49:53 +01:00
Merge branch 'reflected-bt-address' into 'master'
Use reflected BT address if we don't know our own address See merge request briar/briar!1265
This commit is contained in:
3
.idea/codeStyles/Project.xml
generated
3
.idea/codeStyles/Project.xml
generated
@@ -1,8 +1,5 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<AndroidXmlCodeStyleSettings>
|
|
||||||
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
|
|
||||||
</AndroidXmlCodeStyleSettings>
|
|
||||||
<JavaCodeStyleSettings>
|
<JavaCodeStyleSettings>
|
||||||
<option name="ANNOTATION_PARAMETER_WRAP" value="1" />
|
<option name="ANNOTATION_PARAMETER_WRAP" value="1" />
|
||||||
<option name="IMPORT_LAYOUT_TABLE">
|
<option name="IMPORT_LAYOUT_TABLE">
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ public interface BluetoothConstants {
|
|||||||
String PROP_ADDRESS = "address";
|
String PROP_ADDRESS = "address";
|
||||||
String PROP_UUID = "uuid";
|
String PROP_UUID = "uuid";
|
||||||
|
|
||||||
// Default value for PREF_PLUGIN_ENABLE
|
// Local settings (not shared with contacts)
|
||||||
|
String PREF_ADDRESS_IS_REFLECTED = "addressIsReflected";
|
||||||
|
String PREF_EVER_CONNECTED = "everConnected";
|
||||||
|
|
||||||
|
// Default values for local settings
|
||||||
boolean DEFAULT_PREF_PLUGIN_ENABLE = false;
|
boolean DEFAULT_PREF_PLUGIN_ENABLE = false;
|
||||||
|
boolean DEFAULT_PREF_ADDRESS_IS_REFLECTED = false;
|
||||||
|
boolean DEFAULT_PREF_EVER_CONNECTED = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
|
|||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface through which a transport plugin interacts with the rest of
|
* An interface through which a transport plugin interacts with the rest of
|
||||||
* the application.
|
* the application.
|
||||||
@@ -25,6 +27,11 @@ public interface PluginCallback extends ConnectionHandler {
|
|||||||
*/
|
*/
|
||||||
TransportProperties getLocalProperties();
|
TransportProperties getLocalProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the plugin's remote transport properties.
|
||||||
|
*/
|
||||||
|
Collection<TransportProperties> getRemoteProperties();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges the given settings with the plugin's settings
|
* Merges the given settings with the plugin's settings
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.briarproject.bramble.plugin;
|
package org.briarproject.bramble.plugin;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.connection.ConnectionManager;
|
import org.briarproject.bramble.api.connection.ConnectionManager;
|
||||||
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
@@ -44,6 +45,7 @@ import java.util.logging.Logger;
|
|||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.logging.Level.FINE;
|
import static java.util.logging.Level.FINE;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
@@ -303,6 +305,18 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<TransportProperties> getRemoteProperties() {
|
||||||
|
try {
|
||||||
|
Map<ContactId, TransportProperties> remote =
|
||||||
|
transportPropertyManager.getRemoteProperties(id);
|
||||||
|
return remote.values();
|
||||||
|
} catch (DbException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeSettings(Settings s) {
|
public void mergeSettings(Settings s) {
|
||||||
PluginManagerImpl.this.mergeSettings(s, id.getString());
|
PluginManagerImpl.this.mergeSettings(s, id.getString());
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.briarproject.bramble.plugin.bluetooth;
|
package org.briarproject.bramble.plugin.bluetooth;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.Multiset;
|
||||||
import org.briarproject.bramble.api.Pair;
|
import org.briarproject.bramble.api.Pair;
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
@@ -25,6 +26,7 @@ import org.briarproject.bramble.api.plugin.event.BluetoothEnabledEvent;
|
|||||||
import org.briarproject.bramble.api.plugin.event.DisableBluetoothEvent;
|
import org.briarproject.bramble.api.plugin.event.DisableBluetoothEvent;
|
||||||
import org.briarproject.bramble.api.plugin.event.EnableBluetoothEvent;
|
import org.briarproject.bramble.api.plugin.event.EnableBluetoothEvent;
|
||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
|
import org.briarproject.bramble.api.properties.event.RemoteTransportPropertiesUpdatedEvent;
|
||||||
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
|
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
|
||||||
import org.briarproject.bramble.api.rendezvous.RendezvousEndpoint;
|
import org.briarproject.bramble.api.rendezvous.RendezvousEndpoint;
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
@@ -46,8 +48,12 @@ import static java.util.logging.Level.INFO;
|
|||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
|
||||||
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.DEFAULT_PREF_ADDRESS_IS_REFLECTED;
|
||||||
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.DEFAULT_PREF_EVER_CONNECTED;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.DEFAULT_PREF_PLUGIN_ENABLE;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.DEFAULT_PREF_PLUGIN_ENABLE;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
|
||||||
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_ADDRESS_IS_REFLECTED;
|
||||||
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_EVER_CONNECTED;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
|
||||||
@@ -55,6 +61,7 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
|||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
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.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
||||||
|
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.REFLECTED_PROPERTY_PREFIX;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
||||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||||
@@ -77,6 +84,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
private final PluginCallback callback;
|
private final PluginCallback callback;
|
||||||
private final int maxLatency, maxIdleTime;
|
private final int maxLatency, maxIdleTime;
|
||||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
private final AtomicBoolean everConnected = new AtomicBoolean(false);
|
||||||
|
|
||||||
protected final PluginState state = new PluginState();
|
protected final PluginState state = new PluginState();
|
||||||
|
|
||||||
@@ -167,6 +175,8 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
Settings settings = callback.getSettings();
|
Settings settings = callback.getSettings();
|
||||||
boolean enabledByUser = settings.getBoolean(PREF_PLUGIN_ENABLE,
|
boolean enabledByUser = settings.getBoolean(PREF_PLUGIN_ENABLE,
|
||||||
DEFAULT_PREF_PLUGIN_ENABLE);
|
DEFAULT_PREF_PLUGIN_ENABLE);
|
||||||
|
everConnected.set(settings.getBoolean(PREF_EVER_CONNECTED,
|
||||||
|
DEFAULT_PREF_EVER_CONNECTED));
|
||||||
state.setStarted(enabledByUser);
|
state.setStarted(enabledByUser);
|
||||||
try {
|
try {
|
||||||
initialiseAdapter();
|
initialiseAdapter();
|
||||||
@@ -205,25 +215,68 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
TransportProperties p = callback.getLocalProperties();
|
TransportProperties p = callback.getLocalProperties();
|
||||||
String address = p.get(PROP_ADDRESS);
|
String address = p.get(PROP_ADDRESS);
|
||||||
String uuid = p.get(PROP_UUID);
|
String uuid = p.get(PROP_UUID);
|
||||||
|
Settings s = callback.getSettings();
|
||||||
|
boolean isReflected = s.getBoolean(PREF_ADDRESS_IS_REFLECTED,
|
||||||
|
DEFAULT_PREF_ADDRESS_IS_REFLECTED);
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
if (address == null) {
|
if (address == null || isReflected) {
|
||||||
address = getBluetoothAddress();
|
address = getBluetoothAddress();
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info("Local address " + scrubMacAddress(address));
|
LOG.info("Local address " + scrubMacAddress(address));
|
||||||
if (!isNullOrEmpty(address)) {
|
}
|
||||||
p.put(PROP_ADDRESS, address);
|
if (address == null) {
|
||||||
|
if (everConnected.get()) {
|
||||||
|
address = getReflectedAddress();
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Reflected address " +
|
||||||
|
scrubMacAddress(address));
|
||||||
|
}
|
||||||
|
if (address != null) {
|
||||||
|
changed = true;
|
||||||
|
isReflected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
changed = true;
|
changed = true;
|
||||||
|
isReflected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
byte[] random = new byte[UUID_BYTES];
|
byte[] random = new byte[UUID_BYTES];
|
||||||
secureRandom.nextBytes(random);
|
secureRandom.nextBytes(random);
|
||||||
uuid = UUID.nameUUIDFromBytes(random).toString();
|
uuid = UUID.nameUUIDFromBytes(random).toString();
|
||||||
p.put(PROP_UUID, uuid);
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
contactConnectionsUuid = uuid;
|
contactConnectionsUuid = uuid;
|
||||||
if (changed) callback.mergeLocalProperties(p);
|
if (changed) {
|
||||||
|
p = new TransportProperties();
|
||||||
|
// If we previously used a reflected address and there's no longer
|
||||||
|
// a reflected address with enough votes to be used, we'll continue
|
||||||
|
// to use the old reflected address until there's a new winner
|
||||||
|
if (address != null) p.put(PROP_ADDRESS, address);
|
||||||
|
p.put(PROP_UUID, uuid);
|
||||||
|
callback.mergeLocalProperties(p);
|
||||||
|
s = new Settings();
|
||||||
|
s.putBoolean(PREF_ADDRESS_IS_REFLECTED, isReflected);
|
||||||
|
callback.mergeSettings(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String getReflectedAddress() {
|
||||||
|
// Count the number of votes for each reflected address
|
||||||
|
String key = REFLECTED_PROPERTY_PREFIX + PROP_ADDRESS;
|
||||||
|
Multiset<String> votes = new Multiset<>();
|
||||||
|
for (TransportProperties p : callback.getRemoteProperties()) {
|
||||||
|
String address = p.get(key);
|
||||||
|
if (address != null && isValidAddress(address)) votes.add(address);
|
||||||
|
}
|
||||||
|
// If an address gets more than half of the votes, accept it
|
||||||
|
int total = votes.getTotal();
|
||||||
|
for (String address : votes.keySet()) {
|
||||||
|
if (votes.getCount(address) * 2 > total) return address;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void acceptContactConnections(SS ss) {
|
private void acceptContactConnections(SS ss) {
|
||||||
@@ -240,10 +293,23 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
LOG.info("Connection received");
|
LOG.info("Connection received");
|
||||||
connectionLimiter.connectionOpened(conn);
|
connectionLimiter.connectionOpened(conn);
|
||||||
backoff.reset();
|
backoff.reset();
|
||||||
|
setEverConnected();
|
||||||
callback.handleConnection(conn);
|
callback.handleConnection(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setEverConnected() {
|
||||||
|
if (!everConnected.getAndSet(true)) {
|
||||||
|
ioExecutor.execute(() -> {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putBoolean(PREF_EVER_CONNECTED, true);
|
||||||
|
callback.mergeSettings(s);
|
||||||
|
// Contacts may already have sent a reflected address
|
||||||
|
updateProperties();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
SS ss = state.setStopped();
|
SS ss = state.setStopped();
|
||||||
@@ -290,6 +356,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
DuplexTransportConnection d = createConnection(p);
|
DuplexTransportConnection d = createConnection(p);
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
backoff.reset();
|
backoff.reset();
|
||||||
|
setEverConnected();
|
||||||
h.handleConnection(d);
|
h.handleConnection(d);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -392,7 +459,10 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
LOG.info("Connecting to key agreement UUID " + uuid);
|
LOG.info("Connecting to key agreement UUID " + uuid);
|
||||||
conn = connect(address, uuid);
|
conn = connect(address, uuid);
|
||||||
}
|
}
|
||||||
if (conn != null) connectionLimiter.connectionOpened(conn);
|
if (conn != null) {
|
||||||
|
connectionLimiter.connectionOpened(conn);
|
||||||
|
setEverConnected();
|
||||||
|
}
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,6 +499,12 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
ioExecutor.execute(connectionLimiter::keyAgreementStarted);
|
ioExecutor.execute(connectionLimiter::keyAgreementStarted);
|
||||||
} else if (e instanceof KeyAgreementStoppedListeningEvent) {
|
} else if (e instanceof KeyAgreementStoppedListeningEvent) {
|
||||||
ioExecutor.execute(connectionLimiter::keyAgreementEnded);
|
ioExecutor.execute(connectionLimiter::keyAgreementEnded);
|
||||||
|
} else if (e instanceof RemoteTransportPropertiesUpdatedEvent) {
|
||||||
|
RemoteTransportPropertiesUpdatedEvent r =
|
||||||
|
(RemoteTransportPropertiesUpdatedEvent) e;
|
||||||
|
if (r.getTransportId().equals(ID)) {
|
||||||
|
ioExecutor.execute(this::updateProperties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,13 @@ import java.net.InetSocketAddress;
|
|||||||
import java.net.NetworkInterface;
|
import java.net.NetworkInterface;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import static java.net.NetworkInterface.getNetworkInterfaces;
|
import static java.net.NetworkInterface.getNetworkInterfaces;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Collections.list;
|
import static java.util.Collections.list;
|
||||||
import static java.util.concurrent.Executors.newCachedThreadPool;
|
import static java.util.concurrent.Executors.newCachedThreadPool;
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
@@ -320,6 +322,11 @@ public class LanTcpPluginTest extends BrambleTestCase {
|
|||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<TransportProperties> getRemoteProperties() {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeSettings(Settings s) {
|
public void mergeSettings(Settings s) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
|||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class TestPluginCallback implements PluginCallback {
|
public class TestPluginCallback implements PluginCallback {
|
||||||
|
|
||||||
@@ -22,6 +26,11 @@ public class TestPluginCallback implements PluginCallback {
|
|||||||
return new TransportProperties();
|
return new TransportProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<TransportProperties> getRemoteProperties() {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeSettings(Settings s) {
|
public void mergeSettings(Settings s) {
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user