Part 1 of a major BMP and database refactoring. Tests are broken!

The old logic for selecting when to send subscription and transport
updates has been removed and not yet replaced. Subscription times have
been removed from subscription updates. The database expiry time has
been remove from subscription updates and will later get its own update
packet. Transport updates have been broken up into one update per
transport. Acks for subscription and transport updates have been added.
This commit is contained in:
akwizgran
2013-01-25 15:38:37 +00:00
parent b8247968b6
commit 64bf1fbbb1
67 changed files with 1411 additions and 1762 deletions

View File

@@ -17,8 +17,9 @@ 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.Request;
import net.sf.briar.api.protocol.SubscriptionAck;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportAck;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.transport.ContactTransport;
@@ -66,6 +67,9 @@ public interface DatabaseComponent {
*/
void addSecrets(Collection<TemporarySecret> secrets) throws DbException;
/** Adds a transport to the database. */
void addTransport(TransportId t) throws DbException;
/**
* Generates an acknowledgement for the given contact. Returns null if
* there are no messages to acknowledge.
@@ -98,18 +102,32 @@ public interface DatabaseComponent {
*/
Offer generateOffer(ContactId c, int maxMessages) throws DbException;
/**
* Generates a subscription ack for the given contact. Returns null if no
* ack is due.
*/
SubscriptionAck generateSubscriptionAck(ContactId c) throws DbException;
/**
* Generates a subscription update for the given contact. Returns null if
* an update is not due.
* no update is due.
*/
SubscriptionUpdate generateSubscriptionUpdate(ContactId c)
throws DbException;
/**
* Generates a transport update for the given contact. Returns null if an
* update is not due.
* Generates a batch of transport acks for the given contact. Returns null
* if no acks are due.
*/
TransportUpdate generateTransportUpdate(ContactId c) throws DbException;
Collection<TransportAck> generateTransportAcks(ContactId c)
throws DbException;
/**
* Generates a batch of transport updates for the given contact. Returns
* null if no updates are due.
*/
Collection<TransportUpdate> generateTransportUpdates(ContactId c)
throws DbException;
/** Returns the configuration for the given transport. */
TransportConfig getConfig(TransportId t) throws DbException;
@@ -120,9 +138,6 @@ public interface DatabaseComponent {
/** Returns the local transport properties for the given transport. */
TransportProperties getLocalProperties(TransportId t) throws DbException;
/** Returns all local transports. */
Collection<Transport> getLocalTransports() throws DbException;
/** Returns the headers of all messages in the given group. */
Collection<MessageHeader> getMessageHeaders(GroupId g) throws DbException;
@@ -168,7 +183,7 @@ public interface DatabaseComponent {
void mergeLocalProperties(TransportId t, TransportProperties p)
throws DbException;
/** Processes an acknowledgement from the given contact. */
/** Processes an ack from the given contact. */
void receiveAck(ContactId c, Ack a) throws DbException;
/** Processes a message from the given contact. */
@@ -184,10 +199,17 @@ public interface DatabaseComponent {
*/
Request receiveOffer(ContactId c, Offer o) throws DbException;
/** Processes a subscription ack from the given contact. */
void receiveSubscriptionAck(ContactId c, SubscriptionAck a)
throws DbException;
/** Processes a subscription update from the given contact. */
void receiveSubscriptionUpdate(ContactId c, SubscriptionUpdate s)
throws DbException;
/** Processes a transport ack from the given contact. */
void receiveTransportAck(ContactId c, TransportAck a) throws DbException;
/** Processes a transport update from the given contact. */
void receiveTransportUpdate(ContactId c, TransportUpdate t)
throws DbException;

View File

@@ -1,27 +0,0 @@
package net.sf.briar.api.db.event;
import java.util.Collection;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.protocol.Transport;
/** An event that is broadcast when a contact's transports are updated. */
public class RemoteTransportsUpdatedEvent extends DatabaseEvent {
private final ContactId contactId;
private final Collection<Transport> transports;
public RemoteTransportsUpdatedEvent(ContactId contactId,
Collection<Transport> transports) {
this.contactId = contactId;
this.transports = transports;
}
public ContactId getContactId() {
return contactId;
}
public Collection<Transport> getTransports() {
return transports;
}
}

View File

@@ -4,6 +4,6 @@ package net.sf.briar.api.db.event;
* An event that is broadcast when the local transport properties are
* updated.
*/
public class LocalTransportsUpdatedEvent extends DatabaseEvent {
public class TransportsUpdatedEvent extends DatabaseEvent {
}

View File

@@ -2,9 +2,17 @@ package net.sf.briar.api.protocol;
import java.util.Collection;
/** A packet acknowledging receipt of one or more messages. */
public interface Ack {
/** A packet acknowledging receipt of one or more {@link Message}s. */
public class Ack {
/** Returns the IDs of the acknowledged messages. */
Collection<MessageId> getMessageIds();
private final Collection<MessageId> acked;
public Ack(Collection<MessageId> acked) {
this.acked = acked;
}
/** Returns the identifiers of the acknowledged messages. */
public Collection<MessageId> getMessageIds() {
return acked;
}
}

View File

@@ -1,17 +1,43 @@
package net.sf.briar.api.protocol;
/** A pseudonymous author of messages. */
public interface Author {
/** A pseudonymous author of {@link Message}s. */
public class Author {
private final AuthorId id;
private final String name;
private final byte[] publicKey;
public Author(AuthorId id, String name, byte[] publicKey) {
this.id = id;
this.name = name;
this.publicKey = publicKey;
}
/** Returns the author's unique identifier. */
AuthorId getId();
public AuthorId getId() {
return id;
}
/** Returns the author's name. */
String getName();
public String getName() {
return name;
}
/**
* Returns the public key that is used to verify messages signed by the
* author.
*/
byte[] getPublicKey();
public byte[] getPublicKey() {
return publicKey;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof Author && id.equals(((Author) o).id);
}
}

View File

@@ -5,6 +5,4 @@ import java.io.IOException;
public interface AuthorFactory {
Author createAuthor(String name, byte[] publicKey) throws IOException;
Author createAuthor(AuthorId id, String name, byte[] publicKey);
}

View File

@@ -2,7 +2,10 @@ package net.sf.briar.api.protocol;
import java.util.Arrays;
/** Type-safe wrapper for a byte array that uniquely identifies an author. */
/**
* Type-safe wrapper for a byte array that uniquely identifies an
* {@link Author}.
*/
public class AuthorId extends UniqueId {
public AuthorId(byte[] id) {

View File

@@ -3,8 +3,7 @@ package net.sf.briar.api.protocol;
import java.util.Arrays;
/**
* Type-safe wrapper for a byte array that uniquely identifies a group to which
* users may subscribe.
* Type-safe wrapper for a byte array that uniquely identifies a {@link Group}.
*/
public class GroupId extends UniqueId {

View File

@@ -6,21 +6,27 @@ public interface Message {
MessageId getId();
/**
* Returns the message's parent, or null if this is the first message in a
* thread.
* Returns the identifier of the message's parent, or null if this is the
* first message in a thread.
*/
MessageId getParent();
/** Returns the group to which the message belongs. */
/**
* Returns the identifier of the {@link Group} to which the message
* belongs, or null if this is a private message.
*/
GroupId getGroup();
/** Returns the message's author. */
/**
* Returns the identifier of the message's {@link Author}, or null if this
* is an anonymous message.
*/
AuthorId getAuthor();
/** Returns the message's subject line. */
String getSubject();
/** Returns the timestamp created by the message's author. */
/** Returns the timestamp created by the message's {@link Author}. */
long getTimestamp();
/** Returns the serialised message. */

View File

@@ -2,7 +2,10 @@ package net.sf.briar.api.protocol;
import java.util.Arrays;
/** Type-safe wrapper for a byte array that uniquely identifies a message. */
/**
* Type-safe wrapper for a byte array that uniquely identifies a
* {@link Message}.
*/
public class MessageId extends UniqueId {
public MessageId(byte[] id) {

View File

@@ -2,6 +2,7 @@ package net.sf.briar.api.protocol;
import java.security.GeneralSecurityException;
/** Verifies the signatures on an {@link UnverifiedMessage}. */
public interface MessageVerifier {
Message verifyMessage(UnverifiedMessage m) throws GeneralSecurityException;

View File

@@ -2,9 +2,17 @@ package net.sf.briar.api.protocol;
import java.util.Collection;
/** A packet offering the recipient some messages. */
public interface Offer {
/** A packet offering the recipient one or more {@link Messages}. */
public class Offer {
/** Returns the message IDs contained in the offer. */
Collection<MessageId> getMessageIds();
private final Collection<MessageId> offered;
public Offer(Collection<MessageId> offered) {
this.offered = offered;
}
/** Returns the identifiers of the offered messages. */
public Collection<MessageId> getMessageIds() {
return offered;
}
}

View File

@@ -1,20 +0,0 @@
package net.sf.briar.api.protocol;
import java.util.BitSet;
import java.util.Collection;
import java.util.Map;
public interface PacketFactory {
Ack createAck(Collection<MessageId> acked);
Offer createOffer(Collection<MessageId> offered);
Request createRequest(BitSet requested, int length);
SubscriptionUpdate createSubscriptionUpdate(Map<GroupId, GroupId> holes,
Map<Group, Long> subs, long expiry, long timestamp);
TransportUpdate createTransportUpdate(Collection<Transport> transports,
long timestamp);
}

View File

@@ -11,9 +11,6 @@ public interface ProtocolConstants {
*/
int MAX_PACKET_LENGTH = MIN_CONNECTION_LENGTH / 2;
/** The maximum number of transports a node may support. */
int MAX_TRANSPORTS = 25;
/** The maximum number of properties per transport. */
int MAX_PROPERTIES_PER_TRANSPORT = 100;

View File

@@ -18,9 +18,15 @@ public interface ProtocolReader {
boolean hasRequest() throws IOException;
Request readRequest() throws IOException;
boolean hasSubscriptionAck() throws IOException;
SubscriptionAck readSubscriptionAck() throws IOException;
boolean hasSubscriptionUpdate() throws IOException;
SubscriptionUpdate readSubscriptionUpdate() throws IOException;
boolean hasTransportAck() throws IOException;
TransportAck readTransportAck() throws IOException;
boolean hasTransportUpdate() throws IOException;
TransportUpdate readTransportUpdate() throws IOException;
}

View File

@@ -16,8 +16,12 @@ public interface ProtocolWriter {
void writeRequest(Request r) throws IOException;
void writeSubscriptionAck(SubscriptionAck a) throws IOException;
void writeSubscriptionUpdate(SubscriptionUpdate s) throws IOException;
void writeTransportAck(TransportAck a) throws IOException;
void writeTransportUpdate(TransportUpdate t) throws IOException;
void flush() throws IOException;

View File

@@ -2,15 +2,30 @@ package net.sf.briar.api.protocol;
import java.util.BitSet;
/** A packet requesting some or all of the messages from an offer. */
public interface Request {
/**
* A packet requesting some or all of the {@link Message}s from an
* {@link Offer}.
*/
public class Request {
private final BitSet requested;
private final int length;
public Request(BitSet requested, int length) {
this.requested = requested;
this.length = length;
}
/**
* 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.
*/
BitSet getBitmap();
public BitSet getBitmap() {
return requested;
}
/** Returns the length of the bitmap in bits. */
int getLength();
public int getLength() {
return length;
}
}

View File

@@ -0,0 +1,16 @@
package net.sf.briar.api.protocol;
/** A packet acknowledging a {@link SubscriptionUpdate}. */
public class SubscriptionAck {
final long version;
public SubscriptionAck(long version) {
this.version = version;
}
/** Returns the version number of the acknowledged update. */
public long getVersionNumber() {
return version;
}
}

View File

@@ -1,25 +1,28 @@
package net.sf.briar.api.protocol;
import java.util.Map;
import java.util.Collection;
/** A packet updating the sender's subscriptions. */
public interface SubscriptionUpdate {
public class SubscriptionUpdate {
/** Returns the holes contained in the update. */
Map<GroupId, GroupId> getHoles();
private final Collection<Group> subs;
private final long version;
/** Returns the subscriptions contained in the update. */
Map<Group, Long> getSubscriptions();
public SubscriptionUpdate(Collection<Group> subs, long version) {
this.subs = subs;
this.version = version;
}
/**
* Returns the expiry time of the contact's database. Messages that are
* older than the expiry time must not be sent to the contact.
* Returns the groups to which the sender subscribes, and which the sender
* has made visible to the recipient.
*/
long getExpiryTime();
public Collection<Group> getGroups() {
return subs;
}
/**
* Returns the update's timestamp. Updates that are older than the newest
* update received from the same contact must be ignored.
*/
long getTimestamp();
/** Returns the update's version number. */
public long getVersionNumber() {
return version;
}
}

View File

@@ -1,42 +0,0 @@
package net.sf.briar.api.protocol;
import java.util.Map;
import java.util.TreeMap;
public class Transport {
private final TransportId id;
private final TreeMap<String, String> properties;
public Transport(TransportId id, Map<String, String> p) {
this.id = id;
properties = new TreeMap<String, String>(p);
}
public Transport(TransportId id) {
this.id = id;
properties = new TreeMap<String, String>();
}
public TransportId getId() {
return id;
}
public Map<String, String> getProperties() {
return properties;
}
@Override
public int hashCode() {
return id.hashCode() ^ properties.hashCode();
}
@Override
public boolean equals(Object o) {
if(o instanceof Transport) {
Transport t = (Transport) o;
return id.equals(t.id) && properties.equals(t.properties);
}
return false;
}
}

View File

@@ -0,0 +1,23 @@
package net.sf.briar.api.protocol;
/** A packet acknowledging a {@link TransportUpdate}. */
public class TransportAck {
private final TransportId id;
private final long version;
public TransportAck(TransportId id, long version) {
this.id = id;
this.version = version;
}
/** Returns the identifier of the updated transport. */
public TransportId getId() {
return id;
}
/** Returns the version number of the acknowledged update. */
public long getVersionNumber() {
return version;
}
}

View File

@@ -1,16 +1,33 @@
package net.sf.briar.api.protocol;
import java.util.Collection;
import net.sf.briar.api.TransportProperties;
/** A packet updating the sender's transport properties. */
public interface TransportUpdate {
public class TransportUpdate {
/** Returns the transports contained in the update. */
Collection<Transport> getTransports();
private final TransportId id;
private final TransportProperties properties;
private final long version;
/**
* Returns the update's timestamp. Updates that are older than the newest
* update received from the same contact must be ignored.
*/
long getTimestamp();
public TransportUpdate(TransportId id, TransportProperties properties,
long version) {
this.id = id;
this.properties = properties;
this.version = version;
}
/** Returns the identifier of the updated transport. */
public TransportId getId() {
return id;
}
/** Returns the transport's updated properties. */
public TransportProperties getProperties() {
return properties;
}
/** Returns the update's version number. */
public long getVersionNumber() {
return version;
}
}

View File

@@ -9,7 +9,8 @@ public interface Types {
int MESSAGE = 4;
int OFFER = 5;
int REQUEST = 6;
int SUBSCRIPTION_UPDATE = 7;
int TRANSPORT = 8;
int TRANSPORT_UPDATE = 9;
int SUBSCRIPTION_ACK = 7;
int SUBSCRIPTION_UPDATE = 8;
int TRANSPORT_ACK = 9;
int TRANSPORT_UPDATE = 10;
}

View File

@@ -1,28 +1,61 @@
package net.sf.briar.api.protocol;
/** A {@link Message} that has not yet had its signatures verified. */
public interface UnverifiedMessage {
/**
* Returns the identifier of the message's parent, or null if this is the
* first message in a thread.
*/
MessageId getParent();
/**
* Returns the {@link Group} to which the message belongs, or null if this
* is a private message.
*/
Group getGroup();
/**
* Returns the message's {@link Author}, or null if this is an anonymous
* message.
*/
Author getAuthor();
/** Returns the message's subject line. */
String getSubject();
/** Returns the timestamp created by the message's {@link Author}. */
long getTimestamp();
/** Returns the serialised message. */
byte[] getSerialised();
/**
* Returns the author's signature, or null if this is an anonymous message.
*/
byte[] getAuthorSignature();
/**
* Returns the group's signature, or null if this is a private message or
* a message belonging to an unrestricted group.
*/
byte[] getGroupSignature();
/** Returns the offset of the message body within the serialised message. */
int getBodyStart();
/** Returns the length of the message body in bytes. */
int getBodyLength();
/**
* Returns the length in bytes of the data covered by the author's
* signature.
*/
int getLengthSignedByAuthor();
/**
* Returns the length in bytes of the data covered by the group's
* signature.
*/
int getLengthSignedByGroup();
}

View File

@@ -18,7 +18,7 @@ public interface Reader {
void addConsumer(Consumer c);
void removeConsumer(Consumer c);
void addStructReader(int id, StructReader<?> o);
void addStructReader(int id, StructReader<?> r);
void removeStructReader(int id);
boolean hasBoolean() throws IOException;

View File

@@ -15,8 +15,11 @@ import net.sf.briar.api.protocol.Group;
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.Transport;
import net.sf.briar.api.protocol.SubscriptionAck;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.TransportAck;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.transport.ContactTransport;
import net.sf.briar.api.transport.TemporarySecret;
@@ -73,7 +76,7 @@ interface Database<T> {
/**
* Adds a new contact to the database and returns an ID for the contact.
* <p>
* Locking: contact write, subscription write, transport write.
* Locking: contact write, subscription write.
*/
ContactId addContact(T txn) throws DbException;
@@ -85,8 +88,8 @@ interface Database<T> {
void addContactTransport(T txn, ContactTransport ct) throws DbException;
/**
* Returns false if the given message is already in the database. Otherwise
* stores the message and returns true.
* Stores the given message, or returns false if the message is already in
* the database.
* <p>
* Locking: message write.
*/
@@ -108,8 +111,8 @@ interface Database<T> {
throws DbException;
/**
* Returns false if the given message is already in the database. Otherwise
* stores the message and returns true.
* Stores the given message, or returns false if the message is already in
* the database.
* <p>
* Locking: contact read, message write.
*/
@@ -132,18 +135,16 @@ interface Database<T> {
void addSubscription(T txn, Group g) throws DbException;
/**
* Records the given contact's subscription to the given group starting at
* the given time.
* Adds a new transport to the database.
* <p>
* Locking: contact read, subscription write.
* Locking: transport write.
*/
void addSubscription(T txn, ContactId c, Group g, long start)
throws DbException;
void addTransport(T txn, TransportId t) throws DbException;
/**
* Makes the given group visible to the given contact.
* <p>
* Locking: contact read, subscription write.
* Locking: contact write, subscription write.
*/
void addVisibility(T txn, ContactId c, GroupId g) throws DbException;
@@ -177,23 +178,13 @@ interface Database<T> {
boolean containsSubscription(T txn, GroupId g) throws DbException;
/**
* Returns true if the user has been subscribed to the given group since
* the given time.
* <p>
* Locking: subscription read.
*/
boolean containsSubscription(T txn, GroupId g, long time)
throws DbException;
/**
* Returns true if the user is subscribed to the given group, the group is
* visible to the given contact, and the subscription has existed since the
* given time.
* Returns true if the user subscribes to the given group and the
* subscription is visible to the given contact.
* <p>
* Locking: contact read, subscription read.
*/
boolean containsVisibleSubscription(T txn, GroupId g, ContactId c,
long time) throws DbException;
boolean containsVisibleSubscription(T txn, ContactId c, GroupId g)
throws DbException;
/**
* Returns the configuration for the given transport.
@@ -249,13 +240,6 @@ interface Database<T> {
TransportProperties getLocalProperties(T txn, TransportId t)
throws DbException;
/**
* Returns all local transports.
* <p>
* Locking: transport read.
*/
Collection<Transport> getLocalTransports(T txn) throws DbException;
/**
* Returns the message identified by the given ID, in serialised form.
* <p>
@@ -402,20 +386,42 @@ interface Database<T> {
Collection<Group> getSubscriptions(T txn, ContactId c) throws DbException;
/**
* Returns the time at which the local transports were last modified.
* Returns a subscription ack for the given contact, or null if no ack is
* due.
* <p>
* Locking: transport read.
* Locking: contact read, subscription write.
*/
long getTransportsModified(T txn) throws DbException;
SubscriptionAck getSubscriptionAck(T txn, ContactId c) throws DbException;
/**
* Returns the time at which a transport update was last sent to the given
* contact.
* Returns a subscription update for the given contact, or null if no
* update is due.
* <p>
* Locking: contact read, transport read.
* Locking: contact read, subscription write.
*/
long getTransportsSent(T txn, ContactId c) throws DbException;
SubscriptionUpdate getSubscriptionUpdate(T txn, ContactId c)
throws DbException;
/**
* Returns a collection of transport acks for the given contact, or null if
* no acks are due.
* <p>
* Locking: contact read, transport write.
*/
Collection<TransportAck> getTransportAcks(T txn, ContactId c)
throws DbException;
/**
* Returns a collection of transport updates for the given contact, or
* null if no updates are due.
* <p>
* Locking: contact read, transport write.
*/
Collection<TransportUpdate> getTransportUpdates(T txn, ContactId c)
throws DbException;
/**
* Returns the version number of the
/**
* Returns the number of unread messages in each subscribed group.
* <p>
@@ -430,26 +436,6 @@ interface Database<T> {
*/
Collection<ContactId> getVisibility(T txn, GroupId g) throws DbException;
/**
* Returns any holes covering unsubscriptions that are visible to the given
* contact, occurred strictly before the given timestamp, and have not yet
* been acknowledged.
* <p>
* Locking: contact read, subscription read.
*/
Map<GroupId, GroupId> getVisibleHoles(T txn, ContactId c, long timestamp)
throws DbException;
/**
* Returns any subscriptions that are visible to the given contact,
* occurred strictly before the given timestamp, and have not yet been
* acknowledged.
* <p>
* Locking: contact read, subscription read.
*/
Map<Group, Long> getVisibleSubscriptions(T txn, ContactId c, long timestamp)
throws DbException;
/**
* Returns true if any messages are sendable to the given contact.
* <p>
@@ -523,25 +509,22 @@ interface Database<T> {
* Unsubscribes from the given group. Any messages belonging to the group
* are deleted from the database.
* <p>
* Locking: contact read, message write, messageFlag write,
* Locking: contact write, message write, messageFlag write,
* messageStatus write, subscription write.
*/
void removeSubscription(T txn, GroupId g) throws DbException;
/**
* Removes any subscriptions for the given contact with IDs between the
* given IDs. If both of the given IDs are null, all subscriptions are
* removed. If only the first is null, all subscriptions with IDs less than
* the second ID are removed. If onlt the second is null, all subscriptions
* with IDs greater than the first are removed.
* Removes a transport (and all associated state) from the database.
* <p>
* Locking: contact read, transport write.
*/
void removeSubscriptions(T txn, ContactId c, GroupId start, GroupId end)
throws DbException;
void removeTransport(T txn, TransportId t) throws DbException;
/**
* Makes the given group invisible to the given contact.
* <p>
* Locking: contact read, subscription write.
* Locking: contact write, subscription write.
*/
void removeVisibility(T txn, ContactId c, GroupId g) throws DbException;
@@ -557,7 +540,7 @@ interface Database<T> {
/**
* Sets the given contact's database expiry time.
* <p>
* Locking: contact read, subscription write.
* Locking: contact write.
*/
void setExpiryTime(T txn, ContactId c, long expiry) throws DbException;
@@ -576,6 +559,17 @@ interface Database<T> {
*/
boolean setRead(T txn, MessageId m, boolean read) throws DbException;
/**
* Updates the remote transport properties for the given contact and the
* given transport, replacing any existing properties, unless an update
* with an equal or higher version number has already been received from
* the contact.
* <p>
* Locking: contact read, transport write.
*/
void setRemoteProperties(T txn, ContactId c, TransportUpdate t)
throws DbException;
/**
* Sets the sendability score of the given message.
* <p>
@@ -612,45 +606,30 @@ interface Database<T> {
throws DbException;
/**
* Records the time of the latest subscription update acknowledged by the
* given contact.
* Updates the groups to which the given contact subscribes, unless an
* update with an equal or higher version number has already been received
* from the contact.
* <p>
* Locking: contact read, subscription write.
*/
void setSubscriptionsAcked(T txn, ContactId c, long timestamp)
void setSubscriptions(T txn, ContactId c, SubscriptionUpdate s)
throws DbException;
/**
* Records the time of the latest subscription update received from the
* given contact.
* Records a subscription ack from the given contact for the given version
* unless the contact has already acked an equal or higher version.
* <p>
* Locking: contact read, subscription write.
*/
void setSubscriptionsReceived(T txn, ContactId c, long timestamp)
void setSubscriptionUpdateAcked(T txn, ContactId c, long version)
throws DbException;
/**
* Sets the transports for the given contact, replacing any existing
* transports unless the existing transports have a newer timestamp.
* Records a transport ack from the give contact for the given version
* unless the contact has already acked an equal or higher version.
* <p>
* Locking: contact read, transport write.
*/
void setTransports(T txn, ContactId c, Collection<Transport> transports,
long timestamp) throws DbException;
/**
* Records the time at which the local transports were last modified.
* <p>
* Locking: contact read, transport write.
*/
void setTransportsModified(T txn, long timestamp) throws DbException;
/**
* Records the time at which a transport update was last sent to the given
* contact.
* <p>
* Locking: contact read, transport write.
*/
void setTransportsSent(T txn, ContactId c, long timestamp)
throws DbException;
void setTransportUpdateAcked(T txn, ContactId c, TransportId t,
long version) throws DbException;
}

View File

@@ -5,7 +5,6 @@ import static net.sf.briar.db.DatabaseConstants.BYTES_PER_SWEEP;
import static net.sf.briar.db.DatabaseConstants.CRITICAL_FREE_SPACE;
import static net.sf.briar.db.DatabaseConstants.MAX_BYTES_BETWEEN_SPACE_CHECKS;
import static net.sf.briar.db.DatabaseConstants.MAX_MS_BETWEEN_SPACE_CHECKS;
import static net.sf.briar.db.DatabaseConstants.MAX_UPDATE_INTERVAL;
import static net.sf.briar.db.DatabaseConstants.MIN_FREE_SPACE;
import java.io.IOException;
@@ -17,7 +16,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Logger;
@@ -36,12 +34,11 @@ import net.sf.briar.api.db.event.ContactAddedEvent;
import net.sf.briar.api.db.event.ContactRemovedEvent;
import net.sf.briar.api.db.event.DatabaseEvent;
import net.sf.briar.api.db.event.DatabaseListener;
import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
import net.sf.briar.api.db.event.MessageAddedEvent;
import net.sf.briar.api.db.event.MessageReceivedEvent;
import net.sf.briar.api.db.event.RatingChangedEvent;
import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
import net.sf.briar.api.db.event.SubscriptionsUpdatedEvent;
import net.sf.briar.api.db.event.TransportsUpdatedEvent;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.AuthorId;
@@ -50,10 +47,10 @@ 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.PacketFactory;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionAck;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportAck;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.transport.ContactTransport;
@@ -98,7 +95,6 @@ DatabaseCleaner.Callback {
private final Database<T> db;
private final DatabaseCleaner cleaner;
private final ShutdownManager shutdown;
private final PacketFactory packetFactory;
private final Clock clock;
private final Collection<DatabaseListener> listeners =
@@ -114,12 +110,10 @@ DatabaseCleaner.Callback {
@Inject
DatabaseComponentImpl(Database<T> db, DatabaseCleaner cleaner,
ShutdownManager shutdown, PacketFactory packetFactory,
Clock clock) {
ShutdownManager shutdown, Clock clock) {
this.db = db;
this.cleaner = cleaner;
this.shutdown = shutdown;
this.packetFactory = packetFactory;
this.clock = clock;
}
@@ -173,23 +167,13 @@ DatabaseCleaner.Callback {
try {
subscriptionLock.writeLock().lock();
try {
transportLock.writeLock().lock();
T txn = db.startTransaction();
try {
windowLock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
c = db.addContact(txn);
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
windowLock.writeLock().unlock();
}
} finally {
transportLock.writeLock().unlock();
c = db.addContact(txn);
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
subscriptionLock.writeLock().unlock();
@@ -243,12 +227,9 @@ DatabaseCleaner.Callback {
T txn = db.startTransaction();
try {
// Don't store the message if the user has
// unsubscribed from the group or the message
// predates the subscription
if(db.containsSubscription(txn, m.getGroup(),
m.getTimestamp())) {
// unsubscribed from the group
if(db.containsSubscription(txn, m.getGroup()))
added = storeGroupMessage(txn, m, null);
}
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
@@ -418,11 +399,27 @@ DatabaseCleaner.Callback {
}
}
public void addTransport(TransportId t) throws DbException {
transportLock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
db.addTransport(txn, t);
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
transportLock.writeLock().unlock();
}
}
/**
* If the given message is already in the database, returns false.
* Otherwise stores the message and marks it as new or seen with respect to
* the given contact, depending on whether the message is outgoing or
* incoming, respectively.
* incoming, respectively; or returns false if the message is already in
* the database.
* <p>
* Locking: contact read, message write, messageStatus write.
*/
@@ -478,7 +475,7 @@ DatabaseCleaner.Callback {
} finally {
contactLock.readLock().unlock();
}
return packetFactory.createAck(acked);
return new Ack(acked);
}
public Collection<byte[]> generateBatch(ContactId c, int maxLength)
@@ -627,80 +624,94 @@ DatabaseCleaner.Callback {
} finally {
contactLock.readLock().unlock();
}
return packetFactory.createOffer(offered);
return new Offer(offered);
}
public SubscriptionUpdate generateSubscriptionUpdate(ContactId c)
public SubscriptionAck generateSubscriptionAck(ContactId c)
throws DbException {
Map<GroupId, GroupId> holes;
Map<Group, Long> subs;
long expiry, timestamp;
contactLock.readLock().lock();
try {
subscriptionLock.readLock().lock();
subscriptionLock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
if(!db.containsContact(txn, c))
throw new NoSuchContactException();
timestamp = clock.currentTimeMillis() - 1;
holes = db.getVisibleHoles(txn, c, timestamp);
subs = db.getVisibleSubscriptions(txn, c, timestamp);
expiry = db.getExpiryTime(txn);
SubscriptionAck a = db.getSubscriptionAck(txn, c);
db.commitTransaction(txn);
return a;
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
subscriptionLock.readLock().unlock();
subscriptionLock.writeLock().unlock();
}
} finally {
contactLock.readLock().unlock();
}
return packetFactory.createSubscriptionUpdate(holes, subs, expiry,
timestamp);
}
private boolean updateIsDue(long sent) {
long now = clock.currentTimeMillis();
return now - sent >= MAX_UPDATE_INTERVAL;
}
public TransportUpdate generateTransportUpdate(ContactId c)
public SubscriptionUpdate generateSubscriptionUpdate(ContactId c)
throws DbException {
boolean due;
Collection<Transport> transports;
long timestamp;
contactLock.readLock().lock();
try {
transportLock.readLock().lock();
subscriptionLock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
if(!db.containsContact(txn, c))
throw new NoSuchContactException();
// Work out whether an update is due
long modified = db.getTransportsModified(txn);
long sent = db.getTransportsSent(txn, c);
due = modified >= sent || updateIsDue(sent);
SubscriptionUpdate s = db.getSubscriptionUpdate(txn, c);
db.commitTransaction(txn);
return s;
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
transportLock.readLock().unlock();
subscriptionLock.writeLock().unlock();
}
if(!due) return null;
} finally {
contactLock.readLock().unlock();
}
}
public Collection<TransportAck> generateTransportAcks(ContactId c)
throws DbException {
contactLock.readLock().lock();
try {
transportLock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
transports = db.getLocalTransports(txn);
timestamp = clock.currentTimeMillis();
db.setTransportsSent(txn, c, timestamp);
Collection<TransportAck> acks = db.getTransportAcks(txn, c);
db.commitTransaction(txn);
return acks;
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
transportLock.writeLock().unlock();
}
} finally {
contactLock.readLock().unlock();
}
}
public Collection<TransportUpdate> generateTransportUpdates(ContactId c)
throws DbException {
contactLock.readLock().lock();
try {
transportLock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
Collection<TransportUpdate> updates =
db.getTransportUpdates(txn, c);
db.commitTransaction(txn);
return updates;
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
@@ -711,7 +722,6 @@ DatabaseCleaner.Callback {
} finally {
contactLock.readLock().unlock();
}
return packetFactory.createTransportUpdate(transports, timestamp);
}
public TransportConfig getConfig(TransportId t) throws DbException {
@@ -766,23 +776,6 @@ DatabaseCleaner.Callback {
}
}
public Collection<Transport> getLocalTransports() throws DbException {
transportLock.readLock().lock();
try {
T txn = db.startTransaction();
try {
Collection<Transport> transports = db.getLocalTransports(txn);
db.commitTransaction(txn);
return transports;
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
transportLock.readLock().unlock();
}
}
public Collection<MessageHeader> getMessageHeaders(GroupId g)
throws DbException {
messageLock.readLock().lock();
@@ -1022,7 +1015,6 @@ DatabaseCleaner.Callback {
try {
if(!p.equals(db.getLocalProperties(txn, t))) {
db.mergeLocalProperties(txn, t, p);
db.setTransportsModified(txn, clock.currentTimeMillis());
changed = true;
}
db.commitTransaction(txn);
@@ -1034,7 +1026,7 @@ DatabaseCleaner.Callback {
transportLock.writeLock().unlock();
}
// Call the listeners outside the lock
if(changed) callListeners(new LocalTransportsUpdatedEvent());
if(changed) callListeners(new TransportsUpdatedEvent());
}
public void receiveAck(ContactId c, Ack a) throws DbException {
@@ -1114,8 +1106,7 @@ DatabaseCleaner.Callback {
throws DbException {
GroupId g = m.getGroup();
if(g == null) return storePrivateMessage(txn, m, c, true);
if(!db.containsVisibleSubscription(txn, g, c, m.getTimestamp()))
return false;
if(!db.containsVisibleSubscription(txn, c, g)) return false;
return storeGroupMessage(txn, m, c);
}
@@ -1161,12 +1152,11 @@ DatabaseCleaner.Callback {
} finally {
contactLock.readLock().unlock();
}
return packetFactory.createRequest(request, offered.size());
return new Request(request, offered.size());
}
public void receiveSubscriptionUpdate(ContactId c, SubscriptionUpdate s)
public void receiveSubscriptionAck(ContactId c, SubscriptionAck a)
throws DbException {
// Update the contact's subscriptions
contactLock.readLock().lock();
try {
subscriptionLock.writeLock().lock();
@@ -1175,17 +1165,8 @@ DatabaseCleaner.Callback {
try {
if(!db.containsContact(txn, c))
throw new NoSuchContactException();
Map<GroupId, GroupId> holes = s.getHoles();
for(Entry<GroupId, GroupId> e : holes.entrySet()) {
GroupId start = e.getKey(), end = e.getValue();
db.removeSubscriptions(txn, c, start, end);
}
Map<Group, Long> subs = s.getSubscriptions();
for(Entry<Group, Long> e : subs.entrySet()) {
db.addSubscription(txn, c, e.getKey(), e.getValue());
}
db.setExpiryTime(txn, c, s.getExpiryTime());
db.setSubscriptionsReceived(txn, c, s.getTimestamp());
long version = a.getVersionNumber();
db.setSubscriptionUpdateAcked(txn, c, version);
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
@@ -1197,15 +1178,34 @@ DatabaseCleaner.Callback {
} finally {
contactLock.readLock().unlock();
}
// Call the listeners outside the lock
callListeners(new SubscriptionsUpdatedEvent(
Collections.singletonList(c)));
}
public void receiveTransportUpdate(ContactId c, TransportUpdate t)
public void receiveSubscriptionUpdate(ContactId c, SubscriptionUpdate s)
throws DbException {
contactLock.readLock().lock();
try {
subscriptionLock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
if(!db.containsContact(txn, c))
throw new NoSuchContactException();
db.setSubscriptions(txn, c, s);
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
subscriptionLock.writeLock().unlock();
}
} finally {
contactLock.readLock().unlock();
}
}
public void receiveTransportAck(ContactId c, TransportAck a)
throws DbException {
Collection<Transport> transports;
// Update the contact's transport properties
contactLock.readLock().lock();
try {
transportLock.writeLock().lock();
@@ -1214,8 +1214,33 @@ DatabaseCleaner.Callback {
try {
if(!db.containsContact(txn, c))
throw new NoSuchContactException();
transports = t.getTransports();
db.setTransports(txn, c, transports, t.getTimestamp());
TransportId t = a.getId();
long version = a.getVersionNumber();
db.setTransportUpdateAcked(txn, c, t, version);
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
transportLock.writeLock().unlock();
}
} finally {
contactLock.readLock().unlock();
}
}
public void receiveTransportUpdate(ContactId c, TransportUpdate t)
throws DbException {
contactLock.readLock().lock();
try {
transportLock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
if(!db.containsContact(txn, c))
throw new NoSuchContactException();
db.setRemoteProperties(txn, c, t);
db.commitTransaction(txn);
} catch(DbException e) {
db.abortTransaction(txn);
@@ -1227,8 +1252,6 @@ DatabaseCleaner.Callback {
} finally {
contactLock.readLock().unlock();
}
// Call the listeners outside the lock
callListeners(new RemoteTransportsUpdatedEvent(c, transports));
}
public void removeContact(ContactId c) throws DbException {
@@ -1398,8 +1421,7 @@ DatabaseCleaner.Callback {
public void setVisibility(GroupId g, Collection<ContactId> visible)
throws DbException {
List<ContactId> affected = new ArrayList<ContactId>();
contactLock.readLock().lock();
contactLock.writeLock().lock();
try {
subscriptionLock.writeLock().lock();
try {
@@ -1413,13 +1435,8 @@ DatabaseCleaner.Callback {
for(ContactId c : db.getContacts(txn)) {
boolean then = oldVisible.contains(c);
boolean now = visible.contains(c);
if(!then && now) {
db.addVisibility(txn, c, g);
affected.add(c);
} else if(then && !now) {
db.removeVisibility(txn, c, g);
affected.add(c);
}
if(!then && now) db.addVisibility(txn, c, g);
else if(then && !now) db.removeVisibility(txn, c, g);
}
db.commitTransaction(txn);
} catch(DbException e) {
@@ -1430,12 +1447,7 @@ DatabaseCleaner.Callback {
subscriptionLock.writeLock().unlock();
}
} finally {
contactLock.readLock().unlock();
}
// Call the listeners outside the lock
if(!affected.isEmpty()) {
affected = Collections.unmodifiableList(affected);
callListeners(new SubscriptionsUpdatedEvent(affected));
contactLock.writeLock().unlock();
}
}
@@ -1459,7 +1471,7 @@ DatabaseCleaner.Callback {
public void unsubscribe(GroupId g) throws DbException {
Collection<ContactId> affected = null;
contactLock.readLock().lock();
contactLock.writeLock().lock();
try {
messageLock.writeLock().lock();
try {
@@ -1493,7 +1505,7 @@ DatabaseCleaner.Callback {
messageLock.writeLock().unlock();
}
} finally {
contactLock.readLock().unlock();
contactLock.writeLock().unlock();
}
// Call the listeners outside the lock
if(affected != null && !affected.isEmpty())

View File

@@ -8,7 +8,6 @@ import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DatabaseConfig;
import net.sf.briar.api.db.DatabaseExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.util.BoundedExecutor;
import com.google.inject.AbstractModule;
@@ -41,15 +40,14 @@ public class DatabaseModule extends AbstractModule {
}
@Provides
Database<Connection> getDatabase(Clock clock, DatabaseConfig config) {
return new H2Database(clock, config);
Database<Connection> getDatabase(DatabaseConfig config) {
return new H2Database(config);
}
@Provides @Singleton
DatabaseComponent getDatabaseComponent(Database<Connection> db,
DatabaseCleaner cleaner, ShutdownManager shutdown,
PacketFactory packetFactory, Clock clock) {
DatabaseCleaner cleaner, ShutdownManager shutdown, Clock clock) {
return new DatabaseComponentImpl<Connection>(db, cleaner, shutdown,
packetFactory, clock);
clock);
}
}

View File

@@ -30,8 +30,8 @@ class H2Database extends JdbcDatabase {
private final long maxSize;
@Inject
H2Database(Clock clock, DatabaseConfig config) {
super(clock, HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE);
H2Database(DatabaseConfig config) {
super(HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE);
home = new File(config.getDataDirectory(), "db");
url = "jdbc:h2:split:" + home.getPath()
+ ";CIPHER=AES;DB_CLOSE_ON_EXIT=false";

File diff suppressed because it is too large Load Diff

View File

@@ -104,7 +104,7 @@ abstract class Connector extends Thread {
protected byte[] receivePublicKeyHash(Reader r) throws IOException {
byte[] b = r.readBytes(HASH_LENGTH);
if(b.length != HASH_LENGTH) throw new FormatException();
if(b.length < HASH_LENGTH) throw new FormatException();
if(LOG.isLoggable(INFO)) LOG.info(pluginName + " received hash");
return b;
}

View File

@@ -1,19 +0,0 @@
package net.sf.briar.protocol;
import java.util.Collection;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.MessageId;
class AckImpl implements Ack {
private final Collection<MessageId> acked;
AckImpl(Collection<MessageId> acked) {
this.acked = acked;
}
public Collection<MessageId> getMessageIds() {
return acked;
}
}

View File

@@ -12,7 +12,6 @@ import net.sf.briar.api.Bytes;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.UniqueId;
import net.sf.briar.api.serial.Consumer;
import net.sf.briar.api.serial.CountingConsumer;
@@ -21,18 +20,11 @@ import net.sf.briar.api.serial.StructReader;
class AckReader implements StructReader<Ack> {
private final PacketFactory packetFactory;
AckReader(PacketFactory packetFactory) {
this.packetFactory = packetFactory;
}
public Ack readStruct(Reader r) throws IOException {
// Initialise the consumer
Consumer counting = new CountingConsumer(MAX_PACKET_LENGTH);
// Read the data
r.addConsumer(counting);
r.readStructId(ACK);
// Read the message IDs as byte arrays
r.setMaxBytesLength(UniqueId.LENGTH);
List<Bytes> raw = r.readList(Bytes.class);
r.resetMaxBytesLength();
@@ -46,6 +38,6 @@ class AckReader implements StructReader<Ack> {
acked.add(new MessageId(b.getBytes()));
}
// Build and return the ack
return packetFactory.createAck(Collections.unmodifiableList(acked));
return new Ack(Collections.unmodifiableList(acked));
}
}

View File

@@ -27,7 +27,7 @@ class AuthorFactoryImpl implements AuthorFactory {
}
public Author createAuthor(String name, byte[] publicKey)
throws IOException {
throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out);
w.writeStructId(AUTHOR);
@@ -36,10 +36,6 @@ class AuthorFactoryImpl implements AuthorFactory {
MessageDigest messageDigest = crypto.getMessageDigest();
messageDigest.update(out.toByteArray());
AuthorId id = new AuthorId(messageDigest.digest());
return new AuthorImpl(id, name, publicKey);
}
public Author createAuthor(AuthorId id, String name, byte[] publicKey) {
return new AuthorImpl(id, name, publicKey);
return new Author(id, name, publicKey);
}
}

View File

@@ -1,29 +0,0 @@
package net.sf.briar.protocol;
import net.sf.briar.api.protocol.Author;
import net.sf.briar.api.protocol.AuthorId;
class AuthorImpl implements Author {
private final AuthorId id;
private final String name;
private final byte[] publicKey;
AuthorImpl(AuthorId id, String name, byte[] publicKey) {
this.id = id;
this.name = name;
this.publicKey = publicKey;
}
public AuthorId getId() {
return id;
}
public String getName() {
return name;
}
public byte[] getPublicKey() {
return publicKey;
}
}

View File

@@ -9,7 +9,6 @@ import java.io.IOException;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.MessageDigest;
import net.sf.briar.api.protocol.Author;
import net.sf.briar.api.protocol.AuthorFactory;
import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.serial.DigestingConsumer;
import net.sf.briar.api.serial.Reader;
@@ -18,15 +17,12 @@ import net.sf.briar.api.serial.StructReader;
class AuthorReader implements StructReader<Author> {
private final MessageDigest messageDigest;
private final AuthorFactory authorFactory;
AuthorReader(CryptoComponent crypto, AuthorFactory authorFactory) {
AuthorReader(CryptoComponent crypto) {
messageDigest = crypto.getMessageDigest();
this.authorFactory = authorFactory;
}
public Author readStruct(Reader r) throws IOException {
// Initialise the consumer
DigestingConsumer digesting = new DigestingConsumer(messageDigest);
// Read and digest the data
r.addConsumer(digesting);
@@ -36,6 +32,6 @@ class AuthorReader implements StructReader<Author> {
r.removeConsumer(digesting);
// Build and return the author
AuthorId id = new AuthorId(messageDigest.digest());
return authorFactory.createAuthor(id, name, publicKey);
return new Author(id, name, publicKey);
}
}

View File

@@ -23,7 +23,6 @@ class GroupReader implements StructReader<Group> {
}
public Group readStruct(Reader r) throws IOException {
// Initialise the consumer
DigestingConsumer digesting = new DigestingConsumer(messageDigest);
// Read and digest the data
r.addConsumer(digesting);

View File

@@ -46,7 +46,7 @@ class MessageReader implements StructReader<UnverifiedMessage> {
r.readNull();
} else {
byte[] b = r.readBytes(UniqueId.LENGTH);
if(b.length != UniqueId.LENGTH) throw new FormatException();
if(b.length < UniqueId.LENGTH) throw new FormatException();
parent = new MessageId(b);
}
// Read the group, if there is one
@@ -74,7 +74,7 @@ class MessageReader implements StructReader<UnverifiedMessage> {
if(timestamp < 0L) throw new FormatException();
// Read the salt
byte[] salt = r.readBytes(SALT_LENGTH);
if(salt.length != SALT_LENGTH) throw new FormatException();
if(salt.length < SALT_LENGTH) throw new FormatException();
// Read the message body
byte[] body = r.readBytes(MAX_BODY_LENGTH);
// Record the offset of the body within the message

View File

@@ -1,19 +0,0 @@
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<MessageId> offered;
OfferImpl(Collection<MessageId> offered) {
this.offered = offered;
}
public Collection<MessageId> getMessageIds() {
return offered;
}
}

View File

@@ -12,7 +12,6 @@ import net.sf.briar.api.Bytes;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.UniqueId;
import net.sf.briar.api.serial.Consumer;
import net.sf.briar.api.serial.CountingConsumer;
@@ -21,18 +20,11 @@ import net.sf.briar.api.serial.StructReader;
class OfferReader implements StructReader<Offer> {
private final PacketFactory packetFactory;
OfferReader(PacketFactory packetFactory) {
this.packetFactory = packetFactory;
}
public Offer readStruct(Reader r) throws IOException {
// Initialise the consumer
Consumer counting = new CountingConsumer(MAX_PACKET_LENGTH);
// Read the data
r.addConsumer(counting);
r.readStructId(OFFER);
// Read the message IDs as byte arrays
r.setMaxBytesLength(UniqueId.LENGTH);
List<Bytes> raw = r.readList(Bytes.class);
r.resetMaxBytesLength();
@@ -46,7 +38,6 @@ class OfferReader implements StructReader<Offer> {
messages.add(new MessageId(b.getBytes()));
}
// Build and return the offer
return packetFactory.createOffer(Collections.unmodifiableList(
messages));
return new Offer(Collections.unmodifiableList(messages));
}
}

View File

@@ -1,42 +0,0 @@
package net.sf.briar.protocol;
import java.util.BitSet;
import java.util.Collection;
import java.util.Map;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportUpdate;
class PacketFactoryImpl implements PacketFactory {
public Ack createAck(Collection<MessageId> acked) {
return new AckImpl(acked);
}
public Offer createOffer(Collection<MessageId> offered) {
return new OfferImpl(offered);
}
public Request createRequest(BitSet requested, int length) {
return new RequestImpl(requested, length);
}
public SubscriptionUpdate createSubscriptionUpdate(
Map<GroupId, GroupId> holes, Map<Group, Long> subs, long expiry,
long timestamp) {
return new SubscriptionUpdateImpl(holes, subs, expiry, timestamp);
}
public TransportUpdate createTransportUpdate(
Collection<Transport> transports, long timestamp) {
return new TransportUpdateImpl(transports, timestamp);
}
}

View File

@@ -11,11 +11,12 @@ import net.sf.briar.api.protocol.GroupFactory;
import net.sf.briar.api.protocol.MessageFactory;
import net.sf.briar.api.protocol.MessageVerifier;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.ProtocolReaderFactory;
import net.sf.briar.api.protocol.ProtocolWriterFactory;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionAck;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.TransportAck;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.protocol.UnverifiedMessage;
import net.sf.briar.api.protocol.VerificationExecutor;
@@ -48,7 +49,6 @@ public class ProtocolModule extends AbstractModule {
bind(GroupFactory.class).to(GroupFactoryImpl.class);
bind(MessageFactory.class).to(MessageFactoryImpl.class);
bind(MessageVerifier.class).to(MessageVerifierImpl.class);
bind(PacketFactory.class).to(PacketFactoryImpl.class);
bind(ProtocolReaderFactory.class).to(ProtocolReaderFactoryImpl.class);
bind(ProtocolWriterFactory.class).to(ProtocolWriterFactoryImpl.class);
// The executor is bounded, so tasks must be independent and short-lived
@@ -59,14 +59,13 @@ public class ProtocolModule extends AbstractModule {
}
@Provides
StructReader<Ack> getAckReader(PacketFactory ackFactory) {
return new AckReader(ackFactory);
StructReader<Ack> getAckReader() {
return new AckReader();
}
@Provides
StructReader<Author> getAuthorReader(CryptoComponent crypto,
AuthorFactory authorFactory) {
return new AuthorReader(crypto, authorFactory);
StructReader<Author> getAuthorReader(CryptoComponent crypto) {
return new AuthorReader(crypto);
}
@Provides
@@ -82,24 +81,33 @@ public class ProtocolModule extends AbstractModule {
}
@Provides
StructReader<Offer> getOfferReader(PacketFactory packetFactory) {
return new OfferReader(packetFactory);
StructReader<Offer> getOfferReader() {
return new OfferReader();
}
@Provides
StructReader<Request> getRequestReader(PacketFactory packetFactory) {
return new RequestReader(packetFactory);
StructReader<Request> getRequestReader() {
return new RequestReader();
}
@Provides
StructReader<SubscriptionUpdate> getSubscriptionReader(
StructReader<Group> groupReader, PacketFactory packetFactory) {
return new SubscriptionUpdateReader(groupReader, packetFactory);
StructReader<SubscriptionAck> getSubscriptionAckReader() {
return new SubscriptionAckReader();
}
@Provides
StructReader<TransportUpdate> getTransportReader(
PacketFactory packetFactory) {
return new TransportUpdateReader(packetFactory);
StructReader<SubscriptionUpdate> getSubscriptionUpdateReader(
StructReader<Group> groupReader) {
return new SubscriptionUpdateReader(groupReader);
}
@Provides
StructReader<TransportAck> getTransportAckReader() {
return new TransportAckReader();
}
@Provides
StructReader<TransportUpdate> getTransportUpdateReader() {
return new TransportUpdateReader();
}
}

View File

@@ -7,7 +7,9 @@ import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.ProtocolReader;
import net.sf.briar.api.protocol.ProtocolReaderFactory;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionAck;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.TransportAck;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.protocol.UnverifiedMessage;
import net.sf.briar.api.serial.ReaderFactory;
@@ -16,6 +18,7 @@ import net.sf.briar.api.serial.StructReader;
import com.google.inject.Inject;
import com.google.inject.Provider;
// FIXME: Refactor this package to reduce boilerplate
class ProtocolReaderFactoryImpl implements ProtocolReaderFactory {
private final ReaderFactory readerFactory;
@@ -23,8 +26,10 @@ class ProtocolReaderFactoryImpl implements ProtocolReaderFactory {
private final Provider<StructReader<UnverifiedMessage>> messageProvider;
private final Provider<StructReader<Offer>> offerProvider;
private final Provider<StructReader<Request>> requestProvider;
private final Provider<StructReader<SubscriptionUpdate>> subscriptionProvider;
private final Provider<StructReader<TransportUpdate>> transportProvider;
private final Provider<StructReader<SubscriptionAck>> subscriptionAckProvider;
private final Provider<StructReader<SubscriptionUpdate>> subscriptionUpdateProvider;
private final Provider<StructReader<TransportAck>> transportAckProvider;
private final Provider<StructReader<TransportUpdate>> transportUpdateProvider;
@Inject
ProtocolReaderFactoryImpl(ReaderFactory readerFactory,
@@ -32,21 +37,26 @@ class ProtocolReaderFactoryImpl implements ProtocolReaderFactory {
Provider<StructReader<UnverifiedMessage>> messageProvider,
Provider<StructReader<Offer>> offerProvider,
Provider<StructReader<Request>> requestProvider,
Provider<StructReader<SubscriptionUpdate>> subscriptionProvider,
Provider<StructReader<TransportUpdate>> transportProvider) {
Provider<StructReader<SubscriptionAck>> subscriptionAckProvider,
Provider<StructReader<SubscriptionUpdate>> subscriptionUpdateProvider,
Provider<StructReader<TransportAck>> transportAckProvider,
Provider<StructReader<TransportUpdate>> transportUpdateProvider) {
this.readerFactory = readerFactory;
this.ackProvider = ackProvider;
this.messageProvider = messageProvider;
this.offerProvider = offerProvider;
this.requestProvider = requestProvider;
this.subscriptionProvider = subscriptionProvider;
this.transportProvider = transportProvider;
this.subscriptionAckProvider = subscriptionAckProvider;
this.subscriptionUpdateProvider = subscriptionUpdateProvider;
this.transportAckProvider = transportAckProvider;
this.transportUpdateProvider = transportUpdateProvider;
}
public ProtocolReader createProtocolReader(InputStream in) {
return new ProtocolReaderImpl(in, readerFactory, ackProvider.get(),
messageProvider.get(), offerProvider.get(),
requestProvider.get(), subscriptionProvider.get(),
transportProvider.get());
requestProvider.get(), subscriptionAckProvider.get(),
subscriptionUpdateProvider.get(), transportAckProvider.get(),
transportUpdateProvider.get());
}
}

View File

@@ -4,7 +4,9 @@ import static net.sf.briar.api.protocol.Types.ACK;
import static net.sf.briar.api.protocol.Types.MESSAGE;
import static net.sf.briar.api.protocol.Types.OFFER;
import static net.sf.briar.api.protocol.Types.REQUEST;
import static net.sf.briar.api.protocol.Types.SUBSCRIPTION_ACK;
import static net.sf.briar.api.protocol.Types.SUBSCRIPTION_UPDATE;
import static net.sf.briar.api.protocol.Types.TRANSPORT_ACK;
import static net.sf.briar.api.protocol.Types.TRANSPORT_UPDATE;
import java.io.IOException;
@@ -14,7 +16,9 @@ import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.ProtocolReader;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionAck;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.TransportAck;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.protocol.UnverifiedMessage;
import net.sf.briar.api.serial.Reader;
@@ -30,15 +34,19 @@ class ProtocolReaderImpl implements ProtocolReader {
StructReader<UnverifiedMessage> messageReader,
StructReader<Offer> offerReader,
StructReader<Request> requestReader,
StructReader<SubscriptionUpdate> subscriptionReader,
StructReader<TransportUpdate> transportReader) {
StructReader<SubscriptionAck> subscriptionAckReader,
StructReader<SubscriptionUpdate> subscriptionUpdateReader,
StructReader<TransportAck> transportAckReader,
StructReader<TransportUpdate> transportUpdateReader) {
reader = readerFactory.createReader(in);
reader.addStructReader(ACK, ackReader);
reader.addStructReader(MESSAGE, messageReader);
reader.addStructReader(OFFER, offerReader);
reader.addStructReader(REQUEST, requestReader);
reader.addStructReader(SUBSCRIPTION_UPDATE, subscriptionReader);
reader.addStructReader(TRANSPORT_UPDATE, transportReader);
reader.addStructReader(SUBSCRIPTION_ACK, subscriptionAckReader);
reader.addStructReader(SUBSCRIPTION_UPDATE, subscriptionUpdateReader);
reader.addStructReader(TRANSPORT_ACK, transportAckReader);
reader.addStructReader(TRANSPORT_UPDATE, transportUpdateReader);
}
public boolean eof() throws IOException {
@@ -77,6 +85,14 @@ class ProtocolReaderImpl implements ProtocolReader {
return reader.readStruct(REQUEST, Request.class);
}
public boolean hasSubscriptionAck() throws IOException {
return reader.hasStruct(SUBSCRIPTION_ACK);
}
public SubscriptionAck readSubscriptionAck() throws IOException {
return reader.readStruct(SUBSCRIPTION_ACK, SubscriptionAck.class);
}
public boolean hasSubscriptionUpdate() throws IOException {
return reader.hasStruct(SUBSCRIPTION_UPDATE);
}
@@ -86,6 +102,14 @@ class ProtocolReaderImpl implements ProtocolReader {
SubscriptionUpdate.class);
}
public boolean hasTransportAck() throws IOException {
return reader.hasStruct(TRANSPORT_ACK);
}
public TransportAck readTransportAck() throws IOException {
return reader.readStruct(TRANSPORT_ACK, TransportAck.class);
}
public boolean hasTransportUpdate() throws IOException {
return reader.hasStruct(TRANSPORT_UPDATE);
}

View File

@@ -5,24 +5,24 @@ import static net.sf.briar.api.protocol.Types.ACK;
import static net.sf.briar.api.protocol.Types.GROUP;
import static net.sf.briar.api.protocol.Types.OFFER;
import static net.sf.briar.api.protocol.Types.REQUEST;
import static net.sf.briar.api.protocol.Types.SUBSCRIPTION_ACK;
import static net.sf.briar.api.protocol.Types.SUBSCRIPTION_UPDATE;
import static net.sf.briar.api.protocol.Types.TRANSPORT;
import static net.sf.briar.api.protocol.Types.TRANSPORT_ACK;
import static net.sf.briar.api.protocol.Types.TRANSPORT_UPDATE;
import java.io.IOException;
import java.io.OutputStream;
import java.util.BitSet;
import java.util.Map.Entry;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.ProtocolWriter;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionAck;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportAck;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.serial.SerialComponent;
import net.sf.briar.api.serial.Writer;
@@ -103,48 +103,40 @@ class ProtocolWriterImpl implements ProtocolWriter {
if(flush) out.flush();
}
public void writeSubscriptionUpdate(SubscriptionUpdate s)
throws IOException {
w.writeStructId(SUBSCRIPTION_UPDATE);
// Holes
w.writeMapStart();
for(Entry<GroupId, GroupId> e : s.getHoles().entrySet()) {
w.writeBytes(e.getKey().getBytes());
w.writeBytes(e.getValue().getBytes());
}
w.writeMapEnd();
// Subscriptions
w.writeMapStart();
for(Entry<Group, Long> e : s.getSubscriptions().entrySet()) {
writeGroup(w, e.getKey());
w.writeInt64(e.getValue());
}
w.writeMapEnd();
// Expiry time
w.writeInt64(s.getExpiryTime());
// Timestamp
w.writeInt64(s.getTimestamp());
public void writeSubscriptionAck(SubscriptionAck a) throws IOException {
w.writeStructId(SUBSCRIPTION_ACK);
w.writeInt64(a.getVersionNumber());
if(flush) out.flush();
}
private void writeGroup(Writer w, Group g) throws IOException {
w.writeStructId(GROUP);
w.writeString(g.getName());
byte[] publicKey = g.getPublicKey();
if(publicKey == null) w.writeNull();
else w.writeBytes(publicKey);
public void writeSubscriptionUpdate(SubscriptionUpdate s)
throws IOException {
w.writeStructId(SUBSCRIPTION_UPDATE);
w.writeListStart();
for(Group g : s.getGroups()) {
w.writeStructId(GROUP);
w.writeString(g.getName());
byte[] publicKey = g.getPublicKey();
if(publicKey == null) w.writeNull();
else w.writeBytes(publicKey);
}
w.writeListEnd();
w.writeInt64(s.getVersionNumber());
if(flush) out.flush();
}
public void writeTransportAck(TransportAck a) throws IOException {
w.writeStructId(TRANSPORT_ACK);
w.writeBytes(a.getId().getBytes());
w.writeInt64(a.getVersionNumber());
if(flush) out.flush();
}
public void writeTransportUpdate(TransportUpdate t) throws IOException {
w.writeStructId(TRANSPORT_UPDATE);
w.writeListStart();
for(Transport p : t.getTransports()) {
w.writeStructId(TRANSPORT);
w.writeBytes(p.getId().getBytes());
w.writeMap(p.getProperties());
}
w.writeListEnd();
w.writeInt64(t.getTimestamp());
w.writeBytes(t.getId().getBytes());
w.writeMap(t.getProperties());
w.writeInt64(t.getVersionNumber());
if(flush) out.flush();
}

View File

@@ -1,24 +0,0 @@
package net.sf.briar.protocol;
import java.util.BitSet;
import net.sf.briar.api.protocol.Request;
class RequestImpl implements Request {
private final BitSet requested;
private final int length;
RequestImpl(BitSet requested, int length) {
this.requested = requested;
this.length = length;
}
public BitSet getBitmap() {
return requested;
}
public int getLength() {
return length;
}
}

View File

@@ -7,7 +7,6 @@ import java.io.IOException;
import java.util.BitSet;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.serial.Consumer;
import net.sf.briar.api.serial.CountingConsumer;
@@ -16,20 +15,14 @@ import net.sf.briar.api.serial.StructReader;
class RequestReader implements StructReader<Request> {
private final PacketFactory packetFactory;
RequestReader(PacketFactory packetFactory) {
this.packetFactory = packetFactory;
}
public Request readStruct(Reader r) throws IOException {
// Initialise the consumer
Consumer counting = new CountingConsumer(MAX_PACKET_LENGTH);
// Read the data
r.addConsumer(counting);
r.readStructId(REQUEST);
// There may be up to 7 bits of padding at the end of the bitmap
int padding = r.readUint7();
if(padding > 7) throw new FormatException();
// Read the bitmap
byte[] bitmap = r.readBytes(MAX_PACKET_LENGTH);
r.removeConsumer(counting);
// Convert the bitmap into a BitSet
@@ -41,6 +34,6 @@ class RequestReader implements StructReader<Request> {
if((bitmap[i] & bit) != 0) b.set(i * 8 + j);
}
}
return packetFactory.createRequest(b, length);
return new Request(b, length);
}
}

View File

@@ -0,0 +1,20 @@
package net.sf.briar.protocol;
import static net.sf.briar.api.protocol.Types.SUBSCRIPTION_ACK;
import java.io.IOException;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.SubscriptionAck;
import net.sf.briar.api.serial.Reader;
import net.sf.briar.api.serial.StructReader;
class SubscriptionAckReader implements StructReader<SubscriptionAck> {
public SubscriptionAck readStruct(Reader r) throws IOException {
r.readStructId(SUBSCRIPTION_ACK);
long version = r.readInt64();
if(version < 0L) throw new FormatException();
return new SubscriptionAck(version);
}
}

View File

@@ -1,38 +0,0 @@
package net.sf.briar.protocol;
import java.util.Map;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.SubscriptionUpdate;
class SubscriptionUpdateImpl implements SubscriptionUpdate {
private final Map<GroupId, GroupId> holes;
private final Map<Group, Long> subs;
private final long expiry, timestamp;
SubscriptionUpdateImpl(Map<GroupId, GroupId> holes, Map<Group, Long> subs,
long expiry, long timestamp) {
this.holes = holes;
this.subs = subs;
this.expiry = expiry;
this.timestamp = timestamp;
}
public Map<GroupId, GroupId> getHoles() {
return holes;
}
public Map<Group, Long> getSubscriptions() {
return subs;
}
public long getExpiryTime() {
return expiry;
}
public long getTimestamp() {
return timestamp;
}
}

View File

@@ -5,15 +5,12 @@ import static net.sf.briar.api.protocol.Types.GROUP;
import static net.sf.briar.api.protocol.Types.SUBSCRIPTION_UPDATE;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Collections;
import java.util.List;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.UniqueId;
import net.sf.briar.api.serial.Consumer;
import net.sf.briar.api.serial.CountingConsumer;
import net.sf.briar.api.serial.Reader;
@@ -22,46 +19,25 @@ import net.sf.briar.api.serial.StructReader;
class SubscriptionUpdateReader implements StructReader<SubscriptionUpdate> {
private final StructReader<Group> groupReader;
private final PacketFactory packetFactory;
SubscriptionUpdateReader(StructReader<Group> groupReader,
PacketFactory packetFactory) {
SubscriptionUpdateReader(StructReader<Group> groupReader) {
this.groupReader = groupReader;
this.packetFactory = packetFactory;
}
public SubscriptionUpdate readStruct(Reader r) throws IOException {
// Initialise the consumer
Consumer counting = new CountingConsumer(MAX_PACKET_LENGTH);
// Read the data
r.addConsumer(counting);
r.readStructId(SUBSCRIPTION_UPDATE);
// Holes
Map<GroupId, GroupId> holes = new HashMap<GroupId, GroupId>();
r.setMaxBytesLength(UniqueId.LENGTH);
r.readMapStart();
while(!r.hasMapEnd()) {
byte[] start = r.readBytes();
if(start.length != UniqueId.LENGTH) throw new FormatException();
byte[] end = r.readBytes();
if(end.length != UniqueId.LENGTH)throw new FormatException();
holes.put(new GroupId(start), new GroupId(end));
}
r.readMapEnd();
r.resetMaxBytesLength();
// Subscriptions
// Read the subscriptions
r.addStructReader(GROUP, groupReader);
Map<Group, Long> subs = r.readMap(Group.class, Long.class);
List<Group> subs = r.readList(Group.class);
r.removeStructReader(GROUP);
// Expiry time
long expiry = r.readInt64();
if(expiry < 0L) throw new FormatException();
// Timestamp
long timestamp = r.readInt64();
if(timestamp < 0L) throw new FormatException();
// Read the version number
long version = r.readInt64();
if(version < 0L) throw new FormatException();
r.removeConsumer(counting);
// Build and return the subscription update
return packetFactory.createSubscriptionUpdate(holes, subs, expiry,
timestamp);
subs = Collections.unmodifiableList(subs);
return new SubscriptionUpdate(subs, version);
}
}

View File

@@ -0,0 +1,24 @@
package net.sf.briar.protocol;
import static net.sf.briar.api.protocol.Types.TRANSPORT_ACK;
import java.io.IOException;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.TransportAck;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.UniqueId;
import net.sf.briar.api.serial.Reader;
import net.sf.briar.api.serial.StructReader;
class TransportAckReader implements StructReader<TransportAck> {
public TransportAck readStruct(Reader r) throws IOException {
r.readStructId(TRANSPORT_ACK);
byte[] b = r.readBytes(UniqueId.LENGTH);
if(b.length < UniqueId.LENGTH) throw new FormatException();
long version = r.readInt64();
if(version < 0L) throw new FormatException();
return new TransportAck(new TransportId(b), version);
}
}

View File

@@ -1,26 +0,0 @@
package net.sf.briar.protocol;
import java.util.Collection;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportUpdate;
class TransportUpdateImpl implements TransportUpdate {
private final Collection<Transport> transports;
private final long timestamp;
TransportUpdateImpl(Collection<Transport> transports,
long timestamp) {
this.transports = transports;
this.timestamp = timestamp;
}
public Collection<Transport> getTransports() {
return transports;
}
public long getTimestamp() {
return timestamp;
}
}

View File

@@ -3,19 +3,13 @@ package net.sf.briar.protocol;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PROPERTIES_PER_TRANSPORT;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PROPERTY_LENGTH;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_TRANSPORTS;
import static net.sf.briar.api.protocol.Types.TRANSPORT;
import static net.sf.briar.api.protocol.Types.TRANSPORT_UPDATE;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.TransportProperties;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.protocol.UniqueId;
@@ -26,50 +20,25 @@ import net.sf.briar.api.serial.StructReader;
class TransportUpdateReader implements StructReader<TransportUpdate> {
private final PacketFactory packetFactory;
private final StructReader<Transport> transportReader;
TransportUpdateReader(PacketFactory packetFactory) {
this.packetFactory = packetFactory;
transportReader = new TransportReader();
}
public TransportUpdate readStruct(Reader r) throws IOException {
// Initialise the consumer
Consumer counting = new CountingConsumer(MAX_PACKET_LENGTH);
// Read the data
r.addConsumer(counting);
r.readStructId(TRANSPORT_UPDATE);
r.addStructReader(TRANSPORT, transportReader);
Collection<Transport> transports = r.readList(Transport.class);
r.removeStructReader(TRANSPORT);
if(transports.size() > MAX_TRANSPORTS) throw new FormatException();
long timestamp = r.readInt64();
// Read the transport ID
byte[] b = r.readBytes(UniqueId.LENGTH);
if(b.length < UniqueId.LENGTH) throw new FormatException();
TransportId id = new TransportId(b);
// Read the transport properties
r.setMaxStringLength(MAX_PROPERTY_LENGTH);
Map<String, String> m = r.readMap(String.class, String.class);
r.resetMaxStringLength();
if(m.size() > MAX_PROPERTIES_PER_TRANSPORT)
throw new FormatException();
// Read the version number
long version = r.readInt64();
if(version < 0L) throw new FormatException();
r.removeConsumer(counting);
// Check for duplicate IDs
Set<TransportId> ids = new HashSet<TransportId>();
for(Transport t : transports) {
if(!ids.add(t.getId())) throw new FormatException();
}
// Build and return the transport update
return packetFactory.createTransportUpdate(transports, timestamp);
}
private static class TransportReader implements StructReader<Transport> {
public Transport readStruct(Reader r) throws IOException {
r.readStructId(TRANSPORT);
// Read the ID
byte[] b = r.readBytes(UniqueId.LENGTH);
if(b.length != UniqueId.LENGTH) throw new FormatException();
TransportId id = new TransportId(b);
// Read the properties
r.setMaxStringLength(MAX_PROPERTY_LENGTH);
Map<String, String> m = r.readMap(String.class, String.class);
r.resetMaxStringLength();
if(m.size() > MAX_PROPERTIES_PER_TRANSPORT)
throw new FormatException();
return new Transport(id, m);
}
return new TransportUpdate(id, new TransportProperties(m), version);
}
}

View File

@@ -27,10 +27,10 @@ import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.event.ContactRemovedEvent;
import net.sf.briar.api.db.event.DatabaseEvent;
import net.sf.briar.api.db.event.DatabaseListener;
import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
import net.sf.briar.api.db.event.MessageAddedEvent;
import net.sf.briar.api.db.event.MessageReceivedEvent;
import net.sf.briar.api.db.event.SubscriptionsUpdatedEvent;
import net.sf.briar.api.db.event.TransportsUpdatedEvent;
import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.Message;
@@ -55,6 +55,7 @@ import net.sf.briar.api.transport.ConnectionWriter;
import net.sf.briar.api.transport.ConnectionWriterFactory;
import net.sf.briar.util.ByteUtils;
// FIXME: Read and write subscription and transport acks
abstract class DuplexConnection implements DatabaseListener {
private static final Logger LOG =
@@ -132,7 +133,7 @@ abstract class DuplexConnection implements DatabaseListener {
if(affected.contains(contactId)) {
dbExecutor.execute(new GenerateSubscriptionUpdate());
}
} else if(e instanceof LocalTransportsUpdatedEvent) {
} else if(e instanceof TransportsUpdatedEvent) {
dbExecutor.execute(new GenerateTransportUpdate());
}
}
@@ -556,8 +557,9 @@ abstract class DuplexConnection implements DatabaseListener {
public void run() {
try {
TransportUpdate t = db.generateTransportUpdate(contactId);
if(t != null) writerTasks.add(new WriteTransportUpdate(t));
Collection<TransportUpdate> t =
db.generateTransportUpdates(contactId);
if(t != null) writerTasks.add(new WriteTransportUpdates(t));
} catch(DbException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
@@ -565,18 +567,18 @@ abstract class DuplexConnection implements DatabaseListener {
}
// This task runs on the writer thread
private class WriteTransportUpdate implements Runnable {
private class WriteTransportUpdates implements Runnable {
private final TransportUpdate update;
private final Collection<TransportUpdate> updates;
private WriteTransportUpdate(TransportUpdate update) {
this.update = update;
private WriteTransportUpdates(Collection<TransportUpdate> updates) {
this.updates = updates;
}
public void run() {
assert writer != null;
try {
writer.writeTransportUpdate(update);
for(TransportUpdate t : updates) writer.writeTransportUpdate(t);
} catch(IOException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
dispose(true, true);

View File

@@ -30,6 +30,7 @@ import net.sf.briar.api.transport.ConnectionReaderFactory;
import net.sf.briar.api.transport.ConnectionRegistry;
import net.sf.briar.util.ByteUtils;
// FIXME: Read subscription and transport acks
class IncomingSimplexConnection {
private static final Logger LOG =

View File

@@ -25,6 +25,7 @@ import net.sf.briar.api.transport.ConnectionWriter;
import net.sf.briar.api.transport.ConnectionWriterFactory;
import net.sf.briar.util.ByteUtils;
// FIXME: Write subscription and transport acks
class OutgoingSimplexConnection {
private static final Logger LOG =
@@ -66,15 +67,15 @@ class OutgoingSimplexConnection {
// There should be enough space for a packet
long capacity = conn.getRemainingCapacity();
if(capacity < MAX_PACKET_LENGTH) throw new EOFException();
// Write a transport update
TransportUpdate t = db.generateTransportUpdate(contactId);
if(t != null) writer.writeTransportUpdate(t);
// If there's space, write a subscription update
capacity = conn.getRemainingCapacity();
if(capacity >= MAX_PACKET_LENGTH) {
SubscriptionUpdate s = db.generateSubscriptionUpdate(contactId);
if(s != null) writer.writeSubscriptionUpdate(s);
// Write transport updates. FIXME: Check for space
Collection<TransportUpdate> updates =
db.generateTransportUpdates(contactId);
if(updates != null) {
for(TransportUpdate t : updates) writer.writeTransportUpdate(t);
}
// Write a subscription update. FIXME: Check for space
SubscriptionUpdate s = db.generateSubscriptionUpdate(contactId);
if(s != null) writer.writeSubscriptionUpdate(s);
// Write acks until you can't write acks no more
capacity = conn.getRemainingCapacity();
int maxMessages = writer.getMaxMessagesForAck(capacity);

View File

@@ -98,7 +98,7 @@ class ReaderImpl implements Reader {
if(!consumers.remove(c)) throw new IllegalArgumentException();
}
public void addStructReader(int id, StructReader<?> o) {
public void addStructReader(int id, StructReader<?> r) {
if(id < 0 || id > 255) throw new IllegalArgumentException();
if(structReaders.length < id + 1) {
int len = Math.min(256, Math.max(id + 1, structReaders.length * 2));
@@ -107,7 +107,7 @@ class ReaderImpl implements Reader {
structReaders.length);
structReaders = newStructReaders;
}
structReaders[id] = o;
structReaders[id] = r;
}
public void removeStructReader(int id) {

View File

@@ -12,7 +12,6 @@ import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
@@ -23,18 +22,18 @@ import net.sf.briar.api.protocol.Author;
import net.sf.briar.api.protocol.AuthorFactory;
import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.GroupFactory;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageFactory;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.MessageVerifier;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.ProtocolReader;
import net.sf.briar.api.protocol.ProtocolReaderFactory;
import net.sf.briar.api.protocol.ProtocolWriter;
import net.sf.briar.api.protocol.ProtocolWriterFactory;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.Subscription;
import net.sf.briar.api.protocol.SubscriptionHole;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportId;
@@ -66,7 +65,6 @@ public class ProtocolIntegrationTest extends BriarTestCase {
private final ConnectionWriterFactory connectionWriterFactory;
private final ProtocolReaderFactory protocolReaderFactory;
private final ProtocolWriterFactory protocolWriterFactory;
private final PacketFactory packetFactory;
private final MessageVerifier messageVerifier;
private final ContactId contactId;
@@ -80,7 +78,6 @@ public class ProtocolIntegrationTest extends BriarTestCase {
private final String messageBody = "Hello world";
private final Collection<MessageId> messageIds;
private final Collection<Transport> transports;
private final long timestamp = System.currentTimeMillis();
public ProtocolIntegrationTest() throws Exception {
super();
@@ -93,7 +90,6 @@ public class ProtocolIntegrationTest extends BriarTestCase {
connectionWriterFactory = i.getInstance(ConnectionWriterFactory.class);
protocolReaderFactory = i.getInstance(ProtocolReaderFactory.class);
protocolWriterFactory = i.getInstance(ProtocolWriterFactory.class);
packetFactory = i.getInstance(PacketFactory.class);
messageVerifier = i.getInstance(MessageVerifier.class);
contactId = new ContactId(234);
transportId = new TransportId(TestUtils.getRandomId());
@@ -149,33 +145,29 @@ public class ProtocolIntegrationTest extends BriarTestCase {
ProtocolWriter writer = protocolWriterFactory.createProtocolWriter(out1,
false);
Ack a = packetFactory.createAck(messageIds);
writer.writeAck(a);
writer.writeAck(new Ack(messageIds));
writer.writeMessage(message.getSerialised());
writer.writeMessage(message1.getSerialised());
writer.writeMessage(message2.getSerialised());
writer.writeMessage(message3.getSerialised());
Offer o = packetFactory.createOffer(messageIds);
writer.writeOffer(o);
writer.writeOffer(new Offer(messageIds));
BitSet requested = new BitSet(4);
requested.set(1);
requested.set(3);
Request r = packetFactory.createRequest(requested, 4);
writer.writeRequest(r);
writer.writeRequest(new Request(requested, 4));
// Use a LinkedHashMap for predictable iteration order
Map<Group, Long> subs = new LinkedHashMap<Group, Long>();
subs.put(group, 0L);
subs.put(group1, 0L);
SubscriptionUpdate s = packetFactory.createSubscriptionUpdate(
Collections.<GroupId, GroupId>emptyMap(), subs, 0L, timestamp);
Collection<SubscriptionHole> holes = Arrays.asList(
new SubscriptionHole(group.getId(), group1.getId()));
Collection<Subscription> subs = Arrays.asList(
new Subscription(group, 0L), new Subscription(group1, 0L));
SubscriptionUpdate s = new SubscriptionUpdate(holes, subs, 0L,
subscriptionVersion);
writer.writeSubscriptionUpdate(s);
TransportUpdate t = packetFactory.createTransportUpdate(transports,
timestamp);
TransportUpdate t = new TransportUpdate(transports, transportVersion);
writer.writeTransportUpdate(t);
writer.flush();
@@ -232,17 +224,12 @@ public class ProtocolIntegrationTest extends BriarTestCase {
// Read the subscription update
assertTrue(reader.hasSubscriptionUpdate());
SubscriptionUpdate s = reader.readSubscriptionUpdate();
Map<Group, Long> subs = s.getSubscriptions();
assertEquals(2, subs.size());
assertEquals(Long.valueOf(0L), subs.get(group));
assertEquals(Long.valueOf(0L), subs.get(group1));
assertTrue(s.getTimestamp() == timestamp);
// FIXME: Test for equality
// Read the transport update
assertTrue(reader.hasTransportUpdate());
TransportUpdate t = reader.readTransportUpdate();
assertEquals(transports, t.getTransports());
assertTrue(t.getTimestamp() == timestamp);
// FIXME: Test for equality
in.close();
}

View File

@@ -9,7 +9,6 @@ import net.sf.briar.api.clock.SystemClock;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.db.DatabaseCleaner.Callback;
import org.jmock.Expectations;
@@ -29,13 +28,11 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE));
}});
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown,
packetFactory);
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown);
db.checkFreeSpaceAndClean();
@@ -49,7 +46,6 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE - 1));
@@ -62,8 +58,7 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE));
}});
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown,
packetFactory);
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown);
db.checkFreeSpaceAndClean();
@@ -72,13 +67,12 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
@Test
public void testExpiringUnsendableMessageDoesNotTriggerBackwardInclusion()
throws DbException {
throws DbException {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE - 1));
@@ -93,8 +87,7 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE));
}});
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown,
packetFactory);
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown);
db.checkFreeSpaceAndClean();
@@ -103,13 +96,12 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
@Test
public void testExpiringSendableMessageTriggersBackwardInclusion()
throws DbException {
throws DbException {
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE - 1));
@@ -126,8 +118,7 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE));
}});
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown,
packetFactory);
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown);
db.checkFreeSpaceAndClean();
@@ -137,15 +128,14 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
@Override
protected <T> DatabaseComponent createDatabaseComponent(
Database<T> database, DatabaseCleaner cleaner,
ShutdownManager shutdown, PacketFactory packetFactory) {
return createDatabaseComponentImpl(database, cleaner, shutdown,
packetFactory);
ShutdownManager shutdown) {
return createDatabaseComponentImpl(database, cleaner, shutdown);
}
private <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
Database<T> database, DatabaseCleaner cleaner,
ShutdownManager shutdown, PacketFactory packetFactory) {
ShutdownManager shutdown) {
return new DatabaseComponentImpl<T>(database, cleaner, shutdown,
packetFactory, new SystemClock());
new SystemClock());
}
}

View File

@@ -1,6 +1,5 @@
package net.sf.briar.db;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
@@ -29,7 +28,6 @@ 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.PacketFactory;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.protocol.SubscriptionUpdate;
import net.sf.briar.api.protocol.Transport;
@@ -89,7 +87,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
protected abstract <T> DatabaseComponent createDatabaseComponent(
Database<T> database, DatabaseCleaner cleaner,
ShutdownManager shutdown, PacketFactory packetFactory);
ShutdownManager shutdown);
@Test
@SuppressWarnings("unchecked")
@@ -99,7 +97,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final DatabaseListener listener = context.mock(DatabaseListener.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
@@ -167,7 +164,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).close();
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.open(false);
db.addListener(listener);
@@ -198,7 +195,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
// setRating(authorId, Rating.GOOD)
allowing(database).startTransaction();
@@ -217,7 +213,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.setRating(authorId, Rating.GOOD);
@@ -231,7 +227,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
// setRating(authorId, Rating.GOOD)
oneOf(database).startTransaction();
@@ -254,7 +249,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.setRating(authorId, Rating.GOOD);
@@ -269,7 +264,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
// setRating(authorId, Rating.GOOD)
oneOf(database).startTransaction();
@@ -295,7 +289,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.setRating(authorId, Rating.GOOD);
@@ -310,7 +304,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
// addLocalGroupMessage(message)
oneOf(database).startTransaction();
@@ -320,7 +313,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addLocalGroupMessage(message);
@@ -334,7 +327,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
// addLocalGroupMessage(message)
oneOf(database).startTransaction();
@@ -346,7 +338,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addLocalGroupMessage(message);
@@ -360,7 +352,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
// addLocalGroupMessage(message)
oneOf(database).startTransaction();
@@ -381,7 +372,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addLocalGroupMessage(message);
@@ -396,7 +387,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
// addLocalGroupMessage(message)
oneOf(database).startTransaction();
@@ -420,7 +410,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addLocalGroupMessage(message);
@@ -434,7 +424,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -446,7 +435,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(false));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addLocalPrivateMessage(privateMessage, contactId);
@@ -460,7 +449,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -473,7 +461,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).setStatus(txn, contactId, messageId, Status.NEW);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addLocalPrivateMessage(privateMessage, contactId);
@@ -488,7 +476,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Ack ack = context.mock(Ack.class);
final Offer offer = context.mock(Offer.class);
final SubscriptionUpdate subscriptionUpdate =
@@ -504,7 +491,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
exactly(16).of(database).abortTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
try {
db.addContactTransport(contactTransport);
@@ -598,7 +585,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
// Check whether the contact transport is in the DB (which it's not)
exactly(2).of(database).startTransaction();
@@ -609,7 +595,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
exactly(2).of(database).abortTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
try {
db.incrementConnectionCounter(contactId, transportId, 0L);
@@ -633,8 +619,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Ack ack = context.mock(Ack.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -644,16 +628,14 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
// Get the messages to ack
oneOf(database).getMessagesToAck(txn, contactId, 123);
will(returnValue(messagesToAck));
// Create the ack packet
oneOf(packetFactory).createAck(messagesToAck);
will(returnValue(ack));
// Record the messages that were acked
oneOf(database).removeMessagesToAck(txn, contactId, messagesToAck);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
assertEquals(ack, db.generateAck(contactId, 123));
Ack a = db.generateAck(contactId, 123);
assertEquals(messagesToAck, a.getMessageIds());
context.assertIsSatisfied();
}
@@ -669,7 +651,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -687,7 +668,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).addOutstandingMessages(txn, contactId, sendable);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
assertEquals(messages, db.generateBatch(contactId, size * 2));
@@ -698,17 +679,14 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
public void testGenerateBatchFromRequest() throws Exception {
final MessageId messageId2 = new MessageId(TestUtils.getRandomId());
final byte[] raw1 = new byte[size];
final Collection<MessageId> requested = new ArrayList<MessageId>();
requested.add(messageId);
requested.add(messageId1);
requested.add(messageId2);
final Collection<MessageId> requested = Arrays.asList(messageId,
messageId1, messageId2);
final Collection<byte[]> messages = Arrays.asList(raw1);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -727,7 +705,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
Collections.singletonList(messageId1));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
assertEquals(messages, db.generateBatch(contactId, size * 3,
requested));
@@ -738,16 +716,13 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
@Test
public void testGenerateOffer() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final Collection<MessageId> offerable = new ArrayList<MessageId>();
offerable.add(messageId);
offerable.add(messageId1);
final Collection<MessageId> messagesToOffer = Arrays.asList(messageId,
messageId1);
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Offer offer = context.mock(Offer.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -756,15 +731,13 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(true));
// Get the sendable message IDs
oneOf(database).getMessagesToOffer(txn, contactId, 123);
will(returnValue(offerable));
// Create the packet
oneOf(packetFactory).createOffer(offerable);
will(returnValue(offer));
will(returnValue(messagesToOffer));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
assertEquals(offer, db.generateOffer(contactId, 123));
Offer o = db.generateOffer(contactId, 123);
assertEquals(messagesToOffer, o.getMessageIds());
context.assertIsSatisfied();
}
@@ -776,9 +749,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final SubscriptionUpdate subscriptionUpdate =
context.mock(SubscriptionUpdate.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -786,55 +756,39 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Get the visible holes and subscriptions
oneOf(database).getVisibleHoles(with(txn), with(contactId),
with(any(long.class)));
will(returnValue(Collections.emptyMap()));
oneOf(database).getVisibleSubscriptions(with(txn), with(contactId),
with(any(long.class)));
will(returnValue(Collections.singletonMap(group, 0L)));
oneOf(database).getVisibleHoles(txn, contactId);
will(returnValue(Collections.emptyMap())); // FIXME
oneOf(database).getVisibleSubscriptions(txn, contactId);
will(returnValue(Collections.singletonMap(group, 0L))); // FIXME
// Get the expiry time
oneOf(database).getExpiryTime(txn);
will(returnValue(0L));
// Create the packet
oneOf(packetFactory).createSubscriptionUpdate(
with(Collections.<GroupId, GroupId>emptyMap()),
with(Collections.singletonMap(group, 0L)),
with(any(long.class)),
with(any(long.class)));
will(returnValue(subscriptionUpdate));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
assertEquals(subscriptionUpdate,
db.generateSubscriptionUpdate(contactId));
SubscriptionUpdate s = db.generateSubscriptionUpdate(contactId);
// FIXME: Check that the update contains the expected data
context.assertIsSatisfied();
}
@Test
public void testTransportUpdateNotSentUnlessDue() throws Exception {
final long now = System.currentTimeMillis();
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
allowing(database).commitTransaction(txn);
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Check whether an update is due
oneOf(database).getTransportsModified(txn);
will(returnValue(now - 1L));
oneOf(database).getTransportsSent(txn, contactId);
will(returnValue(now));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
assertNull(db.generateTransportUpdate(contactId));
@@ -848,34 +802,21 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final TransportUpdate transportUpdate =
context.mock(TransportUpdate.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
allowing(database).commitTransaction(txn);
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Check whether an update is due
oneOf(database).getTransportsModified(txn);
will(returnValue(0L));
oneOf(database).getTransportsSent(txn, contactId);
will(returnValue(0L));
// Get the local transport properties
oneOf(database).getLocalTransports(txn);
will(returnValue(transports));
oneOf(database).setTransportsSent(with(txn), with(contactId),
with(any(long.class)));
// Create the packet
oneOf(packetFactory).createTransportUpdate(with(transports),
with(any(long.class)));
will(returnValue(transportUpdate));
oneOf(database).getTransports(txn);
will(returnValue(transports)); // FIXME
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
assertEquals(transportUpdate, db.generateTransportUpdate(contactId));
TransportUpdate t = db.generateTransportUpdate(contactId);
// FIXME: Check that the update contains the expected data
context.assertIsSatisfied();
}
@@ -887,8 +828,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Ack ack = context.mock(Ack.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -896,15 +835,13 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
// Get the acked messages
oneOf(ack).getMessageIds();
will(returnValue(Collections.singletonList(messageId)));
oneOf(database).removeOutstandingMessages(txn, contactId,
Collections.singletonList(messageId));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.receiveAck(contactId, ack);
db.receiveAck(contactId, new Ack(Collections.singletonList(messageId)));
context.assertIsSatisfied();
}
@@ -916,7 +853,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -931,7 +867,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.receiveMessage(contactId, privateMessage);
@@ -945,7 +881,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -959,7 +894,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.receiveMessage(contactId, privateMessage);
@@ -974,7 +909,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -989,7 +923,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.receiveMessage(contactId, message);
@@ -1004,7 +938,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1023,7 +956,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.receiveMessage(contactId, message);
@@ -1037,7 +970,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1065,7 +997,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.receiveMessage(contactId, message);
@@ -1080,7 +1012,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1110,7 +1041,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).addMessageToAck(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.receiveMessage(contactId, message);
@@ -1121,10 +1052,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
public void testReceiveOffer() throws Exception {
final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
final MessageId messageId2 = new MessageId(TestUtils.getRandomId());
final Collection<MessageId> offered = new ArrayList<MessageId>();
offered.add(messageId);
offered.add(messageId1);
offered.add(messageId2);
final Collection<MessageId> offered = Arrays.asList(messageId,
messageId1, messageId2);
final BitSet expectedRequest = new BitSet(3);
expectedRequest.set(0);
expectedRequest.set(2);
@@ -1133,9 +1062,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final Offer offer = context.mock(Offer.class);
final Request request = context.mock(Request.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1151,14 +1078,13 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(true)); // Visible - do not request message # 1
oneOf(database).setStatusSeenIfVisible(txn, contactId, messageId2);
will(returnValue(false)); // Not visible - request message # 2
// Create the packet
oneOf(packetFactory).createRequest(expectedRequest, 3);
will(returnValue(request));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
assertEquals(request, db.receiveOffer(contactId, offer));
Request r = db.receiveOffer(contactId, offer);
assertEquals(expectedRequest, r.getBitmap());
assertEquals(3, r.getLength());
context.assertIsSatisfied();
}
@@ -1167,15 +1093,14 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
public void testReceiveSubscriptionUpdate() throws Exception {
final GroupId start = new GroupId(TestUtils.getRandomId());
final GroupId end = new GroupId(TestUtils.getRandomId());
final long expiry = 1234L, timestamp = 5678L;
final long expiry = 1234L;
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final SubscriptionUpdate subscriptionUpdate =
context.mock(SubscriptionUpdate.class);
context.mock(SubscriptionUpdate.class); // FIXME: Don't mock
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1184,21 +1109,18 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
will(returnValue(true));
// Get the contents of the update
oneOf(subscriptionUpdate).getHoles();
will(returnValue(Collections.singletonMap(start, end)));
oneOf(subscriptionUpdate).getSubscriptions();
will(returnValue(Collections.singletonMap(group, 0L)));
will(returnValue(Collections.singletonMap(start, end))); // FIXME
oneOf(subscriptionUpdate).getGroupIds();
will(returnValue(Collections.singletonMap(group, 0L))); // FIXME
oneOf(subscriptionUpdate).getExpiryTime();
will(returnValue(expiry));
oneOf(subscriptionUpdate).getTimestamp();
will(returnValue(timestamp));
// Store the contents of the update
oneOf(database).removeSubscriptions(txn, contactId, start, end);
oneOf(database).addSubscription(txn, contactId, group, 0L);
oneOf(database).setExpiryTime(txn, contactId, expiry);
oneOf(database).setSubscriptionsReceived(txn, contactId, timestamp);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.receiveSubscriptionUpdate(contactId, subscriptionUpdate);
@@ -1207,15 +1129,13 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
@Test
public void testReceiveTransportUpdate() throws Exception {
final long timestamp = 1234L;
Mockery context = new Mockery();
@SuppressWarnings("unchecked")
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final TransportUpdate transportUpdate =
context.mock(TransportUpdate.class);
context.mock(TransportUpdate.class); // FIXME: Don't mock
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1225,13 +1145,10 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
// Get the contents of the update
oneOf(transportUpdate).getTransports();
will(returnValue(transports));
oneOf(transportUpdate).getTimestamp();
will(returnValue(timestamp));
oneOf(database).setTransports(txn, contactId, transports,
timestamp);
oneOf(database).setTransports(txn, contactId, transports);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.receiveTransportUpdate(contactId, transportUpdate);
@@ -1245,7 +1162,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final DatabaseListener listener = context.mock(DatabaseListener.class);
context.checking(new Expectations() {{
// addLocalGroupMessage(message)
@@ -1268,7 +1184,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(listener).eventOccurred(with(any(MessageAddedEvent.class)));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addListener(listener);
db.addLocalGroupMessage(message);
@@ -1283,7 +1199,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final DatabaseListener listener = context.mock(DatabaseListener.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
@@ -1299,7 +1214,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(listener).eventOccurred(with(any(MessageAddedEvent.class)));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addListener(listener);
db.addLocalPrivateMessage(privateMessage, contactId);
@@ -1315,7 +1230,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final DatabaseListener listener = context.mock(DatabaseListener.class);
context.checking(new Expectations() {{
// addLocalGroupMessage(message)
@@ -1329,7 +1243,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
// The message was not added, so the listener should not be called
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addListener(listener);
db.addLocalGroupMessage(message);
@@ -1345,7 +1259,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final DatabaseListener listener = context.mock(DatabaseListener.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
@@ -1359,7 +1272,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
// The message was not added, so the listener should not be called
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addListener(listener);
db.addLocalPrivateMessage(privateMessage, contactId);
@@ -1377,19 +1290,16 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
oneOf(database).startTransaction();
will(returnValue(txn));
oneOf(database).getLocalProperties(txn, transportId);
will(returnValue(new TransportProperties()));
oneOf(database).mergeLocalProperties(txn, transportId, properties);
oneOf(database).setTransportsModified(with(txn),
with(any(long.class)));
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.mergeLocalProperties(transportId, properties);
@@ -1406,7 +1316,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final DatabaseListener listener = context.mock(DatabaseListener.class);
context.checking(new Expectations() {{
oneOf(database).startTransaction();
@@ -1416,7 +1325,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addListener(listener);
db.mergeLocalProperties(transportId, properties);
@@ -1431,7 +1340,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
allowing(database).startTransaction();
will(returnValue(txn));
@@ -1442,7 +1350,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).setStatusSeenIfVisible(txn, contactId, messageId);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.setSeen(contactId, Collections.singletonList(messageId));
@@ -1458,7 +1366,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final DatabaseListener listener = context.mock(DatabaseListener.class);
context.checking(new Expectations() {{
oneOf(database).startTransaction();
@@ -1473,7 +1380,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
SubscriptionsUpdatedEvent.class)));
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addListener(listener);
db.setVisibility(groupId, Collections.singletonList(contactId));
@@ -1490,7 +1397,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
final DatabaseListener listener = context.mock(DatabaseListener.class);
context.checking(new Expectations() {{
oneOf(database).startTransaction();
@@ -1502,7 +1408,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addListener(listener);
db.setVisibility(groupId, both);
@@ -1517,7 +1423,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
final PacketFactory packetFactory = context.mock(PacketFactory.class);
context.checking(new Expectations() {{
// addSecrets()
oneOf(database).startTransaction();
@@ -1536,7 +1441,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, cleaner,
shutdown, packetFactory);
shutdown);
db.addSecrets(Collections.singletonList(temporarySecret));
assertEquals(Collections.singletonList(temporarySecret),

View File

@@ -5,13 +5,11 @@ import static net.sf.briar.api.protocol.Types.ACK;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Collection;
import net.sf.briar.BriarTestCase;
import net.sf.briar.TestUtils;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.serial.Reader;
import net.sf.briar.api.serial.ReaderFactory;
import net.sf.briar.api.serial.SerialComponent;
@@ -19,8 +17,6 @@ import net.sf.briar.api.serial.Writer;
import net.sf.briar.api.serial.WriterFactory;
import net.sf.briar.serial.SerialModule;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import com.google.inject.Guice;
@@ -33,7 +29,6 @@ public class AckReaderTest extends BriarTestCase {
private final SerialComponent serial;
private final ReaderFactory readerFactory;
private final WriterFactory writerFactory;
private final Mockery context;
public AckReaderTest() throws Exception {
super();
@@ -41,61 +36,39 @@ public class AckReaderTest extends BriarTestCase {
serial = i.getInstance(SerialComponent.class);
readerFactory = i.getInstance(ReaderFactory.class);
writerFactory = i.getInstance(WriterFactory.class);
context = new Mockery();
}
@Test
public void testFormatExceptionIfAckIsTooLarge() throws Exception {
PacketFactory packetFactory = context.mock(PacketFactory.class);
AckReader ackReader = new AckReader(packetFactory);
byte[] b = createAck(true);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(ACK, ackReader);
reader.addStructReader(ACK, new AckReader());
try {
reader.readStruct(ACK, Ack.class);
fail();
} catch(FormatException expected) {}
context.assertIsSatisfied();
}
@Test
@SuppressWarnings("unchecked")
public void testNoFormatExceptionIfAckIsMaximumSize() throws Exception {
final PacketFactory packetFactory = context.mock(PacketFactory.class);
AckReader ackReader = new AckReader(packetFactory);
final Ack ack = context.mock(Ack.class);
context.checking(new Expectations() {{
oneOf(packetFactory).createAck(with(any(Collection.class)));
will(returnValue(ack));
}});
byte[] b = createAck(false);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(ACK, ackReader);
assertEquals(ack, reader.readStruct(ACK, Ack.class));
context.assertIsSatisfied();
reader.addStructReader(ACK, new AckReader());
reader.readStruct(ACK, Ack.class);
}
@Test
public void testEmptyAck() throws Exception {
final PacketFactory packetFactory = context.mock(PacketFactory.class);
AckReader ackReader = new AckReader(packetFactory);
byte[] b = createEmptyAck();
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(ACK, ackReader);
reader.addStructReader(ACK, new AckReader());
try {
reader.readStruct(ACK, Ack.class);
fail();
} catch(FormatException expected) {}
context.assertIsSatisfied();
}
private byte[] createAck(boolean tooBig) throws Exception {

View File

@@ -4,17 +4,13 @@ import static net.sf.briar.api.protocol.ProtocolConstants.MAX_AUTHOR_NAME_LENGTH
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_BODY_LENGTH;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_GROUP_NAME_LENGTH;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PROPERTIES_PER_TRANSPORT;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PROPERTY_LENGTH;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PUBLIC_KEY_LENGTH;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_SUBJECT_LENGTH;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_TRANSPORTS;
import java.io.ByteArrayOutputStream;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import net.sf.briar.BriarTestCase;
import net.sf.briar.TestUtils;
@@ -28,12 +24,8 @@ import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageFactory;
import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.ProtocolWriter;
import net.sf.briar.api.protocol.ProtocolWriterFactory;
import net.sf.briar.api.protocol.Transport;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.protocol.TransportUpdate;
import net.sf.briar.api.protocol.UniqueId;
import net.sf.briar.clock.ClockModule;
import net.sf.briar.crypto.CryptoModule;
@@ -50,7 +42,6 @@ public class ConstantsTest extends BriarTestCase {
private final GroupFactory groupFactory;
private final AuthorFactory authorFactory;
private final MessageFactory messageFactory;
private final PacketFactory packetFactory;
private final ProtocolWriterFactory protocolWriterFactory;
public ConstantsTest() throws Exception {
@@ -61,7 +52,6 @@ public class ConstantsTest extends BriarTestCase {
groupFactory = i.getInstance(GroupFactory.class);
authorFactory = i.getInstance(AuthorFactory.class);
messageFactory = i.getInstance(MessageFactory.class);
packetFactory = i.getInstance(PacketFactory.class);
protocolWriterFactory = i.getInstance(ProtocolWriterFactory.class);
}
@@ -85,8 +75,7 @@ public class ConstantsTest extends BriarTestCase {
for(int i = 0; i < maxMessages; i++) {
acked.add(new MessageId(TestUtils.getRandomId()));
}
Ack a = packetFactory.createAck(acked);
writer.writeAck(a);
writer.writeAck(new Ack(acked));
// Check the size of the serialised ack
assertTrue(out.size() <= length);
}
@@ -136,43 +125,11 @@ public class ConstantsTest extends BriarTestCase {
for(int i = 0; i < maxMessages; i++) {
offered.add(new MessageId(TestUtils.getRandomId()));
}
Offer o = packetFactory.createOffer(offered);
writer.writeOffer(o);
writer.writeOffer(new Offer(offered));
// Check the size of the serialised offer
assertTrue(out.size() <= length);
}
@Test
public void testTransportsFitIntoUpdate() throws Exception {
// Create the maximum number of plugins, each with the maximum number
// of maximum-length properties
Collection<Transport> transports = new ArrayList<Transport>();
for(int i = 0; i < MAX_TRANSPORTS; i++) {
TransportId id = new TransportId(TestUtils.getRandomId());
Transport t = new Transport(id);
Map<String, String> m = t.getProperties();
for(int j = 0; j < MAX_PROPERTIES_PER_TRANSPORT; j++) {
String key = createRandomString(MAX_PROPERTY_LENGTH);
String value = createRandomString(MAX_PROPERTY_LENGTH);
m.put(key, value);
}
transports.add(t);
}
// Add the transports to an update
ByteArrayOutputStream out =
new ByteArrayOutputStream(MAX_PACKET_LENGTH);
ProtocolWriter writer = protocolWriterFactory.createProtocolWriter(out,
true);
TransportUpdate t = packetFactory.createTransportUpdate(transports,
Long.MAX_VALUE);
writer.writeTransportUpdate(t);
// Check the size of the serialised update
assertTrue(out.size() > MAX_TRANSPORTS * (UniqueId.LENGTH + 4
+ (MAX_PROPERTIES_PER_TRANSPORT * MAX_PROPERTY_LENGTH * 2))
+ 8);
assertTrue(out.size() <= MAX_PACKET_LENGTH);
}
private static String createRandomString(int length) throws Exception {
StringBuilder s = new StringBuilder(length);
for(int i = 0; i < length; i++) {

View File

@@ -5,13 +5,11 @@ import static net.sf.briar.api.protocol.Types.OFFER;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Collection;
import net.sf.briar.BriarTestCase;
import net.sf.briar.TestUtils;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.Offer;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.serial.Reader;
import net.sf.briar.api.serial.ReaderFactory;
import net.sf.briar.api.serial.SerialComponent;
@@ -19,8 +17,6 @@ import net.sf.briar.api.serial.Writer;
import net.sf.briar.api.serial.WriterFactory;
import net.sf.briar.serial.SerialModule;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import com.google.inject.Guice;
@@ -33,7 +29,6 @@ public class OfferReaderTest extends BriarTestCase {
private final SerialComponent serial;
private final ReaderFactory readerFactory;
private final WriterFactory writerFactory;
private final Mockery context;
public OfferReaderTest() throws Exception {
super();
@@ -41,61 +36,39 @@ public class OfferReaderTest extends BriarTestCase {
serial = i.getInstance(SerialComponent.class);
readerFactory = i.getInstance(ReaderFactory.class);
writerFactory = i.getInstance(WriterFactory.class);
context = new Mockery();
}
@Test
public void testFormatExceptionIfOfferIsTooLarge() throws Exception {
PacketFactory packetFactory = context.mock(PacketFactory.class);
OfferReader offerReader = new OfferReader(packetFactory);
byte[] b = createOffer(true);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(OFFER, offerReader);
reader.addStructReader(OFFER, new OfferReader());
try {
reader.readStruct(OFFER, Offer.class);
fail();
} catch(FormatException expected) {}
context.assertIsSatisfied();
}
@Test
@SuppressWarnings("unchecked")
public void testNoFormatExceptionIfOfferIsMaximumSize() throws Exception {
final PacketFactory packetFactory = context.mock(PacketFactory.class);
OfferReader offerReader = new OfferReader(packetFactory);
final Offer offer = context.mock(Offer.class);
context.checking(new Expectations() {{
oneOf(packetFactory).createOffer(with(any(Collection.class)));
will(returnValue(offer));
}});
byte[] b = createOffer(false);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(OFFER, offerReader);
assertEquals(offer, reader.readStruct(OFFER, Offer.class));
context.assertIsSatisfied();
reader.addStructReader(OFFER, new OfferReader());
reader.readStruct(OFFER, Offer.class);
}
@Test
public void testEmptyOffer() throws Exception {
final PacketFactory packetFactory = context.mock(PacketFactory.class);
OfferReader offerReader = new OfferReader(packetFactory);
byte[] b = createEmptyOffer();
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(OFFER, offerReader);
reader.addStructReader(OFFER, new OfferReader());
try {
reader.readStruct(OFFER, Offer.class);
fail();
} catch(FormatException expected) {}
context.assertIsSatisfied();
}
private byte[] createOffer(boolean tooBig) throws Exception {

View File

@@ -5,7 +5,6 @@ import java.io.IOException;
import java.util.BitSet;
import net.sf.briar.BriarTestCase;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.ProtocolWriter;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.serial.SerialComponent;
@@ -24,7 +23,6 @@ public class ProtocolWriterImplTest extends BriarTestCase {
// FIXME: This is an integration test, not a unit test
private final PacketFactory packetFactory;
private final SerialComponent serial;
private final WriterFactory writerFactory;
@@ -32,7 +30,6 @@ public class ProtocolWriterImplTest extends BriarTestCase {
super();
Injector i = Guice.createInjector(new ClockModule(), new CryptoModule(),
new ProtocolModule(), new SerialModule());
packetFactory = i.getInstance(PacketFactory.class);
serial = i.getInstance(SerialComponent.class);
writerFactory = i.getInstance(WriterFactory.class);
}
@@ -54,8 +51,7 @@ public class ProtocolWriterImplTest extends BriarTestCase {
b.set(11);
b.set(12);
b.set(15);
Request r = packetFactory.createRequest(b, 16);
w.writeRequest(r);
w.writeRequest(new Request(b, 16));
// Short user tag 6, 0 as uint7, short bytes with length 2, 0xD959
byte[] output = out.toByteArray();
assertEquals("C6" + "00" + "92" + "D959",
@@ -78,8 +74,7 @@ public class ProtocolWriterImplTest extends BriarTestCase {
b.set(9);
b.set(11);
b.set(12);
Request r = packetFactory.createRequest(b, 13);
w.writeRequest(r);
w.writeRequest(new Request(b, 13));
// Short user tag 6, 3 as uint7, short bytes with length 2, 0x59D8
byte[] output = out.toByteArray();
assertEquals("C6" + "03" + "92" + "59D8",

View File

@@ -9,7 +9,6 @@ import java.util.BitSet;
import net.sf.briar.BriarTestCase;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.protocol.PacketFactory;
import net.sf.briar.api.protocol.Request;
import net.sf.briar.api.serial.Reader;
import net.sf.briar.api.serial.ReaderFactory;
@@ -19,8 +18,6 @@ import net.sf.briar.clock.ClockModule;
import net.sf.briar.crypto.CryptoModule;
import net.sf.briar.serial.SerialModule;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import com.google.inject.Guice;
@@ -32,8 +29,6 @@ public class RequestReaderTest extends BriarTestCase {
private final ReaderFactory readerFactory;
private final WriterFactory writerFactory;
private final PacketFactory packetFactory;
private final Mockery context;
public RequestReaderTest() throws Exception {
super();
@@ -41,45 +36,27 @@ public class RequestReaderTest extends BriarTestCase {
new ProtocolModule(), new SerialModule());
readerFactory = i.getInstance(ReaderFactory.class);
writerFactory = i.getInstance(WriterFactory.class);
packetFactory = i.getInstance(PacketFactory.class);
context = new Mockery();
}
@Test
public void testFormatExceptionIfRequestIsTooLarge() throws Exception {
PacketFactory packetFactory = context.mock(PacketFactory.class);
RequestReader requestReader = new RequestReader(packetFactory);
byte[] b = createRequest(true);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(REQUEST, requestReader);
reader.addStructReader(REQUEST, new RequestReader());
try {
reader.readStruct(REQUEST, Request.class);
fail();
} catch(FormatException expected) {}
context.assertIsSatisfied();
}
@Test
public void testNoFormatExceptionIfRequestIsMaximumSize() throws Exception {
final PacketFactory packetFactory = context.mock(PacketFactory.class);
RequestReader requestReader = new RequestReader(packetFactory);
final Request request = context.mock(Request.class);
context.checking(new Expectations() {{
oneOf(packetFactory).createRequest(with(any(BitSet.class)),
with(any(int.class)));
will(returnValue(request));
}});
byte[] b = createRequest(false);
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
reader.addStructReader(REQUEST, requestReader);
assertEquals(request, reader.readStruct(REQUEST, Request.class));
context.assertIsSatisfied();
reader.addStructReader(REQUEST, new RequestReader());
reader.readStruct(REQUEST, Request.class);
}
@Test
@@ -104,7 +81,7 @@ public class RequestReaderTest extends BriarTestCase {
// Deserialise the request
ByteArrayInputStream in = new ByteArrayInputStream(b);
Reader reader = readerFactory.createReader(in);
RequestReader requestReader = new RequestReader(packetFactory);
RequestReader requestReader = new RequestReader();
reader.addStructReader(REQUEST, requestReader);
Request r = reader.readStruct(REQUEST, Request.class);
BitSet decoded = r.getBitmap();

View File

@@ -5,8 +5,6 @@ import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.Random;
import net.sf.briar.BriarTestCase;
@@ -161,17 +159,9 @@ public class SimplexProtocolIntegrationTest extends BriarTestCase {
MessageListener listener = new MessageListener();
db.addListener(listener);
// Fake a transport update from Alice
TransportUpdate transportUpdate = new TransportUpdate() {
public Collection<Transport> getTransports() {
Transport t = new Transport(transportId);
return Collections.singletonList(t);
}
public long getTimestamp() {
return System.currentTimeMillis();
}
};
Transport t = new Transport(transportId);
TransportUpdate transportUpdate = new TransportUpdate(t,
transportVersion);
db.receiveTransportUpdate(contactId, transportUpdate);
// Create a connection recogniser and recognise the connection
ByteArrayInputStream in = new ByteArrayInputStream(b);