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;