Restructured project prior to merging changes from Afsnit repo.

This commit is contained in:
akwizgran
2012-10-30 20:30:50 +00:00
parent 0ffdaf89c0
commit e6ac5494fc
279 changed files with 44 additions and 87 deletions

1
src/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

3
src/build.xml Normal file
View File

@@ -0,0 +1,3 @@
<project name='api' default='depend'>
<import file='../build-common.xml'/>
</project>

View File

@@ -0,0 +1,34 @@
package net.sf.briar.api;
import java.util.Arrays;
/** A wrapper around a byte array, to allow it to be stored in maps etc. */
public class Bytes {
private final byte[] bytes;
private int hashCode = -1;
public Bytes(byte[] bytes) {
this.bytes = bytes;
}
public byte[] getBytes() {
return bytes;
}
@Override
public int hashCode() {
// Thread-safe because if two or more threads check and update the
// value, they'll calculate the same value
if(hashCode == -1) hashCode = Arrays.hashCode(bytes);
return hashCode;
}
@Override
public boolean equals(Object o) {
if(o instanceof Bytes)
return Arrays.equals(bytes, ((Bytes) o).bytes);
return false;
}
}

View File

@@ -0,0 +1,29 @@
package net.sf.briar.api;
/**
* Type-safe wrapper for an integer that uniquely identifies a contact within
* the scope of a single node.
*/
public class ContactId {
private final int id;
public ContactId(int id) {
this.id = id;
}
public int getInt() {
return id;
}
@Override
public boolean equals(Object o) {
if(o instanceof ContactId) return id == ((ContactId) o).id;
return false;
}
@Override
public int hashCode() {
return id;
}
}

View File

@@ -0,0 +1,9 @@
package net.sf.briar.api;
import java.io.IOException;
/** An exception that indicates an unrecoverable formatting error. */
public class FormatException extends IOException {
private static final long serialVersionUID = 2274966775687766337L;
}

View File

@@ -0,0 +1,6 @@
package net.sf.briar.api;
/** The ratings that may be applied to an author in peer moderation. */
public enum Rating {
BAD, UNRATED, GOOD
}

View File

@@ -0,0 +1,17 @@
package net.sf.briar.api;
import java.util.Hashtable;
import java.util.Map;
public class TransportConfig extends Hashtable<String, String> {
private static final long serialVersionUID = 2330384620787778596L;
public TransportConfig(Map<String, String> c) {
super(c);
}
public TransportConfig() {
super();
}
}

View File

@@ -0,0 +1,17 @@
package net.sf.briar.api;
import java.util.Hashtable;
import java.util.Map;
public class TransportProperties extends Hashtable<String, String> {
private static final long serialVersionUID = 7533739534204953625L;
public TransportProperties(Map<String, String> p) {
super(p);
}
public TransportProperties() {
super();
}
}

View File

@@ -0,0 +1,11 @@
package net.sf.briar.api.clock;
/**
* An interface for time-related system functions that allows them to be
* replaced for testing.
*/
public interface Clock {
/** @see {@link java.lang.System#currentTimeMillis()} */
long currentTimeMillis();
}

View File

@@ -0,0 +1,9 @@
package net.sf.briar.api.clock;
/** Default clock implementation. */
public class SystemClock implements Clock {
public long currentTimeMillis() {
return System.currentTimeMillis();
}
}

View File

@@ -0,0 +1,29 @@
package net.sf.briar.api.crypto;
import java.security.InvalidKeyException;
import java.security.Key;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
/**
* A wrapper for a provider-dependent cipher class, since javax.crypto.Cipher
* doesn't support additional authenticated data until Java 7.
*/
public interface AuthenticatedCipher {
/**
* Initializes this cipher with a key, an initialisation vector (IV) and
* additional authenticated data (AAD).
*/
void init(int opmode, Key key, byte[] iv, byte[] aad)
throws InvalidKeyException;
/** Encrypts or decrypts data in a single-part operation. */
int doFinal(byte[] input, int inputOff, int len, byte[] output,
int outputOff) throws IllegalBlockSizeException,
BadPaddingException;
/** Returns the length of the message authenticated code (MAC) in bytes. */
int getMacLength();
}

View File

@@ -0,0 +1,79 @@
package net.sf.briar.api.crypto;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import javax.crypto.Cipher;
public interface CryptoComponent {
/**
* Derives a tag key from the given temporary secret.
* @param alice Indicates whether the key is for connections initiated by
* Alice or Bob.
*/
ErasableKey deriveTagKey(byte[] secret, boolean alice);
/**
* Derives a frame key from the given temporary secret and connection
* number.
* @param alice Indicates whether the key is for a connection initiated by
* Alice or Bob.
* @param initiator Indicates whether the key is for the initiator's or the
* responder's side of the connection.
*/
ErasableKey deriveFrameKey(byte[] secret, long connection, boolean alice,
boolean initiator);
/**
* Derives an initial shared secret from two public keys and one of the
* corresponding private keys.
* @param alice Indicates whether the private key belongs to Alice or Bob.
*/
byte[] deriveInitialSecret(byte[] ourPublicKey, byte[] theirPublicKey,
PrivateKey ourPrivateKey, boolean alice);
/**
* Generates a random invitation code.
*/
int generateInvitationCode();
/**
* Derives two confirmation codes from the given initial shared secret. The
* first code is for Alice to give to Bob; the second is for Bob to give to
* Alice.
*/
int[] deriveConfirmationCodes(byte[] secret);
/**
* Derives a temporary secret for the given period from the previous
* period's temporary secret.
*/
byte[] deriveNextSecret(byte[] secret, long period);
/** Encodes the pseudo-random tag that is used to recognise a connection. */
void encodeTag(byte[] tag, Cipher tagCipher, ErasableKey tagKey,
long connection);
KeyPair generateAgreementKeyPair();
KeyPair generateSignatureKeyPair();
KeyParser getSignatureKeyParser();
ErasableKey generateTestKey();
MessageDigest getMessageDigest();
PseudoRandom getPseudoRandom(int seed);
SecureRandom getSecureRandom();
Cipher getTagCipher();
AuthenticatedCipher getFrameCipher();
Signature getSignature();
}

View File

@@ -0,0 +1,12 @@
package net.sf.briar.api.crypto;
import javax.crypto.SecretKey;
public interface ErasableKey extends SecretKey {
/** Returns a copy of the key. */
ErasableKey copy();
/** Erases the key from memory. */
void erase();
}

View File

@@ -0,0 +1,31 @@
package net.sf.briar.api.crypto;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.db.ContactTransport;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.transport.ConnectionContext;
public interface KeyManager {
/**
* Starts the key manager and returns true if it started successfully. This
* method must be called after the database has been opened.
*/
boolean start();
/** Stops the key manager. */
void stop();
/**
* Returns a connection context for connecting to the given contact over
* the given transport, or null if an error occurs or the contact does not
* support the transport.
*/
ConnectionContext getConnectionContext(ContactId c, TransportId t);
/**
* Called whenever a contact transport has been added. The initial secret
* is erased before returning.
*/
void contactTransportAdded(ContactTransport ct, byte[] initialSecret);
}

View File

@@ -0,0 +1,9 @@
package net.sf.briar.api.crypto;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
public interface KeyParser {
PublicKey parsePublicKey(byte[] encodedKey) throws InvalidKeySpecException;
}

View File

@@ -0,0 +1,29 @@
package net.sf.briar.api.crypto;
/** An interface that allows a java.security.MessageDigest to be wrapped. */
public interface MessageDigest {
/** @see {@link java.security.MessageDigest#digest()} */
byte[] digest();
/** @see {@link java.security.MessageDigest#digest(byte[])} */
byte[] digest(byte[] input);
/** @see {@link java.security.MessageDigest#digest(byte[], int, int)} */
int digest(byte[] buf, int offset, int len);
/** @see {@link java.security.MessageDigest#getDigestLength()} */
int getDigestLength();
/** @see {@link java.security.MessageDigest#reset()} */
void reset();
/** @see {@link java.security.MessageDigest#update(byte)} */
void update(byte input);
/** @see {@link java.security.MessageDigest#update(byte[])} */
void update(byte[] input);
/** @see {@link java.security.MessageDigest#update(byte[], int, int)} */
void update(byte[] input, int offset, int len);
}

View File

@@ -0,0 +1,14 @@
package net.sf.briar.api.crypto;
/**
* Encapsulates a password. Implementations may keep the password encrypted in
* memory to reduce the chances of writing it to the swapfile in plaintext.
*/
public interface Password {
/**
* Returns the password as a character array, which should be filled with
* zeroes as soon as it has been used.
*/
char[] getPassword();
}

View File

@@ -0,0 +1,6 @@
package net.sf.briar.api.crypto;
public interface PseudoRandom {
byte[] nextBytes(int bytes);
}

View File

@@ -0,0 +1,46 @@
package net.sf.briar.api.db;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.protocol.TransportId;
public class ContactTransport {
private final ContactId contactId;
private final TransportId transportId;
private final long epoch, clockDiff, latency;
private final boolean alice;
public ContactTransport(ContactId contactId, TransportId transportId,
long epoch, long clockDiff, long latency, boolean alice) {
this.contactId = contactId;
this.transportId = transportId;
this.epoch = epoch;
this.clockDiff = clockDiff;
this.latency = latency;
this.alice = alice;
}
public ContactId getContactId() {
return contactId;
}
public TransportId getTransportId() {
return transportId;
}
public long getEpoch() {
return epoch;
}
public long getClockDifference() {
return clockDiff;
}
public long getLatency() {
return latency;
}
public boolean getAlice() {
return alice;
}
}

View File

@@ -0,0 +1,223 @@
package net.sf.briar.api.db;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.Rating;
import net.sf.briar.api.TransportConfig;
import net.sf.briar.api.TransportProperties;
import net.sf.briar.api.db.event.DatabaseListener;
import net.sf.briar.api.protocol.Ack;
import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.Batch;
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.Offer;
import net.sf.briar.api.protocol.RawBatch;
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.TransportId;
import net.sf.briar.api.protocol.TransportUpdate;
/**
* Encapsulates the database implementation and exposes high-level operations
* to other components.
*/
public interface DatabaseComponent {
/**
* Opens the database.
* @param resume True to reopen an existing database or false to create a
* new one.
*/
void open(boolean resume) throws DbException, IOException;
/** Waits for any open transactions to finish and closes the database. */
void close() throws DbException, IOException;
/** Adds a listener to be notified when database events occur. */
void addListener(DatabaseListener d);
/** Removes a listener. */
void removeListener(DatabaseListener d);
/**
* Adds a new contact to the database and returns an ID for the contact.
*/
ContactId addContact() throws DbException;
/** Adds a contact transport to the database. */
void addContactTransport(ContactTransport ct) throws DbException;
/** Adds a locally generated group message to the database. */
void addLocalGroupMessage(Message m) throws DbException;
/** Adds a locally generated private message to the database. */
void addLocalPrivateMessage(Message m, ContactId c) throws DbException;
/**
* Stores the given temporary secrets and deletes any secrets that have
* been made obsolete.
*/
void addSecrets(Collection<TemporarySecret> secrets) throws DbException;
/**
* Generates an acknowledgement for the given contact. Returns null if
* there are no batches to acknowledge.
*/
Ack generateAck(ContactId c, int maxBatches) throws DbException;
/**
* Generates a batch of messages for the given contact. Returns null if
* there are no sendable messages that fit in the given capacity.
*/
RawBatch generateBatch(ContactId c, int capacity) throws DbException;
/**
* Generates a batch of messages for the given contact from the given
* collection of requested messages. Any messages that were either added to
* the batch, or were considered but are no longer sendable to the contact,
* are removed from the collection of requested messages before returning.
* Returns null if there are no sendable messages that fit in the given
* capacity.
*/
RawBatch generateBatch(ContactId c, int capacity,
Collection<MessageId> requested) throws DbException;
/**
* Generates an offer for the given contact. Returns null if there are no
* messages to offer.
*/
Offer generateOffer(ContactId c, int maxMessages) throws DbException;
/**
* Generates a subscription update for the given contact. Returns null if
* an update is not due.
*/
SubscriptionUpdate generateSubscriptionUpdate(ContactId c)
throws DbException;
/**
* Generates a transport update for the given contact. Returns null if an
* update is not due.
*/
TransportUpdate generateTransportUpdate(ContactId c) throws DbException;
/** Returns the configuration for the given transport. */
TransportConfig getConfig(TransportId t) throws DbException;
/** Returns the IDs of all contacts. */
Collection<ContactId> getContacts() throws DbException;
/** 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;
/** Returns the user's rating for the given author. */
Rating getRating(AuthorId a) throws DbException;
/** Returns all remote transport properties for the given transport. */
Map<ContactId, TransportProperties> getRemoteProperties(TransportId t)
throws DbException;
/** Returns all temporary secrets. */
Collection<TemporarySecret> getSecrets() throws DbException;
/** Returns the set of groups to which the user subscribes. */
Collection<Group> getSubscriptions() throws DbException;
/** Returns the number of unread messages in each subscribed group. */
Map<GroupId, Integer> getUnreadMessageCounts() throws DbException;
/** Returns the contacts to which the given group is visible. */
Collection<ContactId> getVisibility(GroupId g) throws DbException;
/** Returns true if any messages are sendable to the given contact. */
boolean hasSendableMessages(ContactId c) throws DbException;
/**
* Increments the outgoing connection counter for the given contact
* transport in the given rotation period and returns the old value.
*/
long incrementConnectionCounter(ContactId c, TransportId t, long period)
throws DbException;
/** Processes an acknowledgement from the given contact. */
void receiveAck(ContactId c, Ack a) throws DbException;
/** Processes a batch of messages from the given contact. */
void receiveBatch(ContactId c, Batch b) throws DbException;
/**
* Processes an offer from the given contact and generates a request for
* any messages in the offer that the contact should send. To prevent
* contacts from using offers to test for subscriptions that are not
* visible to them, any messages belonging to groups that are not visible
* to the contact are requested just as though they were not present in the
* database.
*/
Request receiveOffer(ContactId c, Offer o) throws DbException;
/** Processes a subscription update from the given contact. */
void receiveSubscriptionUpdate(ContactId c, SubscriptionUpdate s)
throws DbException;
/** Processes a transport update from the given contact. */
void receiveTransportUpdate(ContactId c, TransportUpdate t)
throws DbException;
/** Removes a contact (and all associated state) from the database. */
void removeContact(ContactId c) throws DbException;
/**
* Sets the configuration for the given transport, replacing any existing
* configuration for that transport.
*/
void setConfig(TransportId t, TransportConfig c) throws DbException;
/**
* Sets the connection reordering window for the given contact transport
* in the given rotation period.
*/
void setConnectionWindow(ContactId c, TransportId t, long period,
long centre, byte[] bitmap) throws DbException;
/**
* Sets the local transport properties for the given transport, replacing
* any existing properties for that transport.
*/
void setLocalProperties(TransportId t, TransportProperties p)
throws DbException;
/** Records the user's rating for the given author. */
void setRating(AuthorId a, Rating r) throws DbException;
/** Records the given messages as having been seen by the given contact. */
void setSeen(ContactId c, Collection<MessageId> seen) throws DbException;
/**
* Makes the given group visible to the given set of contacts and invisible
* to any other contacts.
*/
void setVisibility(GroupId g, Collection<ContactId> visible)
throws DbException;
/** Subscribes to the given group. */
void subscribe(Group g) throws DbException;
/**
* Unsubscribes from the given group. Any messages belonging to the group
* are deleted from the database.
*/
void unsubscribe(GroupId g) throws DbException;
}

View File

@@ -0,0 +1,15 @@
package net.sf.briar.api.db;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
/** Annotation for injecting the directory where the database is stored. */
@BindingAnnotation
@Target({ PARAMETER })
@Retention(RUNTIME)
public @interface DatabaseDirectory {}

View File

@@ -0,0 +1,15 @@
package net.sf.briar.api.db;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
/** Annotation for injecting the executor for database tasks. */
@BindingAnnotation
@Target({ PARAMETER })
@Retention(RUNTIME)
public @interface DatabaseExecutor {}

View File

@@ -0,0 +1,15 @@
package net.sf.briar.api.db;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
/** Annotation for injecting the maximum size in bytes of the database. */
@BindingAnnotation
@Target({ PARAMETER })
@Retention(RUNTIME)
public @interface DatabaseMaxSize {}

View File

@@ -0,0 +1,18 @@
package net.sf.briar.api.db;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
/**
* Annotation for injecting the password from which the database encryption
* key is derived.
*/
@BindingAnnotation
@Target({ PARAMETER })
@Retention(RUNTIME)
public @interface DatabasePassword {}

View File

@@ -0,0 +1,14 @@
package net.sf.briar.api.db;
public class DbException extends Exception {
private static final long serialVersionUID = 3706581789209939441L;
public DbException() {
super();
}
public DbException(Throwable t) {
super(t);
}
}

View File

@@ -0,0 +1,35 @@
package net.sf.briar.api.db;
import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.MessageId;
public interface MessageHeader {
/** Returns the message's unique identifier. */
MessageId getId();
/**
* Returns 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. */
GroupId getGroup();
/** Returns the message's author. */
AuthorId getAuthor();
/** Returns the message's subject line. */
String getSubject();
/** Returns the timestamp created by the message's author. */
long getTimestamp();
/** Returns true if the message has been read. */
boolean getRead();
/** Returns true if the message has been starred. */
boolean getStarred();
}

View File

@@ -0,0 +1,10 @@
package net.sf.briar.api.db;
/**
* Thrown when a database operation is attempted for a contact that is not in
* the database.
*/
public class NoSuchContactException extends DbException {
private static final long serialVersionUID = -7048538231308207386L;
}

View File

@@ -0,0 +1,10 @@
package net.sf.briar.api.db;
/**
* Thrown when a database operation is attempted for a contact transport that
* is not in the database.
*/
public class NoSuchContactTransportException extends DbException {
private static final long serialVersionUID = -6274982612759573100L;
}

View File

@@ -0,0 +1,11 @@
package net.sf.briar.api.db;
/** The status of a message with respect to a particular contact. */
public enum Status {
/** The message has not been sent, received, or acked. */
NEW,
/** The message has been sent, but not received or acked. */
SENT,
/** The message has been received or acked. */
SEEN
}

View File

@@ -0,0 +1,59 @@
package net.sf.briar.api.db;
import static net.sf.briar.api.transport.TransportConstants.CONNECTION_WINDOW_SIZE;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.protocol.TransportId;
public class TemporarySecret extends ContactTransport {
private final long period, outgoing, centre;
private final byte[] secret, bitmap;
/** Creates a temporary secret with the given connection window. */
public TemporarySecret(ContactId contactId, TransportId transportId,
long epoch, long clockDiff, long latency, boolean alice,
long period, byte[] secret, long outgoing, long centre,
byte[] bitmap) {
super(contactId, transportId, epoch, clockDiff, latency, alice);
this.period = period;
this.secret = secret;
this.outgoing = outgoing;
this.centre = centre;
this.bitmap = bitmap;
}
/** Creates a temporary secret with a new connection window. */
public TemporarySecret(ContactId contactId, TransportId transportId,
long epoch, long clockDiff, long latency, boolean alice,
long period, byte[] secret) {
this(contactId, transportId, epoch, clockDiff, latency, alice, period,
secret, 0L, 0L, new byte[CONNECTION_WINDOW_SIZE / 8]);
}
/** Creates a temporary secret derived from the given contact transport. */
public TemporarySecret(ContactTransport ct, long period, byte[] secret) {
this(ct.getContactId(), ct.getTransportId(), ct.getEpoch(),
ct.getClockDifference(), ct.getLatency(), ct.getAlice(),
period, secret);
}
public long getPeriod() {
return period;
}
public byte[] getSecret() {
return secret;
}
public long getOutgoingConnectionCounter() {
return outgoing;
}
public long getWindowCentre() {
return centre;
}
public byte[] getWindowBitmap() {
return bitmap;
}
}

View File

@@ -0,0 +1,6 @@
package net.sf.briar.api.db.event;
/** An event that is broadcast when a batch of messages is received. */
public class BatchReceivedEvent extends DatabaseEvent {
}

View File

@@ -0,0 +1,17 @@
package net.sf.briar.api.db.event;
import net.sf.briar.api.ContactId;
/** An event that is broadcast when a contact is added. */
public class ContactAddedEvent extends DatabaseEvent {
private final ContactId contactId;
public ContactAddedEvent(ContactId contactId) {
this.contactId = contactId;
}
public ContactId getContactId() {
return contactId;
}
}

View File

@@ -0,0 +1,17 @@
package net.sf.briar.api.db.event;
import net.sf.briar.api.ContactId;
/** An event that is broadcast when a contact is removed. */
public class ContactRemovedEvent extends DatabaseEvent {
private final ContactId contactId;
public ContactRemovedEvent(ContactId contactId) {
this.contactId = contactId;
}
public ContactId getContactId() {
return contactId;
}
}

View File

@@ -0,0 +1,6 @@
package net.sf.briar.api.db.event;
/** An abstract superclass for database events. */
public abstract class DatabaseEvent {
}

View File

@@ -0,0 +1,7 @@
package net.sf.briar.api.db.event;
/** An interface for receiving notifications when database events occur. */
public interface DatabaseListener {
void eventOccurred(DatabaseEvent e);
}

View File

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

View File

@@ -0,0 +1,9 @@
package net.sf.briar.api.db.event;
/**
* An event that is broadcast when one or more messages are added to the
* database.
*/
public class MessagesAddedEvent extends DatabaseEvent {
}

View File

@@ -0,0 +1,23 @@
package net.sf.briar.api.db.event;
import net.sf.briar.api.Rating;
import net.sf.briar.api.protocol.AuthorId;
public class RatingChangedEvent extends DatabaseEvent {
private final AuthorId author;
private final Rating rating;
public RatingChangedEvent(AuthorId author, Rating rating) {
this.author = author;
this.rating = rating;
}
public AuthorId getAuthor() {
return author;
}
public Rating getRating() {
return rating;
}
}

View File

@@ -0,0 +1,27 @@
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

@@ -0,0 +1,28 @@
package net.sf.briar.api.db.event;
import java.util.Collection;
import java.util.Collections;
import net.sf.briar.api.ContactId;
/**
* An event that is broadcast when the set of subscriptions visible to one or
* more contacts is updated.
*/
public class SubscriptionsUpdatedEvent extends DatabaseEvent {
private final Collection<ContactId> affectedContacts;
public SubscriptionsUpdatedEvent() {
affectedContacts = Collections.emptyList();
}
public SubscriptionsUpdatedEvent(Collection<ContactId> affectedContacts) {
this.affectedContacts = affectedContacts;
}
/** Returns the contacts affected by the update. */
public Collection<ContactId> getAffectedContacts() {
return affectedContacts;
}
}

View File

@@ -0,0 +1,23 @@
package net.sf.briar.api.i18n;
import java.awt.Font;
import java.io.File;
import java.util.Locale;
public interface FontManager {
/**
* Initializes the FontManager for the given locale. Fonts are loaded from
* the given directory if they cannot be loaded from the running jar.
*/
void initialize(Locale locale, File dir);
/** Returns the appropriate font for the given language. */
Font getFontForLanguage(String language);
/** Returns the current user interface font. */
Font getUiFont();
/** Sets the user interface font appropriately for the given language. */
void setUiFontForLanguage(String language);
}

View File

@@ -0,0 +1,53 @@
package net.sf.briar.api.i18n;
import java.awt.ComponentOrientation;
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
public interface I18n {
/** Returns the named string, translated for the current i18n locale. */
String tr(String name);
/** Returns the i18n locale. This may not match the system locale. */
Locale getLocale();
/** Sets the i18n locale. */
void setLocale(Locale locale);
/** Loads the i18n locale from Briar/Data/locale.cfg. */
void loadLocale() throws IOException;
/** Saves the i18n locale to Briar/Data/locale.cfg. */
void saveLocale() throws IOException;
/** Loads the i18n locale from the given file. */
void loadLocale(File f) throws IOException;
/** Saves the i18n locale to the given file. */
void saveLocale(File f) throws IOException;
/** Returns the ComponentOrientation of the current i18n locale. */
ComponentOrientation getComponentOrientation();
/** Registers a listener for changes to the i18n locale. */
void addListener(Listener l);
/** Unregisters a listener for changes to the i18n locale. */
void removeListener(Listener l);
/**
* Implemented by classes that wish to be informed of changes to the i18n
* locale.
*/
public interface Listener {
/**
* Called whenever the i18n locale changes.
* @param uiFont The user interface font for the new locale.
*/
void localeChanged(Font uiFont);
}
}

View File

@@ -0,0 +1,49 @@
package net.sf.briar.api.i18n;
/** A named translatable string. */
public class Stri18ng {
private static final String HTML_OPEN_LEFT = "<html><body align='left'>";
private static final String HTML_OPEN_RIGHT = "<html><body align='right'>";
private static final String HTML_CLOSE = "</body></html>";
private static final String PARAGRAPH = "<p><p>"; // Yes, two of them
private final String name;
private final I18n i18n;
public Stri18ng(String name, I18n i18n) {
this.name = name;
this.i18n = i18n;
}
/** Returns the string translated for the current i18n locale. */
public String tr() {
return i18n.tr(name);
}
/** Returns the string, translated for the current i18n locale, as HTML. */
public String html() {
if(i18n.getComponentOrientation().isLeftToRight())
return HTML_OPEN_LEFT + i18n.tr(name) + HTML_CLOSE;
else return HTML_OPEN_RIGHT + i18n.tr(name) + HTML_CLOSE;
}
/**
* Returns the string, translated for the current locale, as HTML.
* @param paras Additional (pre-translated) paragraphs that should be
* appended to the HTML.
*/
public String html(String... paras) {
StringBuilder s = new StringBuilder();
if(i18n.getComponentOrientation().isLeftToRight())
s.append(HTML_OPEN_LEFT);
else s.append(HTML_OPEN_RIGHT);
s.append(tr());
for(String para : paras) {
s.append(PARAGRAPH);
s.append(para);
}
s.append(HTML_CLOSE);
return s.toString();
}
}

View File

@@ -0,0 +1,16 @@
package net.sf.briar.api.lifecycle;
public interface ShutdownManager {
/**
* Registers a hook to be run when the JVM shuts down and returns a handle
* that can be used to remove the hook.
*/
int addShutdownHook(Runnable hook);
/**
* Removes the shutdown hook identified by the given handle and returns
* true if the hook was removed.
*/
boolean removeShutdownHook(int handle);
}

View File

@@ -0,0 +1,14 @@
package net.sf.briar.api.plugins;
public interface InvitationConstants {
long INVITATION_TIMEOUT = 60 * 1000; // 1 minute
int CODE_BITS = 19; // Codes must fit into six decimal digits
int MAX_CODE = 1 << CODE_BITS - 1;
int HASH_LENGTH = 48;
int MAX_PUBLIC_KEY_LENGTH = 120;
}

View File

@@ -0,0 +1,38 @@
package net.sf.briar.api.plugins;
import java.io.IOException;
import java.util.Collection;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.protocol.TransportId;
public interface Plugin {
/** Returns the plugin's transport identifier. */
TransportId getId();
/** Starts the plugin. */
void start() throws IOException;
/** Stops the plugin. */
void stop() throws IOException;
/**
* Returns true if the plugin's poll() method should be called
* periodically to attempt to establish connections.
*/
boolean shouldPoll();
/**
* Returns the desired interval in milliseconds between calls to the
* plugin's poll() method.
*/
long getPollingInterval();
/**
* Attempts to establish connections to contacts, passing any created
* connections to the callback. To avoid creating redundant connections,
* the plugin may exclude the given contacts from polling.
*/
void poll(Collection<ContactId> connected);
}

View File

@@ -0,0 +1,50 @@
package net.sf.briar.api.plugins;
import java.util.Map;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportConfig;
import net.sf.briar.api.TransportProperties;
/**
* An interface through which a transport plugin interacts with the rest of
* the application.
*/
public interface PluginCallback {
/** Returns the plugin's configuration. */
TransportConfig getConfig();
/** Returns the plugin's local transport properties. */
TransportProperties getLocalProperties();
/** Returns the plugin's remote transport properties. */
Map<ContactId, TransportProperties> getRemoteProperties();
/** Stores the plugin's configuration. */
void setConfig(TransportConfig c);
/** Stores the plugin's local transport properties. */
void setLocalProperties(TransportProperties p);
/**
* Presents the user with a choice among two or more named options and
* returns the user's response. The message may consist of a translatable
* format string and arguments.
* @return An index into the array of options indicating the user's choice,
* or -1 if the user cancelled the choice.
*/
int showChoice(String[] options, String... message);
/**
* Asks the user to confirm an action and returns the user's response. The
* message may consist of a translatable format string and arguments.
*/
boolean showConfirmationMessage(String... message);
/**
* Shows a message to the user. The message may consist of a translatable
* format string and arguments.
*/
void showMessage(String... message);
}

View File

@@ -0,0 +1,15 @@
package net.sf.briar.api.plugins;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
/** Annotation for injecting the executor used by transport plugins. */
@BindingAnnotation
@Target({ PARAMETER })
@Retention(RUNTIME)
public @interface PluginExecutor {}

View File

@@ -0,0 +1,23 @@
package net.sf.briar.api.plugins;
import java.util.Collection;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
public interface PluginManager {
/**
* Starts the plugins and returns the number of plugins successfully
* started. This method must not be called until the database has been
* opened.
*/
int start();
/**
* Stops the plugins and returns the number of plugins successfully stopped.
*/
int stop();
/** Returns any duplex plugins that support invitations. */
Collection<DuplexPlugin> getInvitationPlugins();
}

View File

@@ -0,0 +1,31 @@
package net.sf.briar.api.plugins.duplex;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.crypto.PseudoRandom;
import net.sf.briar.api.plugins.Plugin;
/** An interface for transport plugins that support duplex communication. */
public interface DuplexPlugin extends Plugin {
/**
* Attempts to create and return a connection to the given contact using
* the current transport and configuration properties. Returns null if a
* connection could not be created.
*/
DuplexTransportConnection createConnection(ContactId c);
/** Returns true if the plugin supports exchanging invitations. */
boolean supportsInvitations();
/**
* Starts the invitation process from the inviter's side. Returns null if
* no connection can be established within the given timeout.
*/
DuplexTransportConnection sendInvitation(PseudoRandom r, long timeout);
/**
* Starts the invitation process from the invitee's side. Returns null if
* no connection can be established within the given timeout.
*/
DuplexTransportConnection acceptInvitation(PseudoRandom r, long timeout);
}

View File

@@ -0,0 +1,14 @@
package net.sf.briar.api.plugins.duplex;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.plugins.PluginCallback;
/**
* An interface for handling connections created by a duplex transport plugin.
*/
public interface DuplexPluginCallback extends PluginCallback {
void incomingConnectionCreated(DuplexTransportConnection d);
void outgoingConnectionCreated(ContactId c, DuplexTransportConnection d);
}

View File

@@ -0,0 +1,9 @@
package net.sf.briar.api.plugins.duplex;
import java.util.concurrent.Executor;
public interface DuplexPluginFactory {
DuplexPlugin createPlugin(Executor pluginExecutor,
DuplexPluginCallback callback);
}

View File

@@ -0,0 +1,32 @@
package net.sf.briar.api.plugins.duplex;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* An interface for reading and writing data over a duplex transport. The
* connection is not responsible for encrypting/decrypting or authenticating
* the data.
*/
public interface DuplexTransportConnection {
/** Returns an input stream for reading from the connection. */
InputStream getInputStream() throws IOException;
/** Returns an output stream for writing to the connection. */
OutputStream getOutputStream() throws IOException;
/**
* Returns true if the output stream should be flushed after each packet.
*/
boolean shouldFlush();
/**
* Closes the connection and disposes of any associated resources. The
* first argument indicates whether the connection is being closed because
* of an exception and the second argument indicates whether the connection
* was recognised, which may affect how resources are disposed of.
*/
void dispose(boolean exception, boolean recognised) throws IOException;
}

View File

@@ -0,0 +1,22 @@
package net.sf.briar.api.plugins.simplex;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.plugins.Plugin;
/** An interface for transport plugins that support simplex communication. */
public interface SimplexPlugin extends Plugin {
/**
* Attempts to create and return a reader for the given contact using the
* current transport and configuration properties. Returns null if a reader
* could not be created.
*/
SimplexTransportReader createReader(ContactId c);
/**
* Attempts to create and return a writer for the given contact using the
* current transport and configuration properties. Returns null if a writer
* could not be created.
*/
SimplexTransportWriter createWriter(ContactId c);
}

View File

@@ -0,0 +1,15 @@
package net.sf.briar.api.plugins.simplex;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.plugins.PluginCallback;
/**
* An interface for handling readers and writers created by a simplex transport
* plugin.
*/
public interface SimplexPluginCallback extends PluginCallback {
void readerCreated(SimplexTransportReader r);
void writerCreated(ContactId c, SimplexTransportWriter w);
}

View File

@@ -0,0 +1,9 @@
package net.sf.briar.api.plugins.simplex;
import java.util.concurrent.Executor;
public interface SimplexPluginFactory {
SimplexPlugin createPlugin(Executor pluginExecutor,
SimplexPluginCallback callback);
}

View File

@@ -0,0 +1,23 @@
package net.sf.briar.api.plugins.simplex;
import java.io.IOException;
import java.io.InputStream;
/**
* An interface for reading data from a simplex transport. The reader is not
* responsible for decrypting or authenticating the data before returning it.
*/
public interface SimplexTransportReader {
/** Returns an input stream for reading from the transport.
* @throws IOException */
InputStream getInputStream() throws IOException;
/**
* Closes the reader and disposes of any associated resources. The first
* argument indicates whether the reader is being closed because of an
* exception and the second argument indicates whether the connection was
* recognised, which may affect how resources are disposed of.
*/
void dispose(boolean exception, boolean recognised) throws IOException;
}

View File

@@ -0,0 +1,30 @@
package net.sf.briar.api.plugins.simplex;
import java.io.IOException;
import java.io.OutputStream;
/**
* An interface for writing data to a simplex transport. The writer is not
* responsible for authenticating or encrypting the data before writing it.
*/
public interface SimplexTransportWriter {
/** Returns the capacity of the transport in bytes. */
long getCapacity();
/** Returns an output stream for writing to the transport.
* @throws IOException */
OutputStream getOutputStream() throws IOException;
/**
* Returns true if the output stream should be flushed after each packet.
*/
boolean shouldFlush();
/**
* Closes the writer and disposes of any associated resources. The
* argument indicates whether the writer is being closed because of an
* exception, which may affect how resources are disposed of.
*/
void dispose(boolean exception) throws IOException;
}

View File

@@ -0,0 +1,10 @@
package net.sf.briar.api.protocol;
import java.util.Collection;
/** A packet acknowledging receipt of one or more batches. */
public interface Ack {
/** Returns the IDs of the acknowledged batches. */
Collection<BatchId> getBatchIds();
}

View File

@@ -0,0 +1,17 @@
package net.sf.briar.api.protocol;
/** A pseudonymous author of messages. */
public interface Author {
/** Returns the author's unique identifier. */
AuthorId getId();
/** Returns the author's name. */
String getName();
/**
* Returns the public key that is used to verify messages signed by the
* author.
*/
byte[] getPublicKey();
}

View File

@@ -0,0 +1,10 @@
package net.sf.briar.api.protocol;
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

@@ -0,0 +1,18 @@
package net.sf.briar.api.protocol;
import java.util.Arrays;
/** Type-safe wrapper for a byte array that uniquely identifies an author. */
public class AuthorId extends UniqueId {
public AuthorId(byte[] id) {
super(id);
}
@Override
public boolean equals(Object o) {
if(o instanceof AuthorId)
return Arrays.equals(id, ((AuthorId) o).id);
return false;
}
}

View File

@@ -0,0 +1,13 @@
package net.sf.briar.api.protocol;
import java.util.Collection;
/** An incoming packet containing messages. */
public interface Batch {
/** Returns the batch's unique identifier. */
BatchId getId();
/** Returns the messages contained in the batch. */
Collection<Message> getMessages();
}

View File

@@ -0,0 +1,21 @@
package net.sf.briar.api.protocol;
import java.util.Arrays;
/**
* Type-safe wrapper for a byte array that uniquely identifies a batch of
* messages.
*/
public class BatchId extends UniqueId {
public BatchId(byte[] id) {
super(id);
}
@Override
public boolean equals(Object o) {
if(o instanceof BatchId)
return Arrays.equals(id, ((BatchId) o).id);
return false;
}
}

View File

@@ -0,0 +1,17 @@
package net.sf.briar.api.protocol;
/** A group to which users may subscribe. */
public interface Group {
/** Returns the group's unique identifier. */
GroupId getId();
/** Returns the group's name. */
String getName();
/**
* If the group is restricted, returns the public key that is used to
* authorise all messages sent to the group. Otherwise returns null.
*/
byte[] getPublicKey();
}

View File

@@ -0,0 +1,10 @@
package net.sf.briar.api.protocol;
import java.io.IOException;
public interface GroupFactory {
Group createGroup(String name, byte[] publicKey) throws IOException;
Group createGroup(GroupId id, String name, byte[] publicKey);
}

View File

@@ -0,0 +1,21 @@
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.
*/
public class GroupId extends UniqueId {
public GroupId(byte[] id) {
super(id);
}
@Override
public boolean equals(Object o) {
if(o instanceof GroupId)
return Arrays.equals(id, ((GroupId) o).id);
return false;
}
}

View File

@@ -0,0 +1,34 @@
package net.sf.briar.api.protocol;
public interface Message {
/** Returns the message's unique identifier. */
MessageId getId();
/**
* Returns 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. */
GroupId getGroup();
/** Returns the message's author. */
AuthorId getAuthor();
/** Returns the message's subject line. */
String getSubject();
/** Returns the timestamp created by the message's author. */
long getTimestamp();
/** Returns the serialised message. */
byte[] getSerialised();
/** Returns the offset of the message body within the serialised message. */
int getBodyStart();
/** Returns the length of the message body in bytes. */
int getBodyLength();
}

View File

@@ -0,0 +1,31 @@
package net.sf.briar.api.protocol;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
public interface MessageFactory {
/** Creates a private message. */
Message createMessage(MessageId parent, String subject, byte[] body)
throws IOException, GeneralSecurityException;
/** Creates an anonymous message to an unrestricted group. */
Message createMessage(MessageId parent, Group group, String subject,
byte[] body) throws IOException, GeneralSecurityException;
/** Creates an anonymous message to a restricted group. */
Message createMessage(MessageId parent, Group group, PrivateKey groupKey,
String subject, byte[] body) throws IOException,
GeneralSecurityException;
/** Creates a pseudonymous message to an unrestricted group. */
Message createMessage(MessageId parent, Group group, Author author,
PrivateKey authorKey, String subject, byte[] body)
throws IOException, GeneralSecurityException;
/** Creates a pseudonymous message to a restricted group. */
Message createMessage(MessageId parent, Group group, PrivateKey groupKey,
Author author, PrivateKey authorKey, String subject, byte[] body)
throws IOException, GeneralSecurityException;
}

View File

@@ -0,0 +1,18 @@
package net.sf.briar.api.protocol;
import java.util.Arrays;
/** Type-safe wrapper for a byte array that uniquely identifies a message. */
public class MessageId extends UniqueId {
public MessageId(byte[] id) {
super(id);
}
@Override
public boolean equals(Object o) {
if(o instanceof MessageId)
return Arrays.equals(id, ((MessageId) o).id);
return false;
}
}

View File

@@ -0,0 +1,10 @@
package net.sf.briar.api.protocol;
import java.util.Collection;
/** A packet offering the recipient some messages. */
public interface Offer {
/** Returns the message IDs contained in the offer. */
Collection<MessageId> getMessageIds();
}

View File

@@ -0,0 +1,22 @@
package net.sf.briar.api.protocol;
import java.util.BitSet;
import java.util.Collection;
import java.util.Map;
public interface PacketFactory {
Ack createAck(Collection<BatchId> acked);
RawBatch createBatch(Collection<byte[]> messages);
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

@@ -0,0 +1,47 @@
package net.sf.briar.api.protocol;
import static net.sf.briar.api.transport.TransportConstants.MIN_CONNECTION_LENGTH;
public interface ProtocolConstants {
/**
* The maximum length of a serialised packet in bytes. To allow for future
* changes in the protocol, this is smaller than the minimum connection
* length minus the maximum encryption and authentication overhead.
*/
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;
/** The maximum length of a property's key or value in UTF-8 bytes. */
int MAX_PROPERTY_LENGTH = 100;
/** The maximum length of a group's name in UTF-8 bytes. */
int MAX_GROUP_NAME_LENGTH = 50;
/** The maximum length of a public key in bytes. */
int MAX_PUBLIC_KEY_LENGTH = 120;
/** The maximum length of an author's name in UTF-8 bytes. */
int MAX_AUTHOR_NAME_LENGTH = 50;
/**
* The maximum length of a message body in bytes. To allow for future
* changes in the protocol, this is smaller than the maximum packet length
* even when all the message's other fields have their maximum lengths.
*/
int MAX_BODY_LENGTH = MAX_PACKET_LENGTH - 1024;
/** The maximum length of a message's subject line in UTF-8 bytes. */
int MAX_SUBJECT_LENGTH = 100;
/** The maximum length of a signature in bytes. */
int MAX_SIGNATURE_LENGTH = 120;
/** The length of a message's random salt in bytes. */
int SALT_LENGTH = 8;
}

View File

@@ -0,0 +1,26 @@
package net.sf.briar.api.protocol;
import java.io.IOException;
public interface ProtocolReader {
boolean eof() throws IOException;
boolean hasAck() throws IOException;
Ack readAck() throws IOException;
boolean hasBatch() throws IOException;
UnverifiedBatch readBatch() throws IOException;
boolean hasOffer() throws IOException;
Offer readOffer() throws IOException;
boolean hasRequest() throws IOException;
Request readRequest() throws IOException;
boolean hasSubscriptionUpdate() throws IOException;
SubscriptionUpdate readSubscriptionUpdate() throws IOException;
boolean hasTransportUpdate() throws IOException;
TransportUpdate readTransportUpdate() throws IOException;
}

View File

@@ -0,0 +1,8 @@
package net.sf.briar.api.protocol;
import java.io.InputStream;
public interface ProtocolReaderFactory {
ProtocolReader createProtocolReader(InputStream in);
}

View File

@@ -0,0 +1,28 @@
package net.sf.briar.api.protocol;
import java.io.IOException;
public interface ProtocolWriter {
int getMaxBatchesForAck(long capacity);
int getMaxMessagesForOffer(long capacity);
int getMessageCapacityForBatch(long capacity);
void writeAck(Ack a) throws IOException;
void writeBatch(RawBatch b) throws IOException;
void writeOffer(Offer o) throws IOException;
void writeRequest(Request r) throws IOException;
void writeSubscriptionUpdate(SubscriptionUpdate s) throws IOException;
void writeTransportUpdate(TransportUpdate t) throws IOException;
void flush() throws IOException;
void close() throws IOException;
}

View File

@@ -0,0 +1,8 @@
package net.sf.briar.api.protocol;
import java.io.OutputStream;
public interface ProtocolWriterFactory {
ProtocolWriter createProtocolWriter(OutputStream out, boolean flush);
}

View File

@@ -0,0 +1,13 @@
package net.sf.briar.api.protocol;
import java.util.Collection;
/** An outgoing packet containing messages. */
public interface RawBatch {
/** Returns the batch's unique identifier. */
BatchId getId();
/** Returns the serialised messages contained in the batch. */
Collection<byte[]> getMessages();
}

View File

@@ -0,0 +1,16 @@
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 {
/**
* 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();
/** Returns the length of the bitmap in bits. */
int getLength();
}

View File

@@ -0,0 +1,25 @@
package net.sf.briar.api.protocol;
import java.util.Map;
/** A packet updating the sender's subscriptions. */
public interface SubscriptionUpdate {
/** Returns the holes contained in the update. */
Map<GroupId, GroupId> getHoles();
/** Returns the subscriptions contained in the update. */
Map<Group, Long> getSubscriptions();
/**
* Returns the expiry time of the contact's database. Messages that are
* older than the expiry time must not be sent to the contact.
*/
long getExpiryTime();
/**
* Returns the update's timestamp. Updates that are older than the newest
* update received from the same contact must be ignored.
*/
long getTimestamp();
}

View File

@@ -0,0 +1,39 @@
package net.sf.briar.api.protocol;
import java.util.Map;
import java.util.TreeMap;
public class Transport extends TreeMap<String, String> {
private static final long serialVersionUID = 4900420175715429560L;
private final TransportId id;
public Transport(TransportId id, Map<String, String> p) {
super(p);
this.id = id;
}
public Transport(TransportId id) {
super();
this.id = id;
}
public TransportId getId() {
return id;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals(Object o) {
if(o instanceof Transport) {
Transport t = (Transport) o;
return id.equals(t.id) && super.equals(o);
}
return false;
}
}

View File

@@ -0,0 +1,21 @@
package net.sf.briar.api.protocol;
import java.util.Arrays;
/**
* Type-safe wrapper for a byte array that uniquely identifies a transport
* plugin.
*/
public class TransportId extends UniqueId {
public TransportId(byte[] id) {
super(id);
}
@Override
public boolean equals(Object o) {
if(o instanceof TransportId)
return Arrays.equals(id, ((TransportId) o).id);
return false;
}
}

View File

@@ -0,0 +1,16 @@
package net.sf.briar.api.protocol;
import java.util.Collection;
/** A packet updating the sender's transport properties. */
public interface TransportUpdate {
/** Returns the transports contained in the update. */
Collection<Transport> getTransports();
/**
* Returns the update's timestamp. Updates that are older than the newest
* update received from the same contact must be ignored.
*/
long getTimestamp();
}

View File

@@ -0,0 +1,16 @@
package net.sf.briar.api.protocol;
/** Struct identifiers for encoding and decoding protocol objects. */
public interface Types {
int ACK = 0;
int AUTHOR = 1;
int BATCH = 2;
int GROUP = 3;
int MESSAGE = 4;
int OFFER = 5;
int REQUEST = 6;
int SUBSCRIPTION_UPDATE = 7;
int TRANSPORT = 8;
int TRANSPORT_UPDATE = 9;
}

View File

@@ -0,0 +1,30 @@
package net.sf.briar.api.protocol;
import java.util.Arrays;
public abstract class UniqueId {
/** The length of a unique identifier in bytes. */
public static final int LENGTH = 48;
protected final byte[] id;
private int hashCode = -1;
protected UniqueId(byte[] id) {
if(id.length != LENGTH) throw new IllegalArgumentException();
this.id = id;
}
public byte[] getBytes() {
return id;
}
@Override
public int hashCode() {
// Thread-safe because if two or more threads check and update the
// value, they'll calculate the same value
if(hashCode == -1) hashCode = Arrays.hashCode(id);
return hashCode;
}
}

View File

@@ -0,0 +1,8 @@
package net.sf.briar.api.protocol;
import java.security.GeneralSecurityException;
public interface UnverifiedBatch {
Batch verify() throws GeneralSecurityException;
}

View File

@@ -0,0 +1,15 @@
package net.sf.briar.api.protocol;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
/** Annotation for injecting the executor for message verification tasks. */
@BindingAnnotation
@Target({ PARAMETER })
@Retention(RUNTIME)
public @interface VerificationExecutor {}

View File

@@ -0,0 +1,14 @@
package net.sf.briar.api.protocol.duplex;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.transport.ConnectionContext;
public interface DuplexConnectionFactory {
void createIncomingConnection(ConnectionContext ctx, DuplexTransportConnection d);
void createOutgoingConnection(ContactId c, TransportId t,
DuplexTransportConnection d);
}

View File

@@ -0,0 +1,15 @@
package net.sf.briar.api.protocol.simplex;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
import net.sf.briar.api.protocol.TransportId;
import net.sf.briar.api.transport.ConnectionContext;
public interface SimplexConnectionFactory {
void createIncomingConnection(ConnectionContext ctx, SimplexTransportReader r);
void createOutgoingConnection(ContactId c, TransportId t,
SimplexTransportWriter w);
}

View File

@@ -0,0 +1,10 @@
package net.sf.briar.api.serial;
import java.io.IOException;
public interface Consumer {
void write(byte b) throws IOException;
void write(byte[] b, int off, int len) throws IOException;
}

View File

@@ -0,0 +1,22 @@
package net.sf.briar.api.serial;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/** A consumer that makes a copy of the bytes consumed. */
public class CopyingConsumer implements Consumer {
private final ByteArrayOutputStream out = new ByteArrayOutputStream();
public byte[] getCopy() {
return out.toByteArray();
}
public void write(byte b) throws IOException {
out.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
}
}

View File

@@ -0,0 +1,33 @@
package net.sf.briar.api.serial;
import java.io.IOException;
import net.sf.briar.api.FormatException;
/**
* A consumer that counts the number of bytes consumed and throws a
* FormatException if the count exceeds a given limit.
*/
public class CountingConsumer implements Consumer {
private final long limit;
private long count = 0L;
public CountingConsumer(long limit) {
this.limit = limit;
}
public long getCount() {
return count;
}
public void write(byte b) throws IOException {
count++;
if(count > limit) throw new FormatException();
}
public void write(byte[] b, int off, int len) throws IOException {
count += len;
if(count > limit) throw new FormatException();
}
}

View File

@@ -0,0 +1,21 @@
package net.sf.briar.api.serial;
import net.sf.briar.api.crypto.MessageDigest;
/** A consumer that passes its input through a message digest. */
public class DigestingConsumer implements Consumer {
private final MessageDigest messageDigest;
public DigestingConsumer(MessageDigest messageDigest) {
this.messageDigest = messageDigest;
}
public void write(byte b) {
messageDigest.update(b);
}
public void write(byte[] b, int off, int len) {
messageDigest.update(b, off, len);
}
}

View File

@@ -0,0 +1,73 @@
package net.sf.briar.api.serial;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public interface Reader {
boolean eof() throws IOException;
void close() throws IOException;
void setMaxStringLength(int length);
void resetMaxStringLength();
void setMaxBytesLength(int length);
void resetMaxBytesLength();
void addConsumer(Consumer c);
void removeConsumer(Consumer c);
void addStructReader(int id, StructReader<?> o);
void removeStructReader(int id);
boolean hasBoolean() throws IOException;
boolean readBoolean() throws IOException;
boolean hasUint7() throws IOException;
byte readUint7() throws IOException;
boolean hasInt8() throws IOException;
byte readInt8() throws IOException;
boolean hasInt16() throws IOException;
short readInt16() throws IOException;
boolean hasInt32() throws IOException;
int readInt32() throws IOException;
boolean hasInt64() throws IOException;
long readInt64() throws IOException;
boolean hasIntAny() throws IOException;
long readIntAny() throws IOException;
boolean hasFloat32() throws IOException;
float readFloat32() throws IOException;
boolean hasFloat64() throws IOException;
double readFloat64() throws IOException;
boolean hasString() throws IOException;
String readString() throws IOException;
String readString(int maxLength) throws IOException;
boolean hasBytes() throws IOException;
byte[] readBytes() throws IOException;
byte[] readBytes(int maxLength) throws IOException;
boolean hasList() throws IOException;
<E> List<E> readList(Class<E> e) throws IOException;
boolean hasListStart() throws IOException;
void readListStart() throws IOException;
boolean hasListEnd() throws IOException;
void readListEnd() throws IOException;
boolean hasMap() throws IOException;
<K, V> Map<K, V> readMap(Class<K> k, Class<V> v) throws IOException;
boolean hasMapStart() throws IOException;
void readMapStart() throws IOException;
boolean hasMapEnd() throws IOException;
void readMapEnd() throws IOException;
boolean hasNull() throws IOException;
void readNull() throws IOException;
boolean hasStruct(int id) throws IOException;
<T> T readStruct(int id, Class<T> t) throws IOException;
void readStructId(int id) throws IOException;
}

View File

@@ -0,0 +1,8 @@
package net.sf.briar.api.serial;
import java.io.InputStream;
public interface ReaderFactory {
Reader createReader(InputStream in);
}

View File

@@ -0,0 +1,12 @@
package net.sf.briar.api.serial;
public interface SerialComponent {
int getSerialisedListEndLength();
int getSerialisedListStartLength();
int getSerialisedStructIdLength(int id);
int getSerialisedUniqueIdLength();
}

View File

@@ -0,0 +1,31 @@
package net.sf.briar.api.serial;
import java.io.IOException;
import java.security.Signature;
import java.security.SignatureException;
/** A consumer that passes its input through a signature. */
public class SigningConsumer implements Consumer {
private final Signature signature;
public SigningConsumer(Signature signature) {
this.signature = signature;
}
public void write(byte b) throws IOException {
try {
signature.update(b);
} catch(SignatureException e) {
throw new IOException(e.toString());
}
}
public void write(byte[] b, int off, int len) throws IOException {
try {
signature.update(b, off, len);
} catch(SignatureException e) {
throw new IOException(e.toString());
}
}
}

View File

@@ -0,0 +1,8 @@
package net.sf.briar.api.serial;
import java.io.IOException;
public interface StructReader<T> {
T readStruct(Reader r) throws IOException;
}

View File

@@ -0,0 +1,38 @@
package net.sf.briar.api.serial;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
public interface Writer {
void addConsumer(Consumer c);
void removeConsumer(Consumer c);
void writeBoolean(boolean b) throws IOException;
void writeUint7(byte b) throws IOException;
void writeInt8(byte b) throws IOException;
void writeInt16(short s) throws IOException;
void writeInt32(int i) throws IOException;
void writeInt64(long l) throws IOException;
void writeIntAny(long l) throws IOException;
void writeFloat32(float f) throws IOException;
void writeFloat64(double d) throws IOException;
void writeString(String s) throws IOException;
void writeBytes(byte[] b) throws IOException;
void writeList(Collection<?> c) throws IOException;
void writeListStart() throws IOException;
void writeListEnd() throws IOException;
void writeMap(Map<?, ?> m) throws IOException;
void writeMapStart() throws IOException;
void writeMapEnd() throws IOException;
void writeNull() throws IOException;
void writeStructId(int id) throws IOException;
}

View File

@@ -0,0 +1,8 @@
package net.sf.briar.api.serial;
import java.io.OutputStream;
public interface WriterFactory {
Writer createWriter(OutputStream out);
}

Some files were not shown because too many files have changed in this diff Show More