diff --git a/api/net/sf/briar/api/protocol/writers/AckWriter.java b/api/net/sf/briar/api/protocol/writers/AckWriter.java index 237a487ab9cc86ce9fe015a334c25dfaf4dc219e..80fbd88681d7492fd0522e207f713e95f3bcbf40 100644 --- a/api/net/sf/briar/api/protocol/writers/AckWriter.java +++ b/api/net/sf/briar/api/protocol/writers/AckWriter.java @@ -7,6 +7,12 @@ import net.sf.briar.api.protocol.BatchId; /** An interface for creating an ack packet. */ public interface AckWriter { + /** + * Sets the maximum length of the serialised ack. If this method is not + * called, the default is ProtocolConstants.MAX_PACKET_LENGTH; + */ + void setMaxPacketLength(int length); + /** * Attempts to add the given BatchId to the ack and returns true if it * was added. diff --git a/api/net/sf/briar/api/protocol/writers/BatchWriter.java b/api/net/sf/briar/api/protocol/writers/BatchWriter.java index 60818ac56945c4e5abc9f07300bcb2c04e1ff890..e14aa127e7cf550594fdfd08aca76d4a65d79a9b 100644 --- a/api/net/sf/briar/api/protocol/writers/BatchWriter.java +++ b/api/net/sf/briar/api/protocol/writers/BatchWriter.java @@ -7,6 +7,12 @@ import net.sf.briar.api.protocol.BatchId; /** An interface for creating a batch packet. */ public interface BatchWriter { + /** + * Sets the maximum length of the serialised batch. If this method is not + * called, the default is ProtocolConstants.MAX_PACKET_LENGTH; + */ + void setMaxPacketLength(int length); + /** * Attempts to add the given raw message to the batch and returns true if * it was added. diff --git a/api/net/sf/briar/api/protocol/writers/OfferWriter.java b/api/net/sf/briar/api/protocol/writers/OfferWriter.java index 8faee5bed2fc010b292b74f5f7626106d6255e70..35bdafe926ca6230db171c683b1b087efc08bf3e 100644 --- a/api/net/sf/briar/api/protocol/writers/OfferWriter.java +++ b/api/net/sf/briar/api/protocol/writers/OfferWriter.java @@ -7,6 +7,12 @@ import net.sf.briar.api.protocol.MessageId; /** An interface for creating an offer packet. */ public interface OfferWriter { + /** + * Sets the maximum length of the serialised offer. If this method is not + * called, the default is ProtocolConstants.MAX_PACKET_LENGTH; + */ + void setMaxPacketLength(int length); + /** * Attempts to add the given message ID to the offer and returns true if it * was added. diff --git a/components/net/sf/briar/protocol/writers/AckWriterImpl.java b/components/net/sf/briar/protocol/writers/AckWriterImpl.java index 2da1a1cece1614e8aae34890304745029985eea7..f1d9722cb40c10cc8228bc86902aeb495affec73 100644 --- a/components/net/sf/briar/protocol/writers/AckWriterImpl.java +++ b/components/net/sf/briar/protocol/writers/AckWriterImpl.java @@ -18,7 +18,7 @@ class AckWriterImpl implements AckWriter { private final Writer w; private boolean started = false; - private int capacity = ProtocolConstants.MAX_PACKET_LENGTH; // FIXME + private int capacity = ProtocolConstants.MAX_PACKET_LENGTH; AckWriterImpl(OutputStream out, SerialComponent serial, WriterFactory writerFactory) { @@ -30,6 +30,13 @@ class AckWriterImpl implements AckWriter { w = writerFactory.createWriter(out); } + public void setMaxPacketLength(int length) { + if(started) throw new IllegalStateException(); + if(length < 0 || length > ProtocolConstants.MAX_PACKET_LENGTH) + throw new IllegalArgumentException(); + capacity = length; + } + public boolean writeBatchId(BatchId b) throws IOException { int overhead = started ? footerLength : headerLength + footerLength; if(capacity < idLength + overhead) return false; @@ -43,7 +50,7 @@ class AckWriterImpl implements AckWriter { if(!started) start(); w.writeListEnd(); out.flush(); - capacity = ProtocolConstants.MAX_PACKET_LENGTH; // FIXME + capacity = ProtocolConstants.MAX_PACKET_LENGTH; started = false; } diff --git a/components/net/sf/briar/protocol/writers/BatchWriterImpl.java b/components/net/sf/briar/protocol/writers/BatchWriterImpl.java index 96c982e6a8c5be2a62e7adf6aaac3529261a1966..bc6bfb0f8e09ac45380175cef7200350ab6fa17e 100644 --- a/components/net/sf/briar/protocol/writers/BatchWriterImpl.java +++ b/components/net/sf/briar/protocol/writers/BatchWriterImpl.java @@ -21,7 +21,7 @@ class BatchWriterImpl implements BatchWriter { private final MessageDigest messageDigest; private boolean started = false; - private int capacity = ProtocolConstants.MAX_PACKET_LENGTH; // FIXME + private int capacity = ProtocolConstants.MAX_PACKET_LENGTH; BatchWriterImpl(OutputStream out, SerialComponent serial, WriterFactory writerFactory, MessageDigest messageDigest) { @@ -33,6 +33,13 @@ class BatchWriterImpl implements BatchWriter { this.messageDigest = messageDigest; } + public void setMaxPacketLength(int length) { + if(started) throw new IllegalStateException(); + if(length < 0 || length > ProtocolConstants.MAX_PACKET_LENGTH) + throw new IllegalArgumentException(); + capacity = length; + } + public boolean writeMessage(byte[] message) throws IOException { int overhead = started ? footerLength : headerLength + footerLength; if(capacity < message.length + overhead) return false; @@ -47,7 +54,7 @@ class BatchWriterImpl implements BatchWriter { if(!started) start(); w.writeListEnd(); out.flush(); - capacity = ProtocolConstants.MAX_PACKET_LENGTH; // FIXME + capacity = ProtocolConstants.MAX_PACKET_LENGTH; started = false; return new BatchId(messageDigest.digest()); } diff --git a/components/net/sf/briar/protocol/writers/OfferWriterImpl.java b/components/net/sf/briar/protocol/writers/OfferWriterImpl.java index 40a9221afabf6bf5a2b89427ac8a13a8cd64f1af..04303fbf4d2fbaf1f926a8341e8559f3159ed7c0 100644 --- a/components/net/sf/briar/protocol/writers/OfferWriterImpl.java +++ b/components/net/sf/briar/protocol/writers/OfferWriterImpl.java @@ -18,7 +18,7 @@ class OfferWriterImpl implements OfferWriter { private final Writer w; private boolean started = false; - private int capacity = ProtocolConstants.MAX_PACKET_LENGTH; // FIXME + private int capacity = ProtocolConstants.MAX_PACKET_LENGTH; OfferWriterImpl(OutputStream out, SerialComponent serial, WriterFactory writerFactory) { @@ -30,6 +30,13 @@ class OfferWriterImpl implements OfferWriter { w = writerFactory.createWriter(out); } + public void setMaxPacketLength(int length) { + if(started) throw new IllegalStateException(); + if(length < 0 || length > ProtocolConstants.MAX_PACKET_LENGTH) + throw new IllegalArgumentException(); + capacity = length; + } + public boolean writeMessageId(MessageId m) throws IOException { int overhead = started ? footerLength : headerLength + footerLength; if(capacity < idLength + overhead) return false; @@ -43,7 +50,7 @@ class OfferWriterImpl implements OfferWriter { if(!started) start(); w.writeListEnd(); out.flush(); - capacity = ProtocolConstants.MAX_PACKET_LENGTH; // FIXME + capacity = ProtocolConstants.MAX_PACKET_LENGTH; started = false; } diff --git a/test/net/sf/briar/protocol/writers/ConstantsTest.java b/test/net/sf/briar/protocol/writers/ConstantsTest.java index 6115e08af7152d8ed885fdbbd1d9bd312dca4678..d6a50b20db27b82fd23d212de044c53ae8e20a66 100644 --- a/test/net/sf/briar/protocol/writers/ConstantsTest.java +++ b/test/net/sf/briar/protocol/writers/ConstantsTest.java @@ -58,15 +58,35 @@ public class ConstantsTest extends TestCase { } @Test - public void testBatchesFitIntoAck() throws Exception { - // Create an ack with the maximum number of batch IDs - ByteArrayOutputStream out = new ByteArrayOutputStream( - ProtocolConstants.MAX_PACKET_LENGTH); + public void testBatchesFitIntoLargeAck() throws Exception { + testBatchesFitIntoAck(ProtocolConstants.MAX_PACKET_LENGTH); + } + + @Test + public void testBatchesFitIntoSmallAck() throws Exception { + testBatchesFitIntoAck(1000); + } + + private void testBatchesFitIntoAck(int length) throws Exception { + // Create an ack with as many batch IDs as possible + ByteArrayOutputStream out = new ByteArrayOutputStream(length); AckWriter a = new AckWriterImpl(out, serial, writerFactory); + a.setMaxPacketLength(length); while(a.writeBatchId(new BatchId(TestUtils.getRandomId()))); a.finish(); // Check the size of the serialised ack - assertTrue(out.size() <= ProtocolConstants.MAX_PACKET_LENGTH); + assertTrue(out.size() <= length); + } + + @Test + public void testEmptyAck() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + AckWriter a = new AckWriterImpl(out, serial, writerFactory); + // There's not enough room for a batch ID + a.setMaxPacketLength(4); + assertFalse(a.writeBatchId(new BatchId(TestUtils.getRandomId()))); + // Check that nothing was written + assertEquals(0, out.size()); } @Test @@ -90,7 +110,7 @@ public class ConstantsTest extends TestCase { ProtocolConstants.MAX_PACKET_LENGTH); BatchWriter b = new BatchWriterImpl(out, serial, writerFactory, crypto.getMessageDigest()); - b.writeMessage(message.getBytes()); + assertTrue(b.writeMessage(message.getBytes())); b.finish(); // Check the size of the serialised batch assertTrue(out.size() > UniqueId.LENGTH + Group.MAX_NAME_LENGTH + @@ -100,15 +120,47 @@ public class ConstantsTest extends TestCase { } @Test - public void testMessagesFitIntoOffer() throws Exception { - // Create an offer with the maximum number of message IDs - ByteArrayOutputStream out = new ByteArrayOutputStream( - ProtocolConstants.MAX_PACKET_LENGTH); + public void testEmptyBatch() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BatchWriter b = new BatchWriterImpl(out, serial, writerFactory, + crypto.getMessageDigest()); + // There's not enough room for a message + b.setMaxPacketLength(4); + assertFalse(b.writeMessage(new byte[4])); + // Check that nothing was written + assertEquals(0, out.size()); + } + + @Test + public void testMessagesFitIntoLargeOffer() throws Exception { + testMessagesFitIntoOffer(ProtocolConstants.MAX_PACKET_LENGTH); + } + + @Test + public void testMessagesFitIntoSmallOffer() throws Exception { + testMessagesFitIntoOffer(1000); + } + + private void testMessagesFitIntoOffer(int length) throws Exception { + // Create an offer with as many message IDs as possible + ByteArrayOutputStream out = new ByteArrayOutputStream(length); OfferWriter o = new OfferWriterImpl(out, serial, writerFactory); + o.setMaxPacketLength(length); while(o.writeMessageId(new MessageId(TestUtils.getRandomId()))); o.finish(); // Check the size of the serialised offer - assertTrue(out.size() <= ProtocolConstants.MAX_PACKET_LENGTH); + assertTrue(out.size() <= length); + } + + @Test + public void testEmptyOffer() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + OfferWriter o = new OfferWriterImpl(out, serial, writerFactory); + // There's not enough room for a message ID + o.setMaxPacketLength(4); + assertFalse(o.writeMessageId(new MessageId(TestUtils.getRandomId()))); + // Check that nothing was written + assertEquals(0, out.size()); } @Test