diff --git a/components/net/sf/briar/protocol/AckReader.java b/components/net/sf/briar/protocol/AckReader.java index bffaa76c1..77ba91d23 100644 --- a/components/net/sf/briar/protocol/AckReader.java +++ b/components/net/sf/briar/protocol/AckReader.java @@ -6,6 +6,7 @@ import java.util.Collection; import net.sf.briar.api.protocol.Ack; import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.Tags; +import net.sf.briar.api.serial.Consumer; import net.sf.briar.api.serial.ObjectReader; import net.sf.briar.api.serial.Reader; @@ -24,7 +25,7 @@ class AckReader implements ObjectReader { public Ack readObject(Reader r) throws IOException { // Initialise the consumer - CountingConsumer counting = new CountingConsumer(Ack.MAX_SIZE); + Consumer counting = new CountingConsumer(Ack.MAX_SIZE); // Read and digest the data r.addConsumer(counting); r.readUserDefinedTag(Tags.ACK); diff --git a/components/net/sf/briar/protocol/BatchReader.java b/components/net/sf/briar/protocol/BatchReader.java index 95b3ae344..15ccb655c 100644 --- a/components/net/sf/briar/protocol/BatchReader.java +++ b/components/net/sf/briar/protocol/BatchReader.java @@ -9,6 +9,7 @@ import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.Tags; +import net.sf.briar.api.serial.Consumer; import net.sf.briar.api.serial.ObjectReader; import net.sf.briar.api.serial.Reader; @@ -30,7 +31,7 @@ class BatchReader implements ObjectReader { public Batch readObject(Reader r) throws IOException { // Initialise the consumers - CountingConsumer counting = new CountingConsumer(Batch.MAX_SIZE); + Consumer counting = new CountingConsumer(Batch.MAX_SIZE); DigestingConsumer digesting = new DigestingConsumer(messageDigest); messageDigest.reset(); // Read and digest the data diff --git a/components/net/sf/briar/protocol/MessageIdReader.java b/components/net/sf/briar/protocol/MessageIdReader.java new file mode 100644 index 000000000..118bf0ea4 --- /dev/null +++ b/components/net/sf/briar/protocol/MessageIdReader.java @@ -0,0 +1,20 @@ +package net.sf.briar.protocol; + +import java.io.IOException; + +import net.sf.briar.api.protocol.MessageId; +import net.sf.briar.api.protocol.Tags; +import net.sf.briar.api.protocol.UniqueId; +import net.sf.briar.api.serial.FormatException; +import net.sf.briar.api.serial.ObjectReader; +import net.sf.briar.api.serial.Reader; + +class MessageIdReader implements ObjectReader { + + public MessageId readObject(Reader r) throws IOException { + r.readUserDefinedTag(Tags.MESSAGE_ID); + byte[] b = r.readBytes(); + if(b.length != UniqueId.LENGTH) throw new FormatException(); + return new MessageId(b); + } +} diff --git a/components/net/sf/briar/protocol/MessageReader.java b/components/net/sf/briar/protocol/MessageReader.java index bc206e00b..ef7183128 100644 --- a/components/net/sf/briar/protocol/MessageReader.java +++ b/components/net/sf/briar/protocol/MessageReader.java @@ -14,7 +14,6 @@ import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.Tags; -import net.sf.briar.api.protocol.UniqueId; import net.sf.briar.api.serial.FormatException; import net.sf.briar.api.serial.ObjectReader; import net.sf.briar.api.serial.Reader; @@ -23,6 +22,7 @@ import com.google.inject.Inject; class MessageReader implements ObjectReader { + private final ObjectReader messageIdReader; private final ObjectReader groupReader; private final ObjectReader authorReader; private final KeyParser keyParser; @@ -30,8 +30,11 @@ class MessageReader implements ObjectReader { private final MessageDigest messageDigest; @Inject - MessageReader(CryptoComponent crypto, ObjectReader groupReader, + MessageReader(CryptoComponent crypto, + ObjectReader messageIdReader, + ObjectReader groupReader, ObjectReader authorReader) { + this.messageIdReader = messageIdReader; this.groupReader = groupReader; this.authorReader = authorReader; keyParser = crypto.getKeyParser(); @@ -47,10 +50,9 @@ class MessageReader implements ObjectReader { // Read the initial tag r.readUserDefinedTag(Tags.MESSAGE); // Read the parent's message ID - r.readUserDefinedTag(Tags.MESSAGE_ID); - byte[] b = r.readBytes(); - if(b.length != UniqueId.LENGTH) throw new FormatException(); - MessageId parent = new MessageId(b); + r.addObjectReader(Tags.MESSAGE_ID, messageIdReader); + MessageId parent = r.readUserDefined(Tags.MESSAGE_ID, MessageId.class); + r.removeObjectReader(Tags.MESSAGE_ID); // Read the group r.addObjectReader(Tags.GROUP, groupReader); Group group = r.readUserDefined(Tags.GROUP, Group.class); diff --git a/components/net/sf/briar/protocol/OfferFactory.java b/components/net/sf/briar/protocol/OfferFactory.java new file mode 100644 index 000000000..23fbea52d --- /dev/null +++ b/components/net/sf/briar/protocol/OfferFactory.java @@ -0,0 +1,11 @@ +package net.sf.briar.protocol; + +import java.util.Collection; + +import net.sf.briar.api.protocol.MessageId; +import net.sf.briar.api.protocol.Offer; + +interface OfferFactory { + + Offer createOffer(Collection messages); +} diff --git a/components/net/sf/briar/protocol/OfferFactoryImpl.java b/components/net/sf/briar/protocol/OfferFactoryImpl.java new file mode 100644 index 000000000..8635b0b96 --- /dev/null +++ b/components/net/sf/briar/protocol/OfferFactoryImpl.java @@ -0,0 +1,13 @@ +package net.sf.briar.protocol; + +import java.util.Collection; + +import net.sf.briar.api.protocol.MessageId; +import net.sf.briar.api.protocol.Offer; + +class OfferFactoryImpl implements OfferFactory { + + public Offer createOffer(Collection messages) { + return new OfferImpl(messages); + } +} diff --git a/components/net/sf/briar/protocol/OfferImpl.java b/components/net/sf/briar/protocol/OfferImpl.java new file mode 100644 index 000000000..129d2054e --- /dev/null +++ b/components/net/sf/briar/protocol/OfferImpl.java @@ -0,0 +1,19 @@ +package net.sf.briar.protocol; + +import java.util.Collection; + +import net.sf.briar.api.protocol.MessageId; +import net.sf.briar.api.protocol.Offer; + +class OfferImpl implements Offer { + + private final Collection messages; + + OfferImpl(Collection messages) { + this.messages = messages; + } + + public Collection getMessages() { + return messages; + } +} diff --git a/components/net/sf/briar/protocol/OfferReader.java b/components/net/sf/briar/protocol/OfferReader.java new file mode 100644 index 000000000..459310dec --- /dev/null +++ b/components/net/sf/briar/protocol/OfferReader.java @@ -0,0 +1,40 @@ +package net.sf.briar.protocol; + +import java.io.IOException; +import java.util.Collection; + +import net.sf.briar.api.protocol.MessageId; +import net.sf.briar.api.protocol.Offer; +import net.sf.briar.api.protocol.Tags; +import net.sf.briar.api.serial.Consumer; +import net.sf.briar.api.serial.ObjectReader; +import net.sf.briar.api.serial.Reader; + +import com.google.inject.Inject; + +class OfferReader implements ObjectReader { + + private final ObjectReader messageIdReader; + private final OfferFactory offerFactory; + + @Inject + OfferReader(ObjectReader messageIdReader, + OfferFactory offerFactory) { + this.messageIdReader = messageIdReader; + this.offerFactory = offerFactory; + } + + public Offer readObject(Reader r) throws IOException { + // Initialise the consumer + Consumer counting = new CountingConsumer(Offer.MAX_SIZE); + // Read the data + r.addConsumer(counting); + r.readUserDefinedTag(Tags.OFFER); + r.addObjectReader(Tags.MESSAGE_ID, messageIdReader); + Collection messages = r.readList(MessageId.class); + r.removeObjectReader(Tags.MESSAGE_ID); + r.removeConsumer(counting); + // Build and return the offer + return offerFactory.createOffer(messages); + } +} diff --git a/components/net/sf/briar/protocol/ProtocolModule.java b/components/net/sf/briar/protocol/ProtocolModule.java index c5ea60557..ffd8e51c9 100644 --- a/components/net/sf/briar/protocol/ProtocolModule.java +++ b/components/net/sf/briar/protocol/ProtocolModule.java @@ -8,6 +8,7 @@ import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.GroupFactory; import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.MessageEncoder; +import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.serial.ObjectReader; import com.google.inject.AbstractModule; @@ -21,6 +22,7 @@ public class ProtocolModule extends AbstractModule { bind(AuthorFactory.class).to(AuthorFactoryImpl.class); bind(BatchFactory.class).to(BatchFactoryImpl.class); bind(GroupFactory.class).to(GroupFactoryImpl.class); + bind(OfferFactory.class).to(OfferFactoryImpl.class); bind(SubscriptionFactory.class).to(SubscriptionFactoryImpl.class); bind(TransportFactory.class).to(TransportFactoryImpl.class); bind(MessageEncoder.class).to(MessageEncoderImpl.class); @@ -31,6 +33,11 @@ public class ProtocolModule extends AbstractModule { return new BatchIdReader(); } + @Provides + ObjectReader getMessageIdReader() { + return new MessageIdReader(); + } + @Provides ObjectReader getGroupReader(CryptoComponent crypto, GroupFactory groupFactory) { @@ -45,8 +52,10 @@ public class ProtocolModule extends AbstractModule { @Provides ObjectReader getMessageReader(CryptoComponent crypto, + ObjectReader messageIdReader, ObjectReader groupReader, ObjectReader authorReader) { - return new MessageReader(crypto, groupReader, authorReader); + return new MessageReader(crypto, messageIdReader, groupReader, + authorReader); } } diff --git a/components/net/sf/briar/protocol/SubscriptionReader.java b/components/net/sf/briar/protocol/SubscriptionReader.java index 88a693b26..b3c68b9b6 100644 --- a/components/net/sf/briar/protocol/SubscriptionReader.java +++ b/components/net/sf/briar/protocol/SubscriptionReader.java @@ -6,6 +6,7 @@ import java.util.Collection; import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.Subscriptions; import net.sf.briar.api.protocol.Tags; +import net.sf.briar.api.serial.Consumer; import net.sf.briar.api.serial.ObjectReader; import net.sf.briar.api.serial.Reader; @@ -25,8 +26,7 @@ class SubscriptionReader implements ObjectReader { public Subscriptions readObject(Reader r) throws IOException { // Initialise the consumer - CountingConsumer counting = - new CountingConsumer(Subscriptions.MAX_SIZE); + Consumer counting = new CountingConsumer(Subscriptions.MAX_SIZE); // Read the data r.addConsumer(counting); r.readUserDefinedTag(Tags.SUBSCRIPTIONS); diff --git a/components/net/sf/briar/protocol/TransportReader.java b/components/net/sf/briar/protocol/TransportReader.java index 41d5f21f6..bec0dd0f6 100644 --- a/components/net/sf/briar/protocol/TransportReader.java +++ b/components/net/sf/briar/protocol/TransportReader.java @@ -5,6 +5,7 @@ import java.util.Map; import net.sf.briar.api.protocol.Tags; import net.sf.briar.api.protocol.Transports; +import net.sf.briar.api.serial.Consumer; import net.sf.briar.api.serial.ObjectReader; import net.sf.briar.api.serial.Reader; @@ -21,7 +22,7 @@ class TransportReader implements ObjectReader { public Transports readObject(Reader r) throws IOException { // Initialise the consumer - CountingConsumer counting = new CountingConsumer(Transports.MAX_SIZE); + Consumer counting = new CountingConsumer(Transports.MAX_SIZE); // Read the data r.addConsumer(counting); r.readUserDefinedTag(Tags.TRANSPORTS); diff --git a/test/net/sf/briar/protocol/FileReadWriteTest.java b/test/net/sf/briar/protocol/FileReadWriteTest.java index 695008fa5..9b77922d9 100644 --- a/test/net/sf/briar/protocol/FileReadWriteTest.java +++ b/test/net/sf/briar/protocol/FileReadWriteTest.java @@ -23,12 +23,14 @@ import net.sf.briar.api.protocol.GroupFactory; import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.MessageEncoder; import net.sf.briar.api.protocol.MessageId; +import net.sf.briar.api.protocol.Offer; import net.sf.briar.api.protocol.Subscriptions; import net.sf.briar.api.protocol.Tags; import net.sf.briar.api.protocol.Transports; import net.sf.briar.api.protocol.UniqueId; import net.sf.briar.api.protocol.writers.AckWriter; import net.sf.briar.api.protocol.writers.BatchWriter; +import net.sf.briar.api.protocol.writers.OfferWriter; import net.sf.briar.api.protocol.writers.PacketWriterFactory; import net.sf.briar.api.protocol.writers.SubscriptionWriter; import net.sf.briar.api.protocol.writers.TransportWriter; @@ -58,6 +60,7 @@ public class FileReadWriteTest extends TestCase { private final CryptoComponent crypto; private final AckReader ackReader; private final BatchReader batchReader; + private final OfferReader offerReader; private final SubscriptionReader subscriptionReader; private final TransportReader transportReader; private final Author author; @@ -78,6 +81,7 @@ public class FileReadWriteTest extends TestCase { UniqueId.LENGTH); ackReader = i.getInstance(AckReader.class); batchReader = i.getInstance(BatchReader.class); + offerReader = i.getInstance(OfferReader.class); subscriptionReader = i.getInstance(SubscriptionReader.class); transportReader = i.getInstance(TransportReader.class); // Create two groups: one restricted, one unrestricted @@ -124,6 +128,13 @@ public class FileReadWriteTest extends TestCase { assertTrue(b.writeMessage(message3.getBytes())); b.finish(); + OfferWriter o = packetWriterFactory.createOfferWriter(out); + assertTrue(o.writeMessageId(message.getId())); + assertTrue(o.writeMessageId(message1.getId())); + assertTrue(o.writeMessageId(message2.getId())); + assertTrue(o.writeMessageId(message3.getId())); + o.finish(); + SubscriptionWriter s = packetWriterFactory.createSubscriptionWriter(out); Collection subs = new ArrayList(); @@ -148,6 +159,7 @@ public class FileReadWriteTest extends TestCase { Reader reader = readerFactory.createReader(in); reader.addObjectReader(Tags.ACK, ackReader); reader.addObjectReader(Tags.BATCH, batchReader); + reader.addObjectReader(Tags.OFFER, offerReader); reader.addObjectReader(Tags.SUBSCRIPTIONS, subscriptionReader); reader.addObjectReader(Tags.TRANSPORTS, transportReader); @@ -166,16 +178,27 @@ public class FileReadWriteTest extends TestCase { checkMessageEquality(message1, i.next()); checkMessageEquality(message2, i.next()); checkMessageEquality(message3, i.next()); - + + // Read the offer + assertTrue(reader.hasUserDefined(Tags.OFFER)); + Offer o = reader.readUserDefined(Tags.OFFER, Offer.class); + Collection ids = o.getMessages(); + assertEquals(4, ids.size()); + Iterator i1 = ids.iterator(); + assertEquals(message.getId(), i1.next()); + assertEquals(message1.getId(), i1.next()); + assertEquals(message2.getId(), i1.next()); + assertEquals(message3.getId(), i1.next()); + // Read the subscriptions update assertTrue(reader.hasUserDefined(Tags.SUBSCRIPTIONS)); Subscriptions s = reader.readUserDefined(Tags.SUBSCRIPTIONS, Subscriptions.class); Collection subs = s.getSubscriptions(); assertEquals(2, subs.size()); - Iterator i1 = subs.iterator(); - checkGroupEquality(group, i1.next()); - checkGroupEquality(group1, i1.next()); + Iterator i2 = subs.iterator(); + checkGroupEquality(group, i2.next()); + checkGroupEquality(group1, i2.next()); assertTrue(s.getTimestamp() > start); assertTrue(s.getTimestamp() <= System.currentTimeMillis());