mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 03:09:04 +01:00
Merge branch 'discover-bt-address-from-incoming-connection' into 'master'
Discover remote Bluetooth address from connection See merge request briar/briar!1244
This commit is contained in:
@@ -10,6 +10,9 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
|
||||
import static org.briarproject.bramble.util.AndroidUtils.isValidBluetoothAddress;
|
||||
|
||||
@NotNullByDefault
|
||||
class AndroidBluetoothTransportConnection
|
||||
extends AbstractDuplexTransportConnection {
|
||||
@@ -23,6 +26,8 @@ class AndroidBluetoothTransportConnection
|
||||
super(plugin);
|
||||
this.connectionManager = connectionManager;
|
||||
this.socket = socket;
|
||||
String address = socket.getRemoteDevice().getAddress();
|
||||
if (isValidBluetoothAddress(address)) remote.put(PROP_ADDRESS, address);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -71,7 +71,7 @@ public class AndroidUtils {
|
||||
return new Pair<>("", "");
|
||||
}
|
||||
|
||||
private static boolean isValidBluetoothAddress(@Nullable String address) {
|
||||
public static boolean isValidBluetoothAddress(@Nullable String address) {
|
||||
return !StringUtils.isNullOrEmpty(address)
|
||||
&& BluetoothAdapter.checkBluetoothAddress(address)
|
||||
&& !address.equals(FAKE_BLUETOOTH_ADDRESS);
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.Plugin;
|
||||
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
|
||||
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -14,6 +15,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
public abstract class AbstractDuplexTransportConnection
|
||||
implements DuplexTransportConnection {
|
||||
|
||||
protected final TransportProperties remote = new TransportProperties();
|
||||
|
||||
private final Plugin plugin;
|
||||
private final Reader reader;
|
||||
private final Writer writer;
|
||||
@@ -44,6 +47,11 @@ public abstract class AbstractDuplexTransportConnection
|
||||
return writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportProperties getRemoteProperties() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
private class Reader implements TransportConnectionReader {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.bramble.api.plugin.duplex;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
|
||||
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
|
||||
/**
|
||||
* An interface for reading and writing data over a duplex transport. The
|
||||
@@ -23,4 +24,10 @@ public interface DuplexTransportConnection {
|
||||
* for writing to the connection.
|
||||
*/
|
||||
TransportConnectionWriter getWriter();
|
||||
|
||||
/**
|
||||
* Returns a possibly empty set of {@link TransportProperties} describing
|
||||
* the remote peer.
|
||||
*/
|
||||
TransportProperties getRemoteProperties();
|
||||
}
|
||||
|
||||
@@ -11,4 +11,28 @@ public interface TransportPropertyConstants {
|
||||
* The maximum length of a property's key or value in UTF-8 bytes.
|
||||
*/
|
||||
int MAX_PROPERTY_LENGTH = 100;
|
||||
|
||||
/**
|
||||
* Message metadata key for the transport ID of a local or remote update,
|
||||
* as a BDF string.
|
||||
*/
|
||||
String MSG_KEY_TRANSPORT_ID = "transportId";
|
||||
|
||||
/**
|
||||
* Message metadata key for the version number of a local or remote update,
|
||||
* as a BDF long.
|
||||
*/
|
||||
String MSG_KEY_VERSION = "version";
|
||||
|
||||
/**
|
||||
* Message metadata key for whether an update is local or remote, as a BDF
|
||||
* boolean.
|
||||
*/
|
||||
String MSG_KEY_LOCAL = "local";
|
||||
|
||||
/**
|
||||
* Group metadata key for any discovered transport properties of the
|
||||
* contact, as a BDF dictionary.
|
||||
*/
|
||||
String GROUP_KEY_DISCOVERED = "discovered";
|
||||
}
|
||||
|
||||
@@ -34,6 +34,14 @@ public interface TransportPropertyManager {
|
||||
void addRemoteProperties(Transaction txn, ContactId c,
|
||||
Map<TransportId, TransportProperties> props) throws DbException;
|
||||
|
||||
/**
|
||||
* Stores the given properties discovered from an incoming transport
|
||||
* connection. They will be overridden by any properties received while
|
||||
* adding the contact or synced from the contact.
|
||||
*/
|
||||
void addRemotePropertiesFromConnection(ContactId c, TransportId t,
|
||||
TransportProperties props) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the local transport properties for all transports.
|
||||
*/
|
||||
|
||||
@@ -15,6 +15,8 @@ import org.briarproject.bramble.api.plugin.TransportConnectionReader;
|
||||
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
||||
import org.briarproject.bramble.api.sync.SyncSession;
|
||||
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||
import org.briarproject.bramble.api.transport.KeyManager;
|
||||
@@ -52,6 +54,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
private final HandshakeManager handshakeManager;
|
||||
private final ContactExchangeManager contactExchangeManager;
|
||||
private final ConnectionRegistry connectionRegistry;
|
||||
private final TransportPropertyManager transportPropertyManager;
|
||||
|
||||
@Inject
|
||||
ConnectionManagerImpl(@IoExecutor Executor ioExecutor,
|
||||
@@ -60,7 +63,8 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
SyncSessionFactory syncSessionFactory,
|
||||
HandshakeManager handshakeManager,
|
||||
ContactExchangeManager contactExchangeManager,
|
||||
ConnectionRegistry connectionRegistry) {
|
||||
ConnectionRegistry connectionRegistry,
|
||||
TransportPropertyManager transportPropertyManager) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.keyManager = keyManager;
|
||||
this.streamReaderFactory = streamReaderFactory;
|
||||
@@ -69,6 +73,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
this.handshakeManager = handshakeManager;
|
||||
this.contactExchangeManager = contactExchangeManager;
|
||||
this.connectionRegistry = connectionRegistry;
|
||||
this.transportPropertyManager = transportPropertyManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -269,6 +274,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
private final TransportId transportId;
|
||||
private final TransportConnectionReader reader;
|
||||
private final TransportConnectionWriter writer;
|
||||
private final TransportProperties remote;
|
||||
|
||||
@Nullable
|
||||
private volatile SyncSession outgoingSession = null;
|
||||
@@ -278,6 +284,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
this.transportId = transportId;
|
||||
reader = connection.getReader();
|
||||
writer = connection.getWriter();
|
||||
remote = connection.getRemoteProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -313,13 +320,16 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
// Start the outgoing session on another thread
|
||||
ioExecutor.execute(() -> runOutgoingSession(contactId));
|
||||
try {
|
||||
// Store any transport properties discovered from the connection
|
||||
transportPropertyManager.addRemotePropertiesFromConnection(
|
||||
contactId, transportId, remote);
|
||||
// Create and run the incoming session
|
||||
createIncomingSession(ctx, reader).run();
|
||||
reader.dispose(false, true);
|
||||
// Interrupt the outgoing session so it finishes cleanly
|
||||
SyncSession out = outgoingSession;
|
||||
if (out != null) out.interrupt();
|
||||
} catch (IOException e) {
|
||||
} catch (DbException | IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
onReadError(true);
|
||||
} finally {
|
||||
@@ -375,6 +385,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
private final TransportId transportId;
|
||||
private final TransportConnectionReader reader;
|
||||
private final TransportConnectionWriter writer;
|
||||
private final TransportProperties remote;
|
||||
|
||||
@Nullable
|
||||
private volatile SyncSession outgoingSession = null;
|
||||
@@ -385,6 +396,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
this.transportId = transportId;
|
||||
reader = connection.getReader();
|
||||
writer = connection.getWriter();
|
||||
remote = connection.getRemoteProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -461,13 +473,16 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
connectionRegistry.registerConnection(contactId, transportId,
|
||||
false);
|
||||
try {
|
||||
// Store any transport properties discovered from the connection
|
||||
transportPropertyManager.addRemotePropertiesFromConnection(
|
||||
contactId, transportId, remote);
|
||||
// Create and run the incoming session
|
||||
createIncomingSession(ctx, reader).run();
|
||||
reader.dispose(false, true);
|
||||
// Interrupt the outgoing session so it finishes cleanly
|
||||
SyncSession out = outgoingSession;
|
||||
if (out != null) out.interrupt();
|
||||
} catch (IOException e) {
|
||||
} catch (DbException | IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
onReadError();
|
||||
} finally {
|
||||
|
||||
@@ -37,6 +37,11 @@ import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_DISCOVERED;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_TRANSPORT_ID;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_VERSION;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
@@ -111,10 +116,10 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
try {
|
||||
// Find the latest update for this transport, if any
|
||||
BdfDictionary d = metadataParser.parse(meta);
|
||||
TransportId t = new TransportId(d.getString("transportId"));
|
||||
TransportId t = new TransportId(d.getString(MSG_KEY_TRANSPORT_ID));
|
||||
LatestUpdate latest = findLatest(txn, m.getGroupId(), t, false);
|
||||
if (latest != null) {
|
||||
if (d.getLong("version") > latest.version) {
|
||||
if (d.getLong(MSG_KEY_VERSION) > latest.version) {
|
||||
// This update is newer - delete the previous update
|
||||
db.deleteMessage(txn, latest.messageId);
|
||||
db.deleteMessageMetadata(txn, latest.messageId);
|
||||
@@ -140,6 +145,27 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRemotePropertiesFromConnection(ContactId c, TransportId t,
|
||||
TransportProperties props) throws DbException {
|
||||
if (props.isEmpty()) return;
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
Group g = getContactGroup(db.getContact(txn, c));
|
||||
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(
|
||||
txn, g.getId());
|
||||
BdfDictionary discovered =
|
||||
meta.getOptionalDictionary(GROUP_KEY_DISCOVERED);
|
||||
if (discovered == null) discovered = new BdfDictionary();
|
||||
discovered.putAll(props);
|
||||
meta.put(GROUP_KEY_DISCOVERED, discovered);
|
||||
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
|
||||
});
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<TransportId, TransportProperties> getLocalProperties()
|
||||
throws DbException {
|
||||
@@ -203,12 +229,26 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
Group g = getContactGroup(c);
|
||||
try {
|
||||
// Find the latest remote update
|
||||
TransportProperties remote;
|
||||
LatestUpdate latest = findLatest(txn, g.getId(), t, false);
|
||||
if (latest == null) return new TransportProperties();
|
||||
// Retrieve and parse the latest remote properties
|
||||
BdfList message =
|
||||
clientHelper.getMessageAsList(txn, latest.messageId);
|
||||
return parseProperties(message);
|
||||
if (latest == null) {
|
||||
remote = new TransportProperties();
|
||||
} else {
|
||||
// Retrieve and parse the latest remote properties
|
||||
BdfList message =
|
||||
clientHelper.getMessageAsList(txn, latest.messageId);
|
||||
remote = parseProperties(message);
|
||||
}
|
||||
// Merge in any discovered properties
|
||||
BdfDictionary meta =
|
||||
clientHelper.getGroupMetadataAsDictionary(txn, g.getId());
|
||||
BdfDictionary d = meta.getOptionalDictionary(GROUP_KEY_DISCOVERED);
|
||||
if (d == null) return remote;
|
||||
TransportProperties merged =
|
||||
clientHelper.parseAndValidateTransportProperties(d);
|
||||
// Received properties override discovered properties
|
||||
merged.putAll(remote);
|
||||
return merged;
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
@@ -281,9 +321,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
long now = clock.currentTimeMillis();
|
||||
Message m = clientHelper.createMessage(g, now, body);
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put("transportId", t.getString());
|
||||
meta.put("version", version);
|
||||
meta.put("local", local);
|
||||
meta.put(MSG_KEY_TRANSPORT_ID, t.getString());
|
||||
meta.put(MSG_KEY_VERSION, version);
|
||||
meta.put(MSG_KEY_LOCAL, local);
|
||||
clientHelper.addLocalMessage(txn, m, meta, shared, false);
|
||||
} catch (FormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -302,8 +342,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
.getMessageMetadataAsDictionary(txn, localGroup.getId());
|
||||
for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
|
||||
BdfDictionary meta = e.getValue();
|
||||
TransportId t = new TransportId(meta.getString("transportId"));
|
||||
long version = meta.getLong("version");
|
||||
TransportId t =
|
||||
new TransportId(meta.getString(MSG_KEY_TRANSPORT_ID));
|
||||
long version = meta.getLong(MSG_KEY_VERSION);
|
||||
latestUpdates.put(t, new LatestUpdate(e.getKey(), version));
|
||||
}
|
||||
return latestUpdates;
|
||||
@@ -316,9 +357,10 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
clientHelper.getMessageMetadataAsDictionary(txn, g);
|
||||
for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
|
||||
BdfDictionary meta = e.getValue();
|
||||
if (meta.getString("transportId").equals(t.getString())
|
||||
&& meta.getBoolean("local") == local) {
|
||||
return new LatestUpdate(e.getKey(), meta.getLong("version"));
|
||||
if (meta.getString(MSG_KEY_TRANSPORT_ID).equals(t.getString())
|
||||
&& meta.getBoolean(MSG_KEY_LOCAL) == local) {
|
||||
return new LatestUpdate(e.getKey(),
|
||||
meta.getLong(MSG_KEY_VERSION));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -24,14 +24,18 @@ import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.GROUP_KEY_DISCOVERED;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_TRANSPORT_ID;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MSG_KEY_VERSION;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_ID;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyManager.MAJOR_VERSION;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
@@ -186,25 +190,25 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
Message message = getMessage(contactGroupId);
|
||||
Metadata meta = new Metadata();
|
||||
BdfDictionary metaDictionary = BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 2),
|
||||
new BdfEntry("local", false)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 2),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false)
|
||||
);
|
||||
Map<MessageId, BdfDictionary> messageMetadata =
|
||||
new LinkedHashMap<>();
|
||||
// A remote update for another transport should be ignored
|
||||
MessageId barUpdateId = new MessageId(getRandomId());
|
||||
messageMetadata.put(barUpdateId, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "bar"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", false)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "bar"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false)
|
||||
));
|
||||
// A local update for the same transport should be ignored
|
||||
MessageId localUpdateId = new MessageId(getRandomId());
|
||||
messageMetadata.put(localUpdateId, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", true)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true)
|
||||
));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
@@ -228,18 +232,18 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
Metadata meta = new Metadata();
|
||||
// Version 4 is being delivered
|
||||
BdfDictionary metaDictionary = BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 4),
|
||||
new BdfEntry("local", false)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 4),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false)
|
||||
);
|
||||
Map<MessageId, BdfDictionary> messageMetadata =
|
||||
new LinkedHashMap<>();
|
||||
// An older remote update for the same transport should be deleted
|
||||
MessageId fooVersion3 = new MessageId(getRandomId());
|
||||
messageMetadata.put(fooVersion3, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 3),
|
||||
new BdfEntry("local", false)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 3),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false)
|
||||
));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
@@ -265,18 +269,18 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
Metadata meta = new Metadata();
|
||||
// Version 3 is being delivered
|
||||
BdfDictionary metaDictionary = BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 3),
|
||||
new BdfEntry("local", false)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 3),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false)
|
||||
);
|
||||
Map<MessageId, BdfDictionary> messageMetadata =
|
||||
new LinkedHashMap<>();
|
||||
// A newer remote update for the same transport should not be deleted
|
||||
MessageId fooVersion4 = new MessageId(getRandomId());
|
||||
messageMetadata.put(fooVersion4, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 4),
|
||||
new BdfEntry("local", false)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 4),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false)
|
||||
));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
@@ -342,9 +346,9 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
// A local update for another transport should be ignored
|
||||
MessageId barUpdateId = new MessageId(getRandomId());
|
||||
messageMetadata.put(barUpdateId, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "bar"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", true)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "bar"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true)
|
||||
));
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
@@ -366,16 +370,16 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
// A local update for another transport should be ignored
|
||||
MessageId barUpdateId = new MessageId(getRandomId());
|
||||
messageMetadata.put(barUpdateId, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "bar"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", true)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "bar"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true)
|
||||
));
|
||||
// A local update for the right transport should be returned
|
||||
MessageId fooUpdateId = new MessageId(getRandomId());
|
||||
messageMetadata.put(fooUpdateId, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", true)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true)
|
||||
));
|
||||
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
|
||||
|
||||
@@ -405,28 +409,28 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
List<Contact> contacts = asList(contact1, contact2);
|
||||
Group contactGroup1 = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
Group contactGroup2 = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
Map<MessageId, BdfDictionary> messageMetadata2 =
|
||||
Map<MessageId, BdfDictionary> messageMetadata =
|
||||
new LinkedHashMap<>();
|
||||
// A remote update for another transport should be ignored
|
||||
MessageId barUpdateId = new MessageId(getRandomId());
|
||||
messageMetadata2.put(barUpdateId, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "bar"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", false)
|
||||
messageMetadata.put(barUpdateId, BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "bar"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false)
|
||||
));
|
||||
// A local update for the right transport should be ignored
|
||||
MessageId localUpdateId = new MessageId(getRandomId());
|
||||
messageMetadata2.put(localUpdateId, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", true)
|
||||
messageMetadata.put(localUpdateId, BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true)
|
||||
));
|
||||
// A remote update for the right transport should be returned
|
||||
MessageId fooUpdateId = new MessageId(getRandomId());
|
||||
messageMetadata2.put(fooUpdateId, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", false)
|
||||
messageMetadata.put(fooUpdateId, BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false)
|
||||
));
|
||||
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
|
||||
|
||||
@@ -440,19 +444,25 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(contactGroup1));
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup1.getId());
|
||||
will(returnValue(Collections.emptyMap()));
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup1.getId());
|
||||
will(returnValue(new BdfDictionary()));
|
||||
// Second contact: returns an update
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
|
||||
MAJOR_VERSION, contact2);
|
||||
will(returnValue(contactGroup2));
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup2.getId());
|
||||
will(returnValue(messageMetadata2));
|
||||
will(returnValue(messageMetadata));
|
||||
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
|
||||
will(returnValue(fooUpdate));
|
||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||
fooPropertiesDict);
|
||||
will(returnValue(fooProperties));
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup2.getId());
|
||||
will(returnValue(new BdfDictionary()));
|
||||
}});
|
||||
|
||||
TransportPropertyManagerImpl t = createInstance();
|
||||
@@ -463,6 +473,62 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
assertEquals(fooProperties, properties.get(contact2.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReceivePropertiesOverrideDiscoveredProperties()
|
||||
throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
Contact contact = getContact();
|
||||
List<Contact> contacts = singletonList(contact);
|
||||
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
MessageId updateId = new MessageId(getRandomId());
|
||||
Map<MessageId, BdfDictionary> messageMetadata = singletonMap(updateId,
|
||||
BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false)
|
||||
));
|
||||
BdfList update = BdfList.of("foo", 1, fooPropertiesDict);
|
||||
TransportProperties discovered = new TransportProperties();
|
||||
discovered.put("fooKey1", "overridden");
|
||||
discovered.put("fooKey3", "fooValue3");
|
||||
BdfDictionary discoveredDict = new BdfDictionary(discovered);
|
||||
BdfDictionary groupMeta = BdfDictionary.of(
|
||||
new BdfEntry(GROUP_KEY_DISCOVERED, discoveredDict)
|
||||
);
|
||||
TransportProperties merged = new TransportProperties();
|
||||
merged.putAll(fooProperties);
|
||||
merged.put("fooKey3", "fooValue3");
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(contacts));
|
||||
// One update
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
|
||||
MAJOR_VERSION, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(messageMetadata));
|
||||
oneOf(clientHelper).getMessageAsList(txn, updateId);
|
||||
will(returnValue(update));
|
||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||
fooPropertiesDict);
|
||||
will(returnValue(fooProperties));
|
||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(groupMeta));
|
||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||
discoveredDict);
|
||||
will(returnValue(discovered));
|
||||
}});
|
||||
|
||||
TransportPropertyManagerImpl t = createInstance();
|
||||
Map<ContactId, TransportProperties> properties =
|
||||
t.getRemoteProperties(new TransportId("foo"));
|
||||
assertEquals(merged, properties.get(contact.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergingUnchangedPropertiesDoesNotCreateUpdate()
|
||||
throws Exception {
|
||||
@@ -470,9 +536,9 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
MessageId updateId = new MessageId(getRandomId());
|
||||
Map<MessageId, BdfDictionary> messageMetadata = singletonMap(updateId,
|
||||
BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", true)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true)
|
||||
));
|
||||
BdfList update = BdfList.of("foo", 1, fooPropertiesDict);
|
||||
|
||||
@@ -505,7 +571,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
// There are no existing properties to merge with
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
will(returnValue(Collections.emptyMap()));
|
||||
will(returnValue(emptyMap()));
|
||||
// Store the new properties in the local group, version 1
|
||||
expectStoreMessage(txn, localGroup.getId(), "foo",
|
||||
fooPropertiesDict, 1, true, false);
|
||||
@@ -517,7 +583,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
contactGroup.getId());
|
||||
will(returnValue(Collections.emptyMap()));
|
||||
will(returnValue(emptyMap()));
|
||||
expectStoreMessage(txn, contactGroup.getId(), "foo",
|
||||
fooPropertiesDict, 1, true, true);
|
||||
}});
|
||||
@@ -532,9 +598,9 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
Contact contact = getContact();
|
||||
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
BdfDictionary oldMetadata = BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", true)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 1),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true)
|
||||
);
|
||||
MessageId localGroupUpdateId = new MessageId(getRandomId());
|
||||
Map<MessageId, BdfDictionary> localGroupMessageMetadata =
|
||||
@@ -589,14 +655,14 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
// The latest update for transport "foo" should be returned
|
||||
MessageId fooVersion999 = new MessageId(getRandomId());
|
||||
messageMetadata.put(fooVersion999, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 999)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "foo"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 999)
|
||||
));
|
||||
// The latest update for transport "bar" should be returned
|
||||
MessageId barVersion3 = new MessageId(getRandomId());
|
||||
messageMetadata.put(barVersion3, BdfDictionary.of(
|
||||
new BdfEntry("transportId", "bar"),
|
||||
new BdfEntry("version", 3)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, "bar"),
|
||||
new BdfEntry(MSG_KEY_VERSION, 3)
|
||||
));
|
||||
BdfList fooUpdate = BdfList.of("foo", 999, fooPropertiesDict);
|
||||
BdfList barUpdate = BdfList.of("bar", 3, barPropertiesDict);
|
||||
@@ -627,9 +693,9 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
Message message = getMessage(g);
|
||||
long timestamp = message.getTimestamp();
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry("transportId", transportId),
|
||||
new BdfEntry("version", version),
|
||||
new BdfEntry("local", local)
|
||||
new BdfEntry(MSG_KEY_TRANSPORT_ID, transportId),
|
||||
new BdfEntry(MSG_KEY_VERSION, version),
|
||||
new BdfEntry(MSG_KEY_LOCAL, local)
|
||||
);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
|
||||
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -37,6 +38,11 @@ public class TestDuplexTransportConnection
|
||||
return writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportProperties getRemoteProperties() {
|
||||
return new TransportProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a pair of TestDuplexTransportConnections that are
|
||||
* connected to each other.
|
||||
|
||||
Reference in New Issue
Block a user