Separated Android code and core code into distinct Eclipse projects.

This should make it possible to develop the core in Eclipse without the ADT.
This commit is contained in:
akwizgran
2012-12-05 20:39:31 +00:00
parent 366d391d89
commit f4f7b96d50
345 changed files with 43 additions and 19 deletions

23
briar-core/.classpath Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="lib" path="libs/activation.jar"/>
<classpathentry kind="lib" path="libs/bluecove-2.1.0-briar.jar"/>
<classpathentry kind="lib" path="libs/bluecove-gpl-2.1.0.jar"/>
<classpathentry kind="lib" path="libs/commons-io-2.0.1.jar"/>
<classpathentry kind="lib" path="libs/guice-3.0-no_aop.jar"/>
<classpathentry kind="lib" path="libs/h2small-1.3.161.jar"/>
<classpathentry kind="lib" path="libs/javax.inject.jar"/>
<classpathentry kind="lib" path="libs/jna-3.5.1.jar"/>
<classpathentry kind="lib" path="libs/jnotify-0.93.jar"/>
<classpathentry kind="lib" path="libs/jssc-0.9-briar.jar"/>
<classpathentry kind="lib" path="libs/platform-3.5.1.jar"/>
<classpathentry kind="lib" path="libs/sc-light-jdk15on-1.47.0.3-SNAPSHOT.jar"/>
<classpathentry kind="lib" path="libs/scpkix-jdk15on-1.47.0.3-SNAPSHOT.jar"/>
<classpathentry kind="lib" path="libs/scprov-jdk15on-1.47.0.3-SNAPSHOT.jar"/>
<classpathentry kind="lib" path="libs/silvertunnel.org-netlib-0.14-briar.jar"/>
<classpathentry kind="lib" path="libs/weupnp-0.1.1.jar"/>
<classpathentry kind="lib" path="android.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
briar-core/.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>briar-core</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

BIN
briar-core/android.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

25
briar-core/src/build.xml Normal file
View File

@@ -0,0 +1,25 @@
<project name='prototype' default='compile'>
<fileset id='prototype-jars' dir='../libs'>
<include name='*.jar'/>
</fileset>
<path id='android-jar'>
<pathelement location='../android.jar'/>
</path>
<path id='prototype-classes'>
<pathelement location='../build'/>
</path>
<target name='clean'>
<delete dir='../build'/>
</target>
<target name='compile'>
<mkdir dir='../build'/>
<javac srcdir='.' destdir='../build' source='1.5'
includeantruntime='false' debug='off'>
<classpath>
<fileset refid='prototype-jars'/>
<path refid='android-jar'/>
<path refid='prototype-classes'/>
</classpath>
</javac>
</target>
</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,16 @@
package net.sf.briar.api.android;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
/**
* Enables background threads to make Android API calls that must be made from
* a thread with a message queue.
*/
public interface AndroidExecutor {
/** Runs the given task on a thread with a message queue. */
<V> V run(Callable<V> c) throws InterruptedException, ExecutionException;
void shutdown();
}

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.clock;
import java.util.TimerTask;
/** Default timer implementation. */
public class SystemTimer implements Timer {
private final java.util.Timer timer = new java.util.Timer();
public void cancel() {
timer.cancel();
}
public int purge() {
return timer.purge();
}
public void schedule(TimerTask task, long delay) {
timer.schedule(task, delay);
}
public void schedule(TimerTask task, long delay, long period) {
timer.schedule(task, delay, period);
}
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
timer.scheduleAtFixedRate(task, delay, period);
}
}

View File

@@ -0,0 +1,27 @@
package net.sf.briar.api.clock;
import java.util.TimerTask;
/**
* A wrapper around a {@link java.util.Timer} that allows it to be replaced for
* testing.
*/
public interface Timer {
/** @see {@link java.util.Timer#cancel()} */
void cancel();
/** @see {@link java.util.Timer#purge()} */
int purge();
/** @see {@link java.util.Timer#schedule(TimerTask, long)} */
void schedule(TimerTask task, long delay);
/** @see {@link java.util.Timer#schedule(TimerTask, long, long)} */
void schedule(TimerTask task, long delay, long period);
/**
* @see {@link java.util.Timer#scheduleAtFixedRate(TimerTask, long, long)}
*/
void scheduleAtFixedRate(TimerTask task, long delay, long period);
}

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,81 @@
package net.sf.briar.api.crypto;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
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[] theirPublicKey, KeyPair ourKeyPair,
boolean alice) throws GeneralSecurityException;
/**
* 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();
KeyParser getAgreementKeyParser();
KeyPair generateSignatureKeyPair();
KeyParser getSignatureKeyParser();
ErasableKey generateTestKey();
MessageDigest getMessageDigest();
PseudoRandom getPseudoRandom(int seed1, int seed2);
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.protocol.TransportId;
import net.sf.briar.api.transport.ConnectionContext;
import net.sf.briar.api.transport.ContactTransport;
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,32 @@
package net.sf.briar.api.crypto;
/**
* A wrapper around a {@link java.security.MessageDigest} that allows it to be
* replaced for testing.
*/
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,225 @@
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;
import net.sf.briar.api.transport.ContactTransport;
import net.sf.briar.api.transport.TemporarySecret;
/**
* 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;
/**
* Merges the given configuration with existing configuration for the
* given transport.
*/
void mergeConfig(TransportId t, TransportConfig c) throws DbException;
/**
* Merges the given properties with the existing local properties for the
* given transport.
*/
void mergeLocalProperties(TransportId t, TransportProperties p)
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 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;
/** 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,14 @@
package net.sf.briar.api.db;
import java.io.File;
import net.sf.briar.api.crypto.Password;
public interface DatabaseConfig {
File getDataDirectory();
Password getPassword();
long getMaxSize();
}

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,7 @@
package net.sf.briar.api.db;
/** Thrown when a database operation is attempted and the database is closed. */
public class DbClosedException extends DbException {
private static final long serialVersionUID = -3679248177625310653L;
}

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,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,26 @@
package net.sf.briar.api.invitation;
/**
* An interface for receiving updates about the state of an
* {@link InvitationTask}.
*/
public interface InvitationListener {
/** Called if a connection is established and key agreement succeeds. */
void connectionSucceeded(int localCode, int remoteCode);
/** Called if a connection cannot be established. */
void connectionFailed();
/**
* Informs the local peer that the remote peer's confirmation check
* succeeded.
*/
void remoteConfirmationSucceeded();
/**
* Informs the local peer that the remote peer's confirmation check did
* not succeed, or the connection was lost during confirmation.
*/
void remoteConfirmationFailed();
}

View File

@@ -0,0 +1,22 @@
package net.sf.briar.api.invitation;
/** Creates and manages tasks for exchanging invitations with remote peers. */
public interface InvitationManager {
/** Creates a task using the given invitation codes. */
InvitationTask createTask(int localCode, int remoteCode);
/**
* Returns the previously created task with the given handle, unless the
* task has subsequently removed itself.
*/
InvitationTask getTask(int handle);
/** Called by tasks to add themselves to the manager when they start. */
void putTask(int handle, InvitationTask task);
/**
* Called by tasks to remove themselves from the managet when they finish.
*/
void removeTask(int handle);
}

View File

@@ -0,0 +1,62 @@
package net.sf.briar.api.invitation;
public class InvitationState {
private final int localInvitationCode, remoteInvitationCode;
private final int localConfirmationCode, remoteConfirmationCode;
private final boolean connectionFailed;
private final boolean localCompared, remoteCompared;
private final boolean localMatched, remoteMatched;
public InvitationState(int localInvitationCode, int remoteInvitationCode,
int localConfirmationCode, int remoteConfirmationCode,
boolean connectionFailed, boolean localCompared,
boolean remoteCompared, boolean localMatched,
boolean remoteMatched) {
this.localInvitationCode = localInvitationCode;
this.remoteInvitationCode = remoteInvitationCode;
this.localConfirmationCode = localConfirmationCode;
this.remoteConfirmationCode = remoteConfirmationCode;
this.connectionFailed = connectionFailed;
this.localCompared = localCompared;
this.remoteCompared = remoteCompared;
this.localMatched = localMatched;
this.remoteMatched = remoteMatched;
}
public int getLocalInvitationCode() {
return localInvitationCode;
}
public int getRemoteInvitationCode() {
return remoteInvitationCode;
}
public int getLocalConfirmationCode() {
return localConfirmationCode;
}
public int getRemoteConfirmationCode() {
return remoteConfirmationCode;
}
public boolean getConnectionFailed() {
return connectionFailed;
}
public boolean getLocalCompared() {
return localCompared;
}
public boolean getRemoteCompared() {
return remoteCompared;
}
public boolean getLocalMatched() {
return localMatched;
}
public boolean getRemoteMatched() {
return remoteMatched;
}
}

View File

@@ -0,0 +1,32 @@
package net.sf.briar.api.invitation;
/** A task for exchanging invitations with a remote peer. */
public interface InvitationTask {
/** Returns the task's unique handle. */
int getHandle();
/**
* Adds a listener to be informed of state changes and returns the
* task's current state.
*/
InvitationState addListener(InvitationListener l);
/** Removes the given listener. */
void removeListener(InvitationListener l);
/** Asynchronously starts the connection process. */
void connect();
/**
* Asynchronously informs the remote peer that the local peer's
* confirmation codes matched.
*/
void localConfirmationSucceeded();
/**
* Asynchronously informs the remote peer that the local peer's
* confirmation codes did not match.
*/
void localConfirmationFailed();
}

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,16 @@
package net.sf.briar.api.plugins;
public interface InvitationConstants {
long CONNECTION_TIMEOUT = 15 * 1000; // Milliseconds
long CONFIRMATION_TIMEOUT = 60 * 1000; // Milliseconds
int CODE_BITS = 19; // Codes must fit into six decimal digits
int MAX_CODE = (1 << CODE_BITS) - 1; // 524287
int HASH_LENGTH = 48; // Bytes
int MAX_PUBLIC_KEY_LENGTH = 120; // Bytes
}

View File

@@ -0,0 +1,41 @@
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();
/** Returns a label for looking up the plugin's translated name. */
String getName();
/** Starts the plugin and returns true if it started successfully. */
boolean start() throws IOException;
/** Stops the plugin. */
void stop() throws IOException;
/**
* Returns true if the plugin's {@link Plugin#poll(Collection)} method
* should be called periodically to attempt to establish connections.
*/
boolean shouldPoll();
/**
* Returns the desired interval in milliseconds between calls to the
* plugin's {@link Plugin#poll(Collection)} 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,52 @@
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();
/** Merges the given configuration with the plugin's configuration. */
void mergeConfig(TransportConfig c);
/**
* Merges the given properties with the plugin's local transport properties.
*/
void mergeLocalProperties(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,28 @@
package net.sf.briar.api.plugins;
import java.util.Collection;
import net.sf.briar.api.plugins.duplex.DuplexPlugin;
import android.content.Context;
/**
* Responsible for starting transport plugins at startup, stopping them at
* shutdown, and providing access to plugins for exchanging invitations.
*/
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. The appContext argument is null on non-Android platforms.
*/
int start(Context appContext);
/**
* 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,17 @@
package net.sf.briar.api.plugins.duplex;
import java.util.concurrent.Executor;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.protocol.TransportId;
import android.content.Context;
public interface DuplexPluginFactory {
TransportId getId();
DuplexPlugin createPlugin(Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager, 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,17 @@
package net.sf.briar.api.plugins.simplex;
import java.util.concurrent.Executor;
import net.sf.briar.api.android.AndroidExecutor;
import net.sf.briar.api.lifecycle.ShutdownManager;
import net.sf.briar.api.protocol.TransportId;
import android.content.Context;
public interface SimplexPluginFactory {
TransportId getId();
SimplexPlugin createPlugin(Executor pluginExecutor,
AndroidExecutor androidExecutor, Context appContext,
ShutdownManager shutdownManager, SimplexPluginCallback callback);
}

View File

@@ -0,0 +1,22 @@
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. */
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,29 @@
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. */
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();
}

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