From c2b0f0ab5a21a690c4c1364ddcfe9772c60b6b0f Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Sat, 13 Aug 2011 17:46:19 +0200 Subject: [PATCH] Each request packet should contain the unique ID of the offer to which it responds. --- api/net/sf/briar/api/protocol/Offer.java | 3 ++ api/net/sf/briar/api/protocol/OfferId.java | 26 ++++++++++++++++ api/net/sf/briar/api/protocol/Request.java | 6 ++++ api/net/sf/briar/api/protocol/Tags.java | 7 +++-- .../api/protocol/writers/OfferWriter.java | 5 ++-- .../api/protocol/writers/RequestWriter.java | 4 ++- .../db/ReadWriteLockDatabaseComponent.java | 2 +- .../db/SynchronizedDatabaseComponent.java | 2 +- .../net/sf/briar/protocol/AckReader.java | 3 -- .../net/sf/briar/protocol/AuthorReader.java | 3 -- .../net/sf/briar/protocol/BatchReader.java | 3 -- .../net/sf/briar/protocol/GroupReader.java | 3 -- .../net/sf/briar/protocol/MessageReader.java | 3 -- .../net/sf/briar/protocol/OfferFactory.java | 3 +- .../sf/briar/protocol/OfferFactoryImpl.java | 5 ++-- .../net/sf/briar/protocol/OfferIdReader.java | 20 +++++++++++++ .../net/sf/briar/protocol/OfferImpl.java | 9 +++++- .../net/sf/briar/protocol/OfferReader.java | 19 ++++++++---- .../net/sf/briar/protocol/ProtocolModule.java | 16 +++++++--- .../net/sf/briar/protocol/RequestFactory.java | 3 +- .../sf/briar/protocol/RequestFactoryImpl.java | 5 ++-- .../net/sf/briar/protocol/RequestImpl.java | 9 +++++- .../net/sf/briar/protocol/RequestReader.java | 13 ++++---- .../sf/briar/protocol/SubscriptionReader.java | 3 -- .../sf/briar/protocol/TransportReader.java | 3 -- .../protocol/writers/OfferWriterImpl.java | 21 ++++++++----- .../writers/ProtocolWriterFactoryImpl.java | 2 +- .../protocol/writers/RequestWriterImpl.java | 6 +++- test/net/sf/briar/FileReadWriteTest.java | 6 +++- .../sf/briar/db/DatabaseCleanerImplTest.java | 8 ++--- .../sf/briar/db/DatabaseComponentTest.java | 9 ++++-- .../briar/protocol/ProtocolReadWriteTest.java | 5 +++- .../sf/briar/protocol/RequestReaderTest.java | 30 +++++++++++++------ .../writers/RequestWriterImplTest.java | 24 +++++++++++---- 34 files changed, 203 insertions(+), 86 deletions(-) create mode 100644 api/net/sf/briar/api/protocol/OfferId.java create mode 100644 components/net/sf/briar/protocol/OfferIdReader.java diff --git a/api/net/sf/briar/api/protocol/Offer.java b/api/net/sf/briar/api/protocol/Offer.java index e62f05d56a..fbeda85080 100644 --- a/api/net/sf/briar/api/protocol/Offer.java +++ b/api/net/sf/briar/api/protocol/Offer.java @@ -11,6 +11,9 @@ public interface Offer { */ static final int MAX_SIZE = (1024 * 1024) - 100; + /** Returns the offer's unique identifier. */ + OfferId getId(); + /** Returns the message IDs contained in the offer. */ Collection<MessageId> getMessageIds(); } diff --git a/api/net/sf/briar/api/protocol/OfferId.java b/api/net/sf/briar/api/protocol/OfferId.java new file mode 100644 index 0000000000..1d235cfe71 --- /dev/null +++ b/api/net/sf/briar/api/protocol/OfferId.java @@ -0,0 +1,26 @@ +package net.sf.briar.api.protocol; + +import java.io.IOException; +import java.util.Arrays; + +import net.sf.briar.api.serial.Writer; + +/** Type-safe wrapper for a byte array that uniquely identifies an offer. */ +public class OfferId extends UniqueId { + + public OfferId(byte[] id) { + super(id); + } + + public void writeTo(Writer w) throws IOException { + w.writeUserDefinedTag(Tags.OFFER_ID); + w.writeBytes(id); + } + + @Override + public boolean equals(Object o) { + if(o instanceof OfferId) + return Arrays.equals(id, ((OfferId) o).id); + return false; + } +} diff --git a/api/net/sf/briar/api/protocol/Request.java b/api/net/sf/briar/api/protocol/Request.java index ea3f461f3f..bc21df77cc 100644 --- a/api/net/sf/briar/api/protocol/Request.java +++ b/api/net/sf/briar/api/protocol/Request.java @@ -11,6 +11,12 @@ public interface Request { */ static final int MAX_SIZE = (1024 * 1024) - 100; + /** + * Returns the unique identifier of the offer to which this request + * responds. + */ + OfferId getOfferId(); + /** * Returns a sequence of bits corresponding to the sequence of messages in * the offer, where the i^th bit is set if the i^th message should be sent. diff --git a/api/net/sf/briar/api/protocol/Tags.java b/api/net/sf/briar/api/protocol/Tags.java index 3b0071d4ca..101b1e6577 100644 --- a/api/net/sf/briar/api/protocol/Tags.java +++ b/api/net/sf/briar/api/protocol/Tags.java @@ -17,7 +17,8 @@ public interface Tags { static final int MESSAGE = 7; static final int MESSAGE_ID = 8; static final int OFFER = 9; - static final int REQUEST = 10; - static final int SUBSCRIPTIONS = 11; - static final int TRANSPORTS = 12; + static final int OFFER_ID = 10; + static final int REQUEST = 11; + static final int SUBSCRIPTIONS = 12; + static final int TRANSPORTS = 13; } diff --git a/api/net/sf/briar/api/protocol/writers/OfferWriter.java b/api/net/sf/briar/api/protocol/writers/OfferWriter.java index 5ad5ddd2e5..6f89b3b87f 100644 --- a/api/net/sf/briar/api/protocol/writers/OfferWriter.java +++ b/api/net/sf/briar/api/protocol/writers/OfferWriter.java @@ -3,6 +3,7 @@ package net.sf.briar.api.protocol.writers; import java.io.IOException; import net.sf.briar.api.protocol.MessageId; +import net.sf.briar.api.protocol.OfferId; /** An interface for creating a have notification. */ public interface OfferWriter { @@ -13,6 +14,6 @@ public interface OfferWriter { */ boolean writeMessageId(MessageId m) throws IOException; - /** Finishes writing the offer. */ - void finish() throws IOException; + /** Finishes writing the offer and returns its unique identifier. */ + OfferId finish() throws IOException; } diff --git a/api/net/sf/briar/api/protocol/writers/RequestWriter.java b/api/net/sf/briar/api/protocol/writers/RequestWriter.java index 335753f6c2..d284f5c0c1 100644 --- a/api/net/sf/briar/api/protocol/writers/RequestWriter.java +++ b/api/net/sf/briar/api/protocol/writers/RequestWriter.java @@ -3,9 +3,11 @@ package net.sf.briar.api.protocol.writers; import java.io.IOException; import java.util.BitSet; +import net.sf.briar.api.protocol.OfferId; + /** An interface for creating a request packet. */ public interface RequestWriter { /** Writes the contents of the request. */ - void writeBitmap(BitSet b, int length) throws IOException; + void writeRequest(OfferId offerId, BitSet b, int length) throws IOException; } diff --git a/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java b/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java index 2eb0dde388..eb8e93375e 100644 --- a/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java +++ b/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java @@ -815,7 +815,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> { db.abortTransaction(txn); throw e; } - r.writeBitmap(request, offered.size()); + r.writeRequest(o.getId(), request, offered.size()); } finally { subscriptionLock.readLock().unlock(); } diff --git a/components/net/sf/briar/db/SynchronizedDatabaseComponent.java b/components/net/sf/briar/db/SynchronizedDatabaseComponent.java index d99f65f4ed..466efead75 100644 --- a/components/net/sf/briar/db/SynchronizedDatabaseComponent.java +++ b/components/net/sf/briar/db/SynchronizedDatabaseComponent.java @@ -627,7 +627,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> { db.abortTransaction(txn); throw e; } - r.writeBitmap(request, offered.size()); + r.writeRequest(o.getId(), request, offered.size()); } } } diff --git a/components/net/sf/briar/protocol/AckReader.java b/components/net/sf/briar/protocol/AckReader.java index 77ba91d23d..96c74d70db 100644 --- a/components/net/sf/briar/protocol/AckReader.java +++ b/components/net/sf/briar/protocol/AckReader.java @@ -10,14 +10,11 @@ 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 AckReader implements ObjectReader<Ack> { private final ObjectReader<BatchId> batchIdReader; private final AckFactory ackFactory; - @Inject AckReader(ObjectReader<BatchId> batchIdReader, AckFactory ackFactory) { this.batchIdReader = batchIdReader; this.ackFactory = ackFactory; diff --git a/components/net/sf/briar/protocol/AuthorReader.java b/components/net/sf/briar/protocol/AuthorReader.java index e0d73ed3ba..4ce4cc8e40 100644 --- a/components/net/sf/briar/protocol/AuthorReader.java +++ b/components/net/sf/briar/protocol/AuthorReader.java @@ -11,14 +11,11 @@ import net.sf.briar.api.protocol.Tags; import net.sf.briar.api.serial.ObjectReader; import net.sf.briar.api.serial.Reader; -import com.google.inject.Inject; - class AuthorReader implements ObjectReader<Author> { private final MessageDigest messageDigest; private final AuthorFactory authorFactory; - @Inject AuthorReader(CryptoComponent crypto, AuthorFactory authorFactory) { messageDigest = crypto.getMessageDigest(); this.authorFactory = authorFactory; diff --git a/components/net/sf/briar/protocol/BatchReader.java b/components/net/sf/briar/protocol/BatchReader.java index 15ccb655cd..bc41e694e8 100644 --- a/components/net/sf/briar/protocol/BatchReader.java +++ b/components/net/sf/briar/protocol/BatchReader.java @@ -13,15 +13,12 @@ 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 BatchReader implements ObjectReader<Batch> { private final MessageDigest messageDigest; private final ObjectReader<Message> messageReader; private final BatchFactory batchFactory; - @Inject BatchReader(CryptoComponent crypto, ObjectReader<Message> messageReader, BatchFactory batchFactory) { messageDigest = crypto.getMessageDigest(); diff --git a/components/net/sf/briar/protocol/GroupReader.java b/components/net/sf/briar/protocol/GroupReader.java index dd61419a03..d855850dd4 100644 --- a/components/net/sf/briar/protocol/GroupReader.java +++ b/components/net/sf/briar/protocol/GroupReader.java @@ -11,14 +11,11 @@ import net.sf.briar.api.protocol.Tags; import net.sf.briar.api.serial.ObjectReader; import net.sf.briar.api.serial.Reader; -import com.google.inject.Inject; - class GroupReader implements ObjectReader<Group> { private final MessageDigest messageDigest; private final GroupFactory groupFactory; - @Inject GroupReader(CryptoComponent crypto, GroupFactory groupFactory) { messageDigest = crypto.getMessageDigest(); this.groupFactory = groupFactory; diff --git a/components/net/sf/briar/protocol/MessageReader.java b/components/net/sf/briar/protocol/MessageReader.java index 96b6824c5d..5319c11710 100644 --- a/components/net/sf/briar/protocol/MessageReader.java +++ b/components/net/sf/briar/protocol/MessageReader.java @@ -18,8 +18,6 @@ import net.sf.briar.api.serial.FormatException; import net.sf.briar.api.serial.ObjectReader; import net.sf.briar.api.serial.Reader; -import com.google.inject.Inject; - class MessageReader implements ObjectReader<Message> { private final ObjectReader<MessageId> messageIdReader; @@ -29,7 +27,6 @@ class MessageReader implements ObjectReader<Message> { private final Signature signature; private final MessageDigest messageDigest; - @Inject MessageReader(CryptoComponent crypto, ObjectReader<MessageId> messageIdReader, ObjectReader<Group> groupReader, diff --git a/components/net/sf/briar/protocol/OfferFactory.java b/components/net/sf/briar/protocol/OfferFactory.java index 6f19d4e291..c9a1c33cc7 100644 --- a/components/net/sf/briar/protocol/OfferFactory.java +++ b/components/net/sf/briar/protocol/OfferFactory.java @@ -4,8 +4,9 @@ import java.util.Collection; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.Offer; +import net.sf.briar.api.protocol.OfferId; interface OfferFactory { - Offer createOffer(Collection<MessageId> offered); + Offer createOffer(OfferId id, Collection<MessageId> offered); } diff --git a/components/net/sf/briar/protocol/OfferFactoryImpl.java b/components/net/sf/briar/protocol/OfferFactoryImpl.java index 075527d147..f76802c205 100644 --- a/components/net/sf/briar/protocol/OfferFactoryImpl.java +++ b/components/net/sf/briar/protocol/OfferFactoryImpl.java @@ -4,10 +4,11 @@ import java.util.Collection; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.Offer; +import net.sf.briar.api.protocol.OfferId; class OfferFactoryImpl implements OfferFactory { - public Offer createOffer(Collection<MessageId> offered) { - return new OfferImpl(offered); + public Offer createOffer(OfferId id, Collection<MessageId> offered) { + return new OfferImpl(id, offered); } } diff --git a/components/net/sf/briar/protocol/OfferIdReader.java b/components/net/sf/briar/protocol/OfferIdReader.java new file mode 100644 index 0000000000..52485760cf --- /dev/null +++ b/components/net/sf/briar/protocol/OfferIdReader.java @@ -0,0 +1,20 @@ +package net.sf.briar.protocol; + +import java.io.IOException; + +import net.sf.briar.api.protocol.OfferId; +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 OfferIdReader implements ObjectReader<OfferId> { + + public OfferId readObject(Reader r) throws IOException { + r.readUserDefinedTag(Tags.OFFER_ID); + byte[] b = r.readBytes(UniqueId.LENGTH); + if(b.length != UniqueId.LENGTH) throw new FormatException(); + return new OfferId(b); + } +} diff --git a/components/net/sf/briar/protocol/OfferImpl.java b/components/net/sf/briar/protocol/OfferImpl.java index de892202e6..0ce2e6bfe9 100644 --- a/components/net/sf/briar/protocol/OfferImpl.java +++ b/components/net/sf/briar/protocol/OfferImpl.java @@ -4,15 +4,22 @@ import java.util.Collection; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.Offer; +import net.sf.briar.api.protocol.OfferId; class OfferImpl implements Offer { + private final OfferId id; private final Collection<MessageId> offered; - OfferImpl(Collection<MessageId> offered) { + OfferImpl(OfferId id, Collection<MessageId> offered) { + this.id = id; this.offered = offered; } + public OfferId getId() { + return id; + } + public Collection<MessageId> getMessageIds() { return offered; } diff --git a/components/net/sf/briar/protocol/OfferReader.java b/components/net/sf/briar/protocol/OfferReader.java index 459310dec1..e269e865a6 100644 --- a/components/net/sf/briar/protocol/OfferReader.java +++ b/components/net/sf/briar/protocol/OfferReader.java @@ -1,40 +1,47 @@ package net.sf.briar.protocol; import java.io.IOException; +import java.security.MessageDigest; import java.util.Collection; +import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.Offer; +import net.sf.briar.api.protocol.OfferId; 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<Offer> { + private final MessageDigest messageDigest; private final ObjectReader<MessageId> messageIdReader; private final OfferFactory offerFactory; - @Inject - OfferReader(ObjectReader<MessageId> messageIdReader, + OfferReader(CryptoComponent crypto, ObjectReader<MessageId> messageIdReader, OfferFactory offerFactory) { + messageDigest = crypto.getMessageDigest(); this.messageIdReader = messageIdReader; this.offerFactory = offerFactory; } public Offer readObject(Reader r) throws IOException { - // Initialise the consumer + // Initialise the consumers Consumer counting = new CountingConsumer(Offer.MAX_SIZE); + DigestingConsumer digesting = new DigestingConsumer(messageDigest); + messageDigest.reset(); // Read the data r.addConsumer(counting); + r.addConsumer(digesting); r.readUserDefinedTag(Tags.OFFER); r.addObjectReader(Tags.MESSAGE_ID, messageIdReader); Collection<MessageId> messages = r.readList(MessageId.class); r.removeObjectReader(Tags.MESSAGE_ID); + r.removeConsumer(digesting); r.removeConsumer(counting); // Build and return the offer - return offerFactory.createOffer(messages); + OfferId id = new OfferId(messageDigest.digest()); + return offerFactory.createOffer(id, messages); } } diff --git a/components/net/sf/briar/protocol/ProtocolModule.java b/components/net/sf/briar/protocol/ProtocolModule.java index 6d36d8efb3..79d4bac586 100644 --- a/components/net/sf/briar/protocol/ProtocolModule.java +++ b/components/net/sf/briar/protocol/ProtocolModule.java @@ -12,6 +12,7 @@ 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.OfferId; import net.sf.briar.api.protocol.ProtocolReaderFactory; import net.sf.briar.api.protocol.Request; import net.sf.briar.api.protocol.SubscriptionUpdate; @@ -81,14 +82,21 @@ public class ProtocolModule extends AbstractModule { } @Provides - ObjectReader<Offer> getOfferReader(ObjectReader<MessageId> messageIdReader, + ObjectReader<OfferId> getOfferIdReader() { + return new OfferIdReader(); + } + + @Provides + ObjectReader<Offer> getOfferReader(CryptoComponent crypto, + ObjectReader<MessageId> messageIdReader, OfferFactory offerFactory) { - return new OfferReader(messageIdReader, offerFactory); + return new OfferReader(crypto, messageIdReader, offerFactory); } @Provides - ObjectReader<Request> getRequestReader(RequestFactory requestFactory) { - return new RequestReader(requestFactory); + ObjectReader<Request> getRequestReader(ObjectReader<OfferId> offerIdReader, + RequestFactory requestFactory) { + return new RequestReader(offerIdReader, requestFactory); } @Provides diff --git a/components/net/sf/briar/protocol/RequestFactory.java b/components/net/sf/briar/protocol/RequestFactory.java index 005982b826..09459765a6 100644 --- a/components/net/sf/briar/protocol/RequestFactory.java +++ b/components/net/sf/briar/protocol/RequestFactory.java @@ -2,9 +2,10 @@ package net.sf.briar.protocol; import java.util.BitSet; +import net.sf.briar.api.protocol.OfferId; import net.sf.briar.api.protocol.Request; interface RequestFactory { - Request createRequest(BitSet requested); + Request createRequest(OfferId offerId, BitSet requested); } diff --git a/components/net/sf/briar/protocol/RequestFactoryImpl.java b/components/net/sf/briar/protocol/RequestFactoryImpl.java index 0c2c77cb1c..68cce91c54 100644 --- a/components/net/sf/briar/protocol/RequestFactoryImpl.java +++ b/components/net/sf/briar/protocol/RequestFactoryImpl.java @@ -2,11 +2,12 @@ package net.sf.briar.protocol; import java.util.BitSet; +import net.sf.briar.api.protocol.OfferId; import net.sf.briar.api.protocol.Request; class RequestFactoryImpl implements RequestFactory { - public Request createRequest(BitSet requested) { - return new RequestImpl(requested); + public Request createRequest(OfferId offerId, BitSet requested) { + return new RequestImpl(offerId, requested); } } diff --git a/components/net/sf/briar/protocol/RequestImpl.java b/components/net/sf/briar/protocol/RequestImpl.java index ddb31898ae..42d3247ee9 100644 --- a/components/net/sf/briar/protocol/RequestImpl.java +++ b/components/net/sf/briar/protocol/RequestImpl.java @@ -2,16 +2,23 @@ package net.sf.briar.protocol; import java.util.BitSet; +import net.sf.briar.api.protocol.OfferId; import net.sf.briar.api.protocol.Request; class RequestImpl implements Request { + private final OfferId offerId; private final BitSet requested; - RequestImpl(BitSet requested) { + RequestImpl(OfferId offerId, BitSet requested) { + this.offerId = offerId; this.requested = requested; } + public OfferId getOfferId() { + return offerId; + } + public BitSet getBitmap() { return requested; } diff --git a/components/net/sf/briar/protocol/RequestReader.java b/components/net/sf/briar/protocol/RequestReader.java index 5677790076..901a557564 100644 --- a/components/net/sf/briar/protocol/RequestReader.java +++ b/components/net/sf/briar/protocol/RequestReader.java @@ -3,20 +3,21 @@ package net.sf.briar.protocol; import java.io.IOException; import java.util.BitSet; +import net.sf.briar.api.protocol.OfferId; import net.sf.briar.api.protocol.Request; 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 RequestReader implements ObjectReader<Request> { + private final ObjectReader<OfferId> offerIdReader; private final RequestFactory requestFactory; - @Inject - RequestReader(RequestFactory requestFactory) { + RequestReader(ObjectReader<OfferId> offerIdReader, + RequestFactory requestFactory) { + this.offerIdReader = offerIdReader; this.requestFactory = requestFactory; } @@ -26,6 +27,8 @@ class RequestReader implements ObjectReader<Request> { // Read the data r.addConsumer(counting); r.readUserDefinedTag(Tags.REQUEST); + r.addObjectReader(Tags.OFFER_ID, offerIdReader); + OfferId offerId = r.readUserDefined(Tags.OFFER_ID, OfferId.class); byte[] bitmap = r.readBytes(Request.MAX_SIZE); r.removeConsumer(counting); // Convert the bitmap into a BitSet @@ -36,6 +39,6 @@ class RequestReader implements ObjectReader<Request> { if((bitmap[i] & bit) != 0) b.set(i * 8 + j); } } - return requestFactory.createRequest(b); + return requestFactory.createRequest(offerId, b); } } diff --git a/components/net/sf/briar/protocol/SubscriptionReader.java b/components/net/sf/briar/protocol/SubscriptionReader.java index 6c31dad6fb..8faaf647e1 100644 --- a/components/net/sf/briar/protocol/SubscriptionReader.java +++ b/components/net/sf/briar/protocol/SubscriptionReader.java @@ -10,14 +10,11 @@ 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 SubscriptionReader implements ObjectReader<SubscriptionUpdate> { private final ObjectReader<Group> groupReader; private final SubscriptionFactory subscriptionFactory; - @Inject SubscriptionReader(ObjectReader<Group> groupReader, SubscriptionFactory subscriptionFactory) { this.groupReader = groupReader; diff --git a/components/net/sf/briar/protocol/TransportReader.java b/components/net/sf/briar/protocol/TransportReader.java index 92a2a47905..2ea5e61b3b 100644 --- a/components/net/sf/briar/protocol/TransportReader.java +++ b/components/net/sf/briar/protocol/TransportReader.java @@ -10,13 +10,10 @@ 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 TransportReader implements ObjectReader<TransportUpdate> { private final TransportFactory transportFactory; - @Inject TransportReader(TransportFactory transportFactory) { this.transportFactory = transportFactory; } diff --git a/components/net/sf/briar/protocol/writers/OfferWriterImpl.java b/components/net/sf/briar/protocol/writers/OfferWriterImpl.java index c0ec46fe94..7bbac598df 100644 --- a/components/net/sf/briar/protocol/writers/OfferWriterImpl.java +++ b/components/net/sf/briar/protocol/writers/OfferWriterImpl.java @@ -2,9 +2,12 @@ package net.sf.briar.protocol.writers; import java.io.IOException; import java.io.OutputStream; +import java.security.DigestOutputStream; +import java.security.MessageDigest; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.Offer; +import net.sf.briar.api.protocol.OfferId; import net.sf.briar.api.protocol.Tags; import net.sf.briar.api.protocol.writers.OfferWriter; import net.sf.briar.api.serial.Writer; @@ -14,17 +17,20 @@ class OfferWriterImpl implements OfferWriter { private final OutputStream out; private final Writer w; + private final MessageDigest messageDigest; - private boolean started = false, finished = false; + private boolean started = false; - OfferWriterImpl(OutputStream out, WriterFactory writerFactory) { - this.out = out; + OfferWriterImpl(OutputStream out, WriterFactory writerFactory, + MessageDigest messageDigest) { + this.out = new DigestOutputStream(out, messageDigest); w = writerFactory.createWriter(out); + this.messageDigest = messageDigest; } public boolean writeMessageId(MessageId m) throws IOException { - if(finished) throw new IllegalStateException(); if(!started) { + messageDigest.reset(); w.writeUserDefinedTag(Tags.OFFER); w.writeListStart(); started = true; @@ -35,15 +41,16 @@ class OfferWriterImpl implements OfferWriter { return true; } - public void finish() throws IOException { - if(finished) throw new IllegalStateException(); + public OfferId finish() throws IOException { if(!started) { + messageDigest.reset(); w.writeUserDefinedTag(Tags.OFFER); w.writeListStart(); started = true; } w.writeListEnd(); out.flush(); - finished = true; + started = false; + return new OfferId(messageDigest.digest()); } } diff --git a/components/net/sf/briar/protocol/writers/ProtocolWriterFactoryImpl.java b/components/net/sf/briar/protocol/writers/ProtocolWriterFactoryImpl.java index 2599940367..ce14908f1c 100644 --- a/components/net/sf/briar/protocol/writers/ProtocolWriterFactoryImpl.java +++ b/components/net/sf/briar/protocol/writers/ProtocolWriterFactoryImpl.java @@ -36,7 +36,7 @@ class ProtocolWriterFactoryImpl implements ProtocolWriterFactory { } public OfferWriter createOfferWriter(OutputStream out) { - return new OfferWriterImpl(out, writerFactory); + return new OfferWriterImpl(out, writerFactory, messageDigest); } public RequestWriter createRequestWriter(OutputStream out) { diff --git a/components/net/sf/briar/protocol/writers/RequestWriterImpl.java b/components/net/sf/briar/protocol/writers/RequestWriterImpl.java index 28bce226a2..d50909dabb 100644 --- a/components/net/sf/briar/protocol/writers/RequestWriterImpl.java +++ b/components/net/sf/briar/protocol/writers/RequestWriterImpl.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.OutputStream; import java.util.BitSet; +import net.sf.briar.api.protocol.OfferId; import net.sf.briar.api.protocol.Tags; import net.sf.briar.api.protocol.writers.RequestWriter; import net.sf.briar.api.serial.Writer; @@ -19,8 +20,11 @@ class RequestWriterImpl implements RequestWriter { w = writerFactory.createWriter(out); } - public void writeBitmap(BitSet b, int length) throws IOException { + public void writeRequest(OfferId offerId, BitSet b, int length) + throws IOException { w.writeUserDefinedTag(Tags.REQUEST); + w.writeUserDefinedTag(Tags.OFFER_ID); + w.writeBytes(offerId.getBytes()); // If the number of bits isn't a multiple of 8, round up to a byte int bytes = length % 8 == 0 ? length / 8 : length / 8 + 1; byte[] bitmap = new byte[bytes]; diff --git a/test/net/sf/briar/FileReadWriteTest.java b/test/net/sf/briar/FileReadWriteTest.java index 490c0d08b0..4988507957 100644 --- a/test/net/sf/briar/FileReadWriteTest.java +++ b/test/net/sf/briar/FileReadWriteTest.java @@ -27,6 +27,7 @@ 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.OfferId; import net.sf.briar.api.protocol.ProtocolReader; import net.sf.briar.api.protocol.ProtocolReaderFactory; import net.sf.briar.api.protocol.Request; @@ -78,6 +79,7 @@ public class FileReadWriteTest extends TestCase { private final Message message, message1, message2, message3; private final String authorName = "Alice"; private final String messageBody = "Hello world"; + private final OfferId offerId; private final Map<String, Map<String, String>> transports; public FileReadWriteTest() throws Exception { @@ -114,6 +116,7 @@ public class FileReadWriteTest extends TestCase { message3 = messageEncoder.encodeMessage(MessageId.NONE, group1, groupKeyPair.getPrivate(), author, authorKeyPair.getPrivate(), messageBody.getBytes("UTF-8")); + offerId = new OfferId(TestUtils.getRandomId()); transports = Collections.singletonMap("foo", Collections.singletonMap("bar", "baz")); } @@ -155,7 +158,7 @@ public class FileReadWriteTest extends TestCase { BitSet requested = new BitSet(4); requested.set(1); requested.set(3); - r.writeBitmap(requested, 4); + r.writeRequest(offerId, requested, 4); packetWriter.finishPacket(); SubscriptionWriter s = @@ -231,6 +234,7 @@ public class FileReadWriteTest extends TestCase { assertTrue(protocolReader.hasRequest()); Request r = protocolReader.readRequest(); packetReader.finishPacket(); + assertEquals(offerId, r.getOfferId()); BitSet requested = r.getBitmap(); assertFalse(requested.get(0)); assertTrue(requested.get(1)); diff --git a/test/net/sf/briar/db/DatabaseCleanerImplTest.java b/test/net/sf/briar/db/DatabaseCleanerImplTest.java index 691574da04..1042338aea 100644 --- a/test/net/sf/briar/db/DatabaseCleanerImplTest.java +++ b/test/net/sf/briar/db/DatabaseCleanerImplTest.java @@ -12,7 +12,7 @@ import org.junit.Test; public class DatabaseCleanerImplTest extends TestCase { @Test - public void testStoppingCleanerWakesItUp() throws DbException { + public void testStoppingCleanerWakesItUp() throws Exception { final CountDownLatch latch = new CountDownLatch(1); Callback callback = new Callback() { @@ -31,11 +31,7 @@ public class DatabaseCleanerImplTest extends TestCase { long start = System.currentTimeMillis(); // Start the cleaner and check that shouldCheckFreeSpace() is called cleaner.startCleaning(); - try { - assertTrue(latch.await(5, TimeUnit.SECONDS)); - } catch(InterruptedException e) { - fail(); - } + assertTrue(latch.await(5, TimeUnit.SECONDS)); // Stop the cleaner (it should be waiting between sweeps) cleaner.stopCleaning(); long end = System.currentTimeMillis(); diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java index 193f4392ea..f49ce59077 100644 --- a/test/net/sf/briar/db/DatabaseComponentTest.java +++ b/test/net/sf/briar/db/DatabaseComponentTest.java @@ -12,10 +12,10 @@ import net.sf.briar.api.ContactId; import net.sf.briar.api.Rating; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DatabaseListener; +import net.sf.briar.api.db.DatabaseListener.Event; import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.NoSuchContactException; import net.sf.briar.api.db.Status; -import net.sf.briar.api.db.DatabaseListener.Event; import net.sf.briar.api.protocol.Ack; import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.Batch; @@ -25,6 +25,7 @@ import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.Offer; +import net.sf.briar.api.protocol.OfferId; import net.sf.briar.api.protocol.SubscriptionUpdate; import net.sf.briar.api.protocol.TransportUpdate; import net.sf.briar.api.protocol.writers.AckWriter; @@ -49,6 +50,7 @@ public abstract class DatabaseComponentTest extends TestCase { protected final ContactId contactId; protected final GroupId groupId; protected final MessageId messageId, parentId; + protected final OfferId offerId; private final long timestamp; private final int size; private final byte[] raw; @@ -65,6 +67,7 @@ public abstract class DatabaseComponentTest extends TestCase { groupId = new GroupId(TestUtils.getRandomId()); messageId = new MessageId(TestUtils.getRandomId()); parentId = new MessageId(TestUtils.getRandomId()); + offerId = new OfferId(TestUtils.getRandomId()); timestamp = System.currentTimeMillis(); size = 1234; raw = new byte[size]; @@ -1031,7 +1034,9 @@ public abstract class DatabaseComponentTest extends TestCase { will(returnValue(true)); // Visible - do not request message # 1 oneOf(database).setStatusSeenIfVisible(txn, contactId, messageId2); will(returnValue(false)); // Not visible - request message # 2 - oneOf(requestWriter).writeBitmap(expectedRequest, 3); + oneOf(offer).getId(); + will(returnValue(offerId)); + oneOf(requestWriter).writeRequest(offerId, expectedRequest, 3); }}); DatabaseComponent db = createDatabaseComponent(database, cleaner); diff --git a/test/net/sf/briar/protocol/ProtocolReadWriteTest.java b/test/net/sf/briar/protocol/ProtocolReadWriteTest.java index cee401bc54..3757ad9f04 100644 --- a/test/net/sf/briar/protocol/ProtocolReadWriteTest.java +++ b/test/net/sf/briar/protocol/ProtocolReadWriteTest.java @@ -17,6 +17,7 @@ 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.OfferId; import net.sf.briar.api.protocol.ProtocolReader; import net.sf.briar.api.protocol.ProtocolReaderFactory; import net.sf.briar.api.protocol.Request; @@ -46,6 +47,7 @@ public class ProtocolReadWriteTest extends TestCase { private final Group group; private final Message message; private final String messageBody = "Hello world"; + private final OfferId offerId; private final BitSet bitSet; private final Map<Group, Long> subscriptions; private final Map<String, Map<String, String>> transports; @@ -62,6 +64,7 @@ public class ProtocolReadWriteTest extends TestCase { MessageEncoder messageEncoder = i.getInstance(MessageEncoder.class); message = messageEncoder.encodeMessage(MessageId.NONE, group, messageBody.getBytes("UTF-8")); + offerId = new OfferId(TestUtils.getRandomId()); bitSet = new BitSet(); bitSet.set(3); bitSet.set(7); @@ -90,7 +93,7 @@ public class ProtocolReadWriteTest extends TestCase { o.finish(); RequestWriter r = writerFactory.createRequestWriter(out); - r.writeBitmap(bitSet, 10); + r.writeRequest(offerId, bitSet, 10); SubscriptionWriter s = writerFactory.createSubscriptionWriter(out); s.writeSubscriptions(subscriptions); diff --git a/test/net/sf/briar/protocol/RequestReaderTest.java b/test/net/sf/briar/protocol/RequestReaderTest.java index 4ff8865903..b9c2be3ef8 100644 --- a/test/net/sf/briar/protocol/RequestReaderTest.java +++ b/test/net/sf/briar/protocol/RequestReaderTest.java @@ -5,8 +5,10 @@ import java.io.ByteArrayOutputStream; import java.util.BitSet; import junit.framework.TestCase; +import net.sf.briar.api.protocol.OfferId; import net.sf.briar.api.protocol.Request; 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.Reader; import net.sf.briar.api.serial.ReaderFactory; @@ -38,7 +40,8 @@ public class RequestReaderTest extends TestCase { @Test public void testFormatExceptionIfRequestIsTooLarge() throws Exception { RequestFactory requestFactory = context.mock(RequestFactory.class); - RequestReader requestReader = new RequestReader(requestFactory); + RequestReader requestReader = + new RequestReader(new OfferIdReader(), requestFactory); byte[] b = createRequest(true); ByteArrayInputStream in = new ByteArrayInputStream(b); @@ -56,10 +59,12 @@ public class RequestReaderTest extends TestCase { public void testNoFormatExceptionIfRequestIsMaximumSize() throws Exception { final RequestFactory requestFactory = context.mock(RequestFactory.class); - RequestReader requestReader = new RequestReader(requestFactory); + RequestReader requestReader = + new RequestReader(new OfferIdReader(), requestFactory); final Request request = context.mock(Request.class); context.checking(new Expectations() {{ - oneOf(requestFactory).createRequest(with(any(BitSet.class))); + oneOf(requestFactory).createRequest(with(any(OfferId.class)), + with(any(BitSet.class))); will(returnValue(request)); }}); @@ -95,8 +100,8 @@ public class RequestReaderTest extends TestCase { // Deserialise the request ByteArrayInputStream in = new ByteArrayInputStream(b); Reader reader = readerFactory.createReader(in); - RequestReader requestReader = - new RequestReader(new RequestFactoryImpl()); + RequestReader requestReader = new RequestReader(new OfferIdReader(), + new RequestFactoryImpl()); reader.addObjectReader(Tags.REQUEST, requestReader); Request r = reader.readUserDefined(Tags.REQUEST, Request.class); BitSet decoded = r.getBitmap(); @@ -115,10 +120,15 @@ public class RequestReaderTest extends TestCase { ByteArrayOutputStream out = new ByteArrayOutputStream(); Writer w = writerFactory.createWriter(out); w.writeUserDefinedTag(Tags.REQUEST); - // Allow one byte for the REQUEST tag, one byte for the BYTES tag, and - // five bytes for the length as an int32 - if(tooBig) w.writeBytes(new byte[Request.MAX_SIZE - 6]); - else w.writeBytes(new byte[Request.MAX_SIZE - 7]); + w.writeUserDefinedTag(Tags.OFFER_ID); + w.writeBytes(new byte[UniqueId.LENGTH]); + // Allow one byte for the REQUEST tag, one byte for the OFFER_ID tag, + // one byte for the BYTES tag, one byte for the length as a uint7, + // UniqueID.LENGTH bytes for the offer ID, one byte for the BYTES tag, + // and five bytes for the length as an int32 + int overhead = UniqueId.LENGTH + 10; + if(tooBig) w.writeBytes(new byte[Request.MAX_SIZE - overhead + 1]); + else w.writeBytes(new byte[Request.MAX_SIZE - overhead]); assertEquals(tooBig, out.size() > Request.MAX_SIZE); return out.toByteArray(); } @@ -127,6 +137,8 @@ public class RequestReaderTest extends TestCase { ByteArrayOutputStream out = new ByteArrayOutputStream(); Writer w = writerFactory.createWriter(out); w.writeUserDefinedTag(Tags.REQUEST); + w.writeUserDefinedTag(Tags.OFFER_ID); + w.writeBytes(new byte[UniqueId.LENGTH]); w.writeBytes(bitmap); return out.toByteArray(); } diff --git a/test/net/sf/briar/protocol/writers/RequestWriterImplTest.java b/test/net/sf/briar/protocol/writers/RequestWriterImplTest.java index b612f95bb1..e7e5d7e73f 100644 --- a/test/net/sf/briar/protocol/writers/RequestWriterImplTest.java +++ b/test/net/sf/briar/protocol/writers/RequestWriterImplTest.java @@ -5,6 +5,8 @@ import java.io.IOException; import java.util.BitSet; import junit.framework.TestCase; +import net.sf.briar.api.protocol.OfferId; +import net.sf.briar.api.protocol.UniqueId; import net.sf.briar.api.protocol.writers.RequestWriter; import net.sf.briar.api.serial.WriterFactory; import net.sf.briar.serial.SerialModule; @@ -18,11 +20,13 @@ import com.google.inject.Injector; public class RequestWriterImplTest extends TestCase { private final WriterFactory writerFactory; + private final OfferId offerId; public RequestWriterImplTest() { super(); Injector i = Guice.createInjector(new SerialModule()); writerFactory = i.getInstance(WriterFactory.class); + offerId = new OfferId(new byte[UniqueId.LENGTH]); } @Test @@ -41,10 +45,14 @@ public class RequestWriterImplTest extends TestCase { b.set(11); b.set(12); b.set(15); - r.writeBitmap(b, 16); - // Short user tag 10, short bytes with length 2, 0xD959 + r.writeRequest(offerId, b, 16); + // Short user tag 11, short user tag 10, bytes with length 32 as a + // uint7, 32 zero bytes, short bytes with length 2, 0xD959 byte[] output = out.toByteArray(); - assertEquals("CA" + "92" + "D959", StringUtils.toHexString(output)); + assertEquals("CB" + "CA" + "F6" + "20" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "92" + "D959", StringUtils.toHexString(output)); } @Test @@ -62,9 +70,13 @@ public class RequestWriterImplTest extends TestCase { b.set(9); b.set(11); b.set(12); - r.writeBitmap(b, 13); - // Short user tag 10, short bytes with length 2, 0x59D8 + r.writeRequest(offerId, b, 13); + // Short user tag 11, short user tag 10, bytes with length 32 as a + // uint7, 32 zero bytes, short bytes with length 2, 0x59D8 byte[] output = out.toByteArray(); - assertEquals("CA" + "92" + "59D8", StringUtils.toHexString(output)); + assertEquals("CB" + "CA" + "F6" + "20" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "92" + "59D8", StringUtils.toHexString(output)); } } -- GitLab