From ae1d1fc5a739738793dbc1a1e96b2f01397e35fb Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 13 Jun 2019 15:47:43 +0100 Subject: [PATCH 1/8] Add thread safety and null safety annotations. --- .../main/java/org/briarproject/bramble/api/sync/Ack.java | 6 ++++++ .../java/org/briarproject/bramble/api/sync/Message.java | 6 ++++++ .../main/java/org/briarproject/bramble/api/sync/Offer.java | 6 ++++++ .../java/org/briarproject/bramble/api/sync/Request.java | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Ack.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Ack.java index 1333e0f4b..0f21a64ea 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Ack.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Ack.java @@ -1,10 +1,16 @@ package org.briarproject.bramble.api.sync; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + import java.util.Collection; +import javax.annotation.concurrent.Immutable; + /** * A record acknowledging receipt of one or more {@link Message Messages}. */ +@Immutable +@NotNullByDefault public class Ack { private final Collection acked; diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Message.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Message.java index e99bf5cef..b2f30debd 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Message.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Message.java @@ -1,8 +1,14 @@ package org.briarproject.bramble.api.sync; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import javax.annotation.concurrent.Immutable; + import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; +@Immutable +@NotNullByDefault public class Message { /** diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Offer.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Offer.java index 4fff0608e..6cfeb5b04 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Offer.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Offer.java @@ -1,10 +1,16 @@ package org.briarproject.bramble.api.sync; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + import java.util.Collection; +import javax.annotation.concurrent.Immutable; + /** * A record offering the recipient one or more {@link Message Messages}. */ +@Immutable +@NotNullByDefault public class Offer { private final Collection offered; diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Request.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Request.java index 9d20fdc19..f4e6e1f2c 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Request.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Request.java @@ -1,10 +1,16 @@ package org.briarproject.bramble.api.sync; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + import java.util.Collection; +import javax.annotation.concurrent.Immutable; + /** * A record requesting one or more {@link Message Messages} from the recipient. */ +@Immutable +@NotNullByDefault public class Request { private final Collection requested; From c228e5c21909a142e896199783833c36ffddd160 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 13 Jun 2019 16:03:31 +0100 Subject: [PATCH 2/8] Add versions record to sync protocol. --- .../bramble/api/sync/RecordTypes.java | 2 +- .../bramble/api/sync/SyncConstants.java | 6 ++ .../bramble/api/sync/SyncRecordReader.java | 3 + .../bramble/api/sync/SyncRecordWriter.java | 2 + .../bramble/api/sync/Versions.java | 26 +++++++++ .../bramble/sync/SyncRecordReaderImpl.java | 28 ++++++++- .../bramble/sync/SyncRecordWriterImpl.java | 8 +++ .../sync/SyncRecordReaderImplTest.java | 57 +++++++++++++++---- 8 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/Versions.java diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/RecordTypes.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/RecordTypes.java index c8d08bdc4..168b4c9ef 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/RecordTypes.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/RecordTypes.java @@ -9,5 +9,5 @@ public interface RecordTypes { byte MESSAGE = 1; byte OFFER = 2; byte REQUEST = 3; - + byte VERSIONS = 4; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java index a6e3474f3..422a15117 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java @@ -35,4 +35,10 @@ public interface SyncConstants { * The maximum number of message IDs in an ack, offer or request record. */ int MAX_MESSAGE_IDS = MAX_RECORD_PAYLOAD_BYTES / UniqueId.LENGTH; + + /** + * The maximum number of versions of the sync protocol a peer may support + * simultaneously. + */ + int MAX_SUPPORTED_VERSIONS = 10; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncRecordReader.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncRecordReader.java index 374a71208..55650e407 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncRecordReader.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncRecordReader.java @@ -25,4 +25,7 @@ public interface SyncRecordReader { Request readRequest() throws IOException; + boolean hasVersions() throws IOException; + + Versions readVersions() throws IOException; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncRecordWriter.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncRecordWriter.java index 1c2600ad7..bdeca0cf8 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncRecordWriter.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncRecordWriter.java @@ -15,5 +15,7 @@ public interface SyncRecordWriter { void writeRequest(Request r) throws IOException; + void writeVersions(Versions v) throws IOException; + void flush() throws IOException; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Versions.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Versions.java new file mode 100644 index 000000000..9517d02e6 --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/Versions.java @@ -0,0 +1,26 @@ +package org.briarproject.bramble.api.sync; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.util.List; + +import javax.annotation.concurrent.Immutable; + +/** + * A record telling the recipient which versions of the sync protocol the + * sender supports. + */ +@Immutable +@NotNullByDefault +public class Versions { + + private final List supported; + + public Versions(List supported) { + this.supported = supported; + } + + public List getSupportedVersions() { + return supported; + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java index 02b3a4154..7ea0f6a41 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java @@ -13,6 +13,7 @@ import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.Offer; import org.briarproject.bramble.api.sync.Request; import org.briarproject.bramble.api.sync.SyncRecordReader; +import org.briarproject.bramble.api.sync.Versions; import org.briarproject.bramble.util.ByteUtils; import java.io.IOException; @@ -26,6 +27,8 @@ import static org.briarproject.bramble.api.sync.RecordTypes.ACK; import static org.briarproject.bramble.api.sync.RecordTypes.MESSAGE; import static org.briarproject.bramble.api.sync.RecordTypes.OFFER; import static org.briarproject.bramble.api.sync.RecordTypes.REQUEST; +import static org.briarproject.bramble.api.sync.RecordTypes.VERSIONS; +import static org.briarproject.bramble.api.sync.SyncConstants.MAX_SUPPORTED_VERSIONS; import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION; @@ -45,7 +48,7 @@ class SyncRecordReaderImpl implements SyncRecordReader { private static boolean isKnownRecordType(byte type) { return type == ACK || type == MESSAGE || type == OFFER || - type == REQUEST; + type == REQUEST || type == VERSIONS; } private final MessageFactory messageFactory; @@ -148,4 +151,27 @@ class SyncRecordReaderImpl implements SyncRecordReader { if (!hasRequest()) throw new FormatException(); return new Request(readMessageIds()); } + + @Override + public boolean hasVersions() throws IOException { + return !eof() && getNextRecordType() == VERSIONS; + } + + @Override + public Versions readVersions() throws IOException { + if (!hasVersions()) throw new FormatException(); + return new Versions(readSupportedVersions()); + } + + private List readSupportedVersions() throws IOException { + if (nextRecord == null) throw new AssertionError(); + byte[] payload = nextRecord.getPayload(); + if (payload.length == 0) throw new FormatException(); + if (payload.length > MAX_SUPPORTED_VERSIONS) + throw new FormatException(); + List supported = new ArrayList<>(payload.length); + for (byte b : payload) supported.add(b); + nextRecord = null; + return supported; + } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordWriterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordWriterImpl.java index 583f4eb62..118cc51cd 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordWriterImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordWriterImpl.java @@ -10,6 +10,7 @@ import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.Offer; import org.briarproject.bramble.api.sync.Request; import org.briarproject.bramble.api.sync.SyncRecordWriter; +import org.briarproject.bramble.api.sync.Versions; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -20,6 +21,7 @@ import static org.briarproject.bramble.api.sync.RecordTypes.ACK; import static org.briarproject.bramble.api.sync.RecordTypes.MESSAGE; import static org.briarproject.bramble.api.sync.RecordTypes.OFFER; import static org.briarproject.bramble.api.sync.RecordTypes.REQUEST; +import static org.briarproject.bramble.api.sync.RecordTypes.VERSIONS; import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION; @NotThreadSafe @@ -65,6 +67,12 @@ class SyncRecordWriterImpl implements SyncRecordWriter { writeRecord(REQUEST); } + @Override + public void writeVersions(Versions v) throws IOException { + for (byte b : v.getSupportedVersions()) payload.write(b); + writeRecord(VERSIONS); + } + @Override public void flush() throws IOException { writer.flush(); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncRecordReaderImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncRecordReaderImplTest.java index ae52af979..667c2b557 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncRecordReaderImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncRecordReaderImplTest.java @@ -10,11 +10,14 @@ import org.briarproject.bramble.api.sync.MessageFactory; import org.briarproject.bramble.api.sync.Offer; import org.briarproject.bramble.api.sync.Request; import org.briarproject.bramble.api.sync.SyncRecordReader; +import org.briarproject.bramble.api.sync.Versions; import org.briarproject.bramble.test.BrambleMockTestCase; import org.jmock.Expectations; +import org.junit.Before; import org.junit.Test; import java.io.ByteArrayOutputStream; +import java.util.List; import javax.annotation.Nullable; @@ -22,7 +25,9 @@ import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTE import static org.briarproject.bramble.api.sync.RecordTypes.ACK; import static org.briarproject.bramble.api.sync.RecordTypes.OFFER; import static org.briarproject.bramble.api.sync.RecordTypes.REQUEST; +import static org.briarproject.bramble.api.sync.RecordTypes.VERSIONS; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS; +import static org.briarproject.bramble.api.sync.SyncConstants.MAX_SUPPORTED_VERSIONS; import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION; import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.junit.Assert.assertEquals; @@ -35,12 +40,17 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase { context.mock(MessageFactory.class); private final RecordReader recordReader = context.mock(RecordReader.class); + private SyncRecordReader reader; + + @Before + public void setUp() { + reader = new SyncRecordReaderImpl(messageFactory, recordReader); + } + @Test public void testNoFormatExceptionIfAckIsMaximumSize() throws Exception { expectReadRecord(createAck()); - SyncRecordReader reader = - new SyncRecordReaderImpl(messageFactory, recordReader); Ack ack = reader.readAck(); assertEquals(MAX_MESSAGE_IDS, ack.getMessageIds().size()); } @@ -49,8 +59,6 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase { public void testFormatExceptionIfAckIsEmpty() throws Exception { expectReadRecord(createEmptyAck()); - SyncRecordReader reader = - new SyncRecordReaderImpl(messageFactory, recordReader); reader.readAck(); } @@ -58,8 +66,6 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase { public void testNoFormatExceptionIfOfferIsMaximumSize() throws Exception { expectReadRecord(createOffer()); - SyncRecordReader reader = - new SyncRecordReaderImpl(messageFactory, recordReader); Offer offer = reader.readOffer(); assertEquals(MAX_MESSAGE_IDS, offer.getMessageIds().size()); } @@ -68,8 +74,6 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase { public void testFormatExceptionIfOfferIsEmpty() throws Exception { expectReadRecord(createEmptyOffer()); - SyncRecordReader reader = - new SyncRecordReaderImpl(messageFactory, recordReader); reader.readOffer(); } @@ -77,8 +81,6 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase { public void testNoFormatExceptionIfRequestIsMaximumSize() throws Exception { expectReadRecord(createRequest()); - SyncRecordReader reader = - new SyncRecordReaderImpl(messageFactory, recordReader); Request request = reader.readRequest(); assertEquals(MAX_MESSAGE_IDS, request.getMessageIds().size()); } @@ -87,11 +89,36 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase { public void testFormatExceptionIfRequestIsEmpty() throws Exception { expectReadRecord(createEmptyRequest()); - SyncRecordReader reader = - new SyncRecordReaderImpl(messageFactory, recordReader); reader.readRequest(); } + @Test + public void testNoFormatExceptionIfVersionsIsMaximumSize() + throws Exception { + expectReadRecord(createVersions(MAX_SUPPORTED_VERSIONS)); + + Versions versions = reader.readVersions(); + List supported = versions.getSupportedVersions(); + assertEquals(MAX_SUPPORTED_VERSIONS, supported.size()); + for (int i = 0; i < supported.size(); i++) { + assertEquals(i, (int) supported.get(i)); + } + } + + @Test(expected = FormatException.class) + public void testFormatExceptionIfVersionsIsEmpty() throws Exception { + expectReadRecord(createVersions(0)); + + reader.readVersions(); + } + + @Test(expected = FormatException.class) + public void testFormatExceptionIfVersionsIsTooLarge() throws Exception { + expectReadRecord(createVersions(MAX_SUPPORTED_VERSIONS + 1)); + + reader.readVersions(); + } + @Test public void testEofReturnsTrueWhenAtEndOfStream() throws Exception { expectReadRecord(createAck()); @@ -140,6 +167,12 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase { return new Record(PROTOCOL_VERSION, REQUEST, new byte[0]); } + private Record createVersions(int numVersions) { + byte[] payload = new byte[numVersions]; + for (int i = 0; i < payload.length; i++) payload[i] = (byte) i; + return new Record(PROTOCOL_VERSION, VERSIONS, payload); + } + private byte[] createPayload() throws Exception { ByteArrayOutputStream payload = new ByteArrayOutputStream(); while (payload.size() + UniqueId.LENGTH <= MAX_RECORD_PAYLOAD_BYTES) { From 132e20a6ce63deb730332f382d91409e79791287 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 13 Jun 2019 16:14:51 +0100 Subject: [PATCH 3/8] Send versions record at start of each session. --- .../org/briarproject/bramble/api/sync/SyncConstants.java | 8 ++++++++ .../briarproject/bramble/sync/DuplexOutgoingSession.java | 7 ++++++- .../org/briarproject/bramble/sync/IncomingSession.java | 9 +++++++++ .../bramble/sync/SimplexOutgoingSession.java | 7 ++++++- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java index 422a15117..c430ac05f 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/SyncConstants.java @@ -2,6 +2,9 @@ package org.briarproject.bramble.api.sync; import org.briarproject.bramble.api.UniqueId; +import java.util.List; + +import static java.util.Collections.singletonList; import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES; public interface SyncConstants { @@ -11,6 +14,11 @@ public interface SyncConstants { */ byte PROTOCOL_VERSION = 0; + /** + * The versions of the sync protocol this peer supports. + */ + List SUPPORTED_VERSIONS = singletonList(PROTOCOL_VERSION); + /** * The maximum length of a group descriptor in bytes. */ diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java index 00c50f16c..0aa1a8985 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java @@ -17,6 +17,7 @@ import org.briarproject.bramble.api.sync.Offer; import org.briarproject.bramble.api.sync.Request; import org.briarproject.bramble.api.sync.SyncRecordWriter; import org.briarproject.bramble.api.sync.SyncSession; +import org.briarproject.bramble.api.sync.Versions; import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent; import org.briarproject.bramble.api.sync.event.MessageRequestedEvent; import org.briarproject.bramble.api.sync.event.MessageSharedEvent; @@ -39,9 +40,11 @@ import javax.annotation.concurrent.ThreadSafe; import static java.util.concurrent.TimeUnit.MILLISECONDS; 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.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS; +import static org.briarproject.bramble.api.sync.SyncConstants.SUPPORTED_VERSIONS; import static org.briarproject.bramble.util.LogUtils.logException; /** @@ -55,7 +58,7 @@ import static org.briarproject.bramble.util.LogUtils.logException; class DuplexOutgoingSession implements SyncSession, EventListener { private static final Logger LOG = - Logger.getLogger(DuplexOutgoingSession.class.getName()); + getLogger(DuplexOutgoingSession.class.getName()); private static final ThrowingRunnable CLOSE = () -> { }; @@ -103,6 +106,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener { public void run() throws IOException { eventBus.addListener(this); try { + // Send our supported protocol versions + recordWriter.writeVersions(new Versions(SUPPORTED_VERSIONS)); // Start a query for each type of record generateAck(); generateBatch(); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java index 6e1e2987d..ae2c26978 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java @@ -18,6 +18,7 @@ import org.briarproject.bramble.api.sync.Offer; import org.briarproject.bramble.api.sync.Request; import org.briarproject.bramble.api.sync.SyncRecordReader; import org.briarproject.bramble.api.sync.SyncSession; +import org.briarproject.bramble.api.sync.Versions; import java.io.IOException; import java.util.concurrent.Executor; @@ -25,6 +26,7 @@ import java.util.logging.Logger; import javax.annotation.concurrent.ThreadSafe; +import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.util.LogUtils.logException; @@ -80,6 +82,13 @@ class IncomingSession implements SyncSession, EventListener { } else if (recordReader.hasRequest()) { Request r = recordReader.readRequest(); dbExecutor.execute(new ReceiveRequest(r)); + } else if (recordReader.hasVersions()) { + Versions v = recordReader.readVersions(); + // TODO: Store remote peer's supported versions + if (LOG.isLoggable(INFO)) { + LOG.info("Received supported versions: " + + v.getSupportedVersions()); + } } else { // unknown records are ignored in RecordReader#eof() throw new FormatException(); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java index ecc7c26bb..9e1e62909 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java @@ -15,6 +15,7 @@ import org.briarproject.bramble.api.sync.Ack; import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.SyncRecordWriter; import org.briarproject.bramble.api.sync.SyncSession; +import org.briarproject.bramble.api.sync.Versions; import org.briarproject.bramble.api.transport.StreamWriter; import java.io.IOException; @@ -29,9 +30,11 @@ import javax.annotation.concurrent.ThreadSafe; 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.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS; +import static org.briarproject.bramble.api.sync.SyncConstants.SUPPORTED_VERSIONS; import static org.briarproject.bramble.util.LogUtils.logException; /** @@ -44,7 +47,7 @@ import static org.briarproject.bramble.util.LogUtils.logException; class SimplexOutgoingSession implements SyncSession, EventListener { private static final Logger LOG = - Logger.getLogger(SimplexOutgoingSession.class.getName()); + getLogger(SimplexOutgoingSession.class.getName()); private static final ThrowingRunnable CLOSE = () -> { }; @@ -80,6 +83,8 @@ class SimplexOutgoingSession implements SyncSession, EventListener { public void run() throws IOException { eventBus.addListener(this); try { + // Send our supported protocol versions + recordWriter.writeVersions(new Versions(SUPPORTED_VERSIONS)); // Start a query for each type of record dbExecutor.execute(new GenerateAck()); dbExecutor.execute(new GenerateBatch()); From 3636aeba9acd46d5435deaa13dbdfcaa7f9fd371 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 13 Jun 2019 16:34:20 +0100 Subject: [PATCH 4/8] Use HyperSQL-compatible syntax in migration. --- .../main/java/org/briarproject/bramble/db/Migration45_46.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Migration45_46.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Migration45_46.java index a6c31dba5..4cbbc05b0 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Migration45_46.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Migration45_46.java @@ -31,8 +31,7 @@ class Migration45_46 implements Migration { try { s = txn.createStatement(); s.execute("ALTER TABLE messages" - + " ADD COLUMN temporary BOOLEAN NOT NULL" - + " DEFAULT (FALSE)"); + + " ADD COLUMN temporary BOOLEAN DEFAULT FALSE NOT NULL"); } catch (SQLException e) { tryToClose(s, LOG, WARNING); throw new DbException(e); From 1e259c100dcd3ee19f7507e145eddd6f27aff83b Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 13 Jun 2019 16:35:48 +0100 Subject: [PATCH 5/8] Add sync versions column to contacts table. --- .../briarproject/bramble/db/JdbcDatabase.java | 6 ++- .../bramble/db/Migration46_47.java | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/db/Migration46_47.java diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java index 058c33726..377ba90a3 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java @@ -98,7 +98,7 @@ import static org.briarproject.bramble.util.LogUtils.now; abstract class JdbcDatabase implements Database { // Package access for testing - static final int CODE_SCHEMA_VERSION = 46; + static final int CODE_SCHEMA_VERSION = 47; // Time period offsets for incoming transport keys private static final int OFFSET_PREV = -1; @@ -135,6 +135,7 @@ abstract class JdbcDatabase implements Database { + " handshakePublicKey _BINARY," // Null if key is unknown + " localAuthorId _HASH NOT NULL," + " verified BOOLEAN NOT NULL," + + " syncVersions _BINARY DEFAULT '00' NOT NULL," + " PRIMARY KEY (contactId)," + " FOREIGN KEY (localAuthorId)" + " REFERENCES localAuthors (authorId)" @@ -461,7 +462,8 @@ abstract class JdbcDatabase implements Database { new Migration42_43(dbTypes), new Migration43_44(dbTypes), new Migration44_45(), - new Migration45_46() + new Migration45_46(), + new Migration46_47(dbTypes) ); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Migration46_47.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Migration46_47.java new file mode 100644 index 000000000..da14f5d36 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Migration46_47.java @@ -0,0 +1,47 @@ +package org.briarproject.bramble.db; + +import org.briarproject.bramble.api.db.DbException; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.logging.Logger; + +import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.db.JdbcUtils.tryToClose; + +class Migration46_47 implements Migration { + + private static final Logger LOG = getLogger(Migration46_47.class.getName()); + + private final DatabaseTypes dbTypes; + + Migration46_47(DatabaseTypes dbTypes) { + this.dbTypes = dbTypes; + } + + @Override + public int getStartVersion() { + return 46; + } + + @Override + public int getEndVersion() { + return 47; + } + + @Override + public void migrate(Connection txn) throws DbException { + Statement s = null; + try { + s = txn.createStatement(); + s.execute(dbTypes.replaceTypes("ALTER TABLE contacts" + + " ADD COLUMN syncVersions" + + " _BINARY DEFAULT '00' NOT NULL")); + } catch (SQLException e) { + tryToClose(s, LOG, WARNING); + throw new DbException(e); + } + } +} From f2c951b70b07cb6753aa1c1c274183a0537ee383 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 13 Jun 2019 16:56:58 +0100 Subject: [PATCH 6/8] Add DB methods for getting and setting sync versions. --- .../bramble/api/db/DatabaseComponent.java | 14 ++++++ .../sync/event/SyncVersionsUpdatedEvent.java | 34 +++++++++++++ .../org/briarproject/bramble/db/Database.java | 14 ++++++ .../bramble/db/DatabaseComponentImpl.java | 21 ++++++++ .../briarproject/bramble/db/JdbcDatabase.java | 49 +++++++++++++++++++ .../bramble/db/DatabaseComponentImplTest.java | 23 +++++++-- .../bramble/db/JdbcDatabaseTest.java | 31 ++++++++++-- 7 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/SyncVersionsUpdatedEvent.java diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index a5d8dc653..58f8a8f06 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -29,6 +29,7 @@ import org.briarproject.bramble.api.transport.TransportKeySet; import org.briarproject.bramble.api.transport.TransportKeys; import java.util.Collection; +import java.util.List; import java.util.Map; import javax.annotation.Nullable; @@ -427,6 +428,13 @@ public interface DatabaseComponent extends TransactionManager { */ Settings getSettings(Transaction txn, String namespace) throws DbException; + /** + * Returns the versions of the sync protocol supported by the given contact. + *

+ * Read-only. + */ + List getSyncVersions(Transaction txn, ContactId c) throws DbException; + /** * Returns all transport keys for the given transport. *

@@ -579,6 +587,12 @@ public interface DatabaseComponent extends TransactionManager { void setReorderingWindow(Transaction txn, KeySetId k, TransportId t, long timePeriod, long base, byte[] bitmap) throws DbException; + /** + * Sets the versions of the sync protocol supported by the given contact. + */ + void setSyncVersions(Transaction txn, ContactId c, List supported) + throws DbException; + /** * Marks the given transport keys as usable for outgoing streams. */ diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/SyncVersionsUpdatedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/SyncVersionsUpdatedEvent.java new file mode 100644 index 000000000..00d1f5b7b --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/event/SyncVersionsUpdatedEvent.java @@ -0,0 +1,34 @@ +package org.briarproject.bramble.api.sync.event; + +import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.event.Event; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.util.List; + +import javax.annotation.concurrent.Immutable; + +/** + * An event that is broadcast when the versions of the sync protocol supported + * by a contact are updated. + */ +@Immutable +@NotNullByDefault +public class SyncVersionsUpdatedEvent extends Event { + + private final ContactId contactId; + private final List supported; + + public SyncVersionsUpdatedEvent(ContactId contactId, List supported) { + this.contactId = contactId; + this.supported = supported; + } + + public ContactId getContactId() { + return contactId; + } + + public List getSupportedVersions() { + return supported; + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java index 395800eac..469204c67 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java @@ -33,6 +33,7 @@ import org.briarproject.bramble.api.transport.TransportKeySet; import org.briarproject.bramble.api.transport.TransportKeys; import java.util.Collection; +import java.util.List; import java.util.Map; import javax.annotation.Nullable; @@ -528,6 +529,13 @@ interface Database { */ Settings getSettings(T txn, String namespace) throws DbException; + /** + * Returns the versions of the sync protocol supported by the given contact. + *

+ * Read-only. + */ + List getSyncVersions(T txn, ContactId c) throws DbException; + /** * Returns all transport keys for the given transport. *

@@ -700,6 +708,12 @@ interface Database { void setReorderingWindow(T txn, KeySetId k, TransportId t, long timePeriod, long base, byte[] bitmap) throws DbException; + /** + * Sets the versions of the sync protocol supported by the given contact. + */ + void setSyncVersions(T txn, ContactId c, List supported) + throws DbException; + /** * Marks the given transport keys as usable for outgoing streams. */ diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 8023763b4..1a73c89f0 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -65,6 +65,7 @@ import org.briarproject.bramble.api.sync.event.MessageToAckEvent; import org.briarproject.bramble.api.sync.event.MessageToRequestEvent; import org.briarproject.bramble.api.sync.event.MessagesAckedEvent; import org.briarproject.bramble.api.sync.event.MessagesSentEvent; +import org.briarproject.bramble.api.sync.event.SyncVersionsUpdatedEvent; import org.briarproject.bramble.api.sync.validation.MessageState; import org.briarproject.bramble.api.transport.KeySetId; import org.briarproject.bramble.api.transport.TransportKeySet; @@ -716,6 +717,15 @@ class DatabaseComponentImpl implements DatabaseComponent { return db.getSettings(txn, namespace); } + @Override + public List getSyncVersions(Transaction transaction, ContactId c) + throws DbException { + T txn = unbox(transaction); + if (!db.containsContact(txn, c)) + throw new NoSuchContactException(); + return db.getSyncVersions(txn, c); + } + @Override public Collection getTransportKeys(Transaction transaction, TransportId t) throws DbException { @@ -1046,6 +1056,17 @@ class DatabaseComponentImpl implements DatabaseComponent { db.setReorderingWindow(txn, k, t, timePeriod, base, bitmap); } + @Override + public void setSyncVersions(Transaction transaction, ContactId c, + List supported) throws DbException { + if (transaction.isReadOnly()) throw new IllegalArgumentException(); + T txn = unbox(transaction); + if (!db.containsContact(txn, c)) + throw new NoSuchContactException(); + db.setSyncVersions(txn, c, supported); + transaction.attach(new SyncVersionsUpdatedEvent(c, supported)); + } + @Override public void setTransportKeysActive(Transaction transaction, TransportId t, KeySetId k) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java index 377ba90a3..f1e0d013c 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java @@ -2330,6 +2330,32 @@ abstract class JdbcDatabase implements Database { } } + @Override + public List getSyncVersions(Connection txn, ContactId c) + throws DbException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + String sql = "SELECT syncVersions FROM contacts" + + " WHERE contactId = ?"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + rs = ps.executeQuery(); + if (!rs.next()) throw new DbStateException(); + byte[] bytes = rs.getBytes(1); + List supported = new ArrayList<>(bytes.length); + for (byte b : bytes) supported.add(b); + if (rs.next()) throw new DbStateException(); + rs.close(); + ps.close(); + return supported; + } catch (SQLException e) { + tryToClose(rs, LOG, WARNING); + tryToClose(ps, LOG, WARNING); + throw new DbException(e); + } + } + @Override public Collection getTransportKeys(Connection txn, TransportId t) throws DbException { @@ -3163,6 +3189,29 @@ abstract class JdbcDatabase implements Database { } } + @Override + public void setSyncVersions(Connection txn, ContactId c, + List supported) throws DbException { + PreparedStatement ps = null; + try { + String sql = "UPDATE contacts SET syncVersions = ?" + + " WHERE contactId = ?"; + ps = txn.prepareStatement(sql); + byte[] bytes = new byte[supported.size()]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = supported.get(i); + } + ps.setBytes(1, bytes); + ps.setInt(2, c.getInt()); + int affected = ps.executeUpdate(); + if (affected < 0 || affected > 1) throw new DbStateException(); + ps.close(); + } catch (SQLException e) { + tryToClose(ps, LOG, WARNING); + throw new DbException(e); + } + } + @Override public void setTransportKeysActive(Connection txn, TransportId t, KeySetId k) throws DbException { diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java index 8ef5f4d67..b8fb04bc8 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java @@ -66,6 +66,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicReference; import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; @@ -294,11 +295,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { throws Exception { context.checking(new Expectations() {{ // Check whether the contact is in the DB (which it's not) - exactly(16).of(database).startTransaction(); + exactly(18).of(database).startTransaction(); will(returnValue(txn)); - exactly(16).of(database).containsContact(txn, contactId); + exactly(18).of(database).containsContact(txn, contactId); will(returnValue(false)); - exactly(16).of(database).abortTransaction(txn); + exactly(18).of(database).abortTransaction(txn); }}); DatabaseComponent db = createDatabaseComponent(database, eventBus, eventExecutor, shutdownManager); @@ -376,6 +377,14 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { // Expected } + try { + db.transaction(false, transaction -> + db.getSyncVersions(transaction, contactId)); + fail(); + } catch (NoSuchContactException expected) { + // Expected + } + try { Ack a = new Ack(singletonList(messageId)); db.transaction(false, transaction -> @@ -435,6 +444,14 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } catch (NoSuchContactException expected) { // Expected } + + try { + db.transaction(false, transaction -> + db.setSyncVersions(transaction, contactId, emptyList())); + fail(); + } catch (NoSuchContactException expected) { + // Expected + } } @Test diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java index 006c1e67c..b8e246013 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java @@ -41,7 +41,6 @@ import org.junit.Test; import java.io.File; import java.sql.Connection; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; @@ -51,6 +50,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; @@ -407,10 +407,10 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { // Both message IDs should be returned Collection ids = db.getMessagesToAck(txn, contactId, 1234); - assertEquals(Arrays.asList(messageId, messageId1), ids); + assertEquals(asList(messageId, messageId1), ids); // Remove both message IDs - db.lowerAckFlag(txn, contactId, Arrays.asList(messageId, messageId1)); + db.lowerAckFlag(txn, contactId, asList(messageId, messageId1)); // Both message IDs should have been removed assertEquals(emptyList(), db.getMessagesToAck(txn, @@ -422,7 +422,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { // Both message IDs should be returned ids = db.getMessagesToAck(txn, contactId, 1234); - assertEquals(Arrays.asList(messageId, messageId1), ids); + assertEquals(asList(messageId, messageId1), ids); db.commitTransaction(txn); db.close(); @@ -2286,6 +2286,29 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { db.close(); } + @Test + public void testSyncVersions() throws Exception { + Database db = open(false); + Connection txn = db.startTransaction(); + + // Add a contact + db.addIdentity(txn, identity); + assertEquals(contactId, + db.addContact(txn, author, localAuthor.getId(), null, true)); + + // Only sync version 0 should be supported by default + List defaultSupported = singletonList((byte) 0); + assertEquals(defaultSupported, db.getSyncVersions(txn, contactId)); + + // Set the supported versions and check that they're returned + List supported = asList((byte) 0, (byte) 1); + db.setSyncVersions(txn, contactId, supported); + assertEquals(supported, db.getSyncVersions(txn, contactId)); + + db.commitTransaction(txn); + db.close(); + } + private Database open(boolean resume) throws Exception { return open(resume, new TestMessageFactory(), new SystemClock()); } From 1d546da781a748c592adfe7be554f709c02353fb Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 13 Jun 2019 17:07:12 +0100 Subject: [PATCH 7/8] Store sync versions received from contacts. --- .../bramble/sync/IncomingSession.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java index ae2c26978..e9c17577e 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java @@ -21,13 +21,14 @@ import org.briarproject.bramble.api.sync.SyncSession; import org.briarproject.bramble.api.sync.Versions; import java.io.IOException; +import java.util.List; import java.util.concurrent.Executor; import java.util.logging.Logger; import javax.annotation.concurrent.ThreadSafe; -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.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.util.LogUtils.logException; @@ -39,7 +40,7 @@ import static org.briarproject.bramble.util.LogUtils.logException; class IncomingSession implements SyncSession, EventListener { private static final Logger LOG = - Logger.getLogger(IncomingSession.class.getName()); + getLogger(IncomingSession.class.getName()); private final DatabaseComponent db; private final Executor dbExecutor; @@ -84,11 +85,7 @@ class IncomingSession implements SyncSession, EventListener { dbExecutor.execute(new ReceiveRequest(r)); } else if (recordReader.hasVersions()) { Versions v = recordReader.readVersions(); - // TODO: Store remote peer's supported versions - if (LOG.isLoggable(INFO)) { - LOG.info("Received supported versions: " - + v.getSupportedVersions()); - } + dbExecutor.execute(new ReceiveVersions(v)); } else { // unknown records are ignored in RecordReader#eof() throw new FormatException(); @@ -199,4 +196,26 @@ class IncomingSession implements SyncSession, EventListener { } } } + + private class ReceiveVersions implements Runnable { + + private final Versions versions; + + private ReceiveVersions(Versions versions) { + this.versions = versions; + } + + @DatabaseExecutor + @Override + public void run() { + try { + List supported = versions.getSupportedVersions(); + db.transaction(false, + txn -> db.setSyncVersions(txn, contactId, supported)); + } catch (DbException e) { + logException(LOG, WARNING, e); + interrupt(); + } + } + } } From ec3f821ba61661f6ad798145fa5a8f7e8629c76c Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 13 Jun 2019 17:17:50 +0100 Subject: [PATCH 8/8] Update test expectations. --- .../bramble/sync/SimplexOutgoingSessionTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bramble-core/src/test/java/org/briarproject/bramble/sync/SimplexOutgoingSessionTest.java b/bramble-core/src/test/java/org/briarproject/bramble/sync/SimplexOutgoingSessionTest.java index c1ba36053..430a9150f 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/sync/SimplexOutgoingSessionTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/sync/SimplexOutgoingSessionTest.java @@ -9,6 +9,7 @@ import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.SyncRecordWriter; +import org.briarproject.bramble.api.sync.Versions; import org.briarproject.bramble.api.transport.StreamWriter; import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.DbExpectations; @@ -49,6 +50,8 @@ public class SimplexOutgoingSessionTest extends BrambleMockTestCase { context.checking(new DbExpectations() {{ // Add listener oneOf(eventBus).addListener(session); + // Send the protocol versions + oneOf(recordWriter).writeVersions(with(any(Versions.class))); // No acks to send oneOf(db).transactionWithNullableResult(with(false), withNullableDbCallable(noAckTxn)); @@ -83,6 +86,8 @@ public class SimplexOutgoingSessionTest extends BrambleMockTestCase { context.checking(new DbExpectations() {{ // Add listener oneOf(eventBus).addListener(session); + // Send the protocol versions + oneOf(recordWriter).writeVersions(with(any(Versions.class))); // One ack to send oneOf(db).transactionWithNullableResult(with(false), withNullableDbCallable(ackTxn));