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:
akwizgran
2020-04-29 15:31:30 +00:00
10 changed files with 261 additions and 80 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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";
}

View File

@@ -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.
*/

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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() {{

View File

@@ -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.