Merge branch '1538-create-handshake-key-pair' into 'master'

Generate and store handshake key pair at startup if necessary

Closes #1538

See merge request briar/briar!1082
This commit is contained in:
Torsten Grote
2019-05-14 15:39:44 +00:00
65 changed files with 886 additions and 577 deletions

View File

@@ -33,7 +33,8 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
/**
* Called once for each incoming message that passes validation.
*
* @return whether or not this message should be shared
* @param txn A read-write transaction
* @return Whether or not this message should be shared
* @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup,
* whereas if a FormatException is thrown, the message will be permanently

View File

@@ -159,8 +159,20 @@ public interface ContactManager {
interface ContactHook {
/**
* Called when a contact is being added.
*
* @param txn A read-write transaction
* @param c The contact that is being added
*/
void addingContact(Transaction txn, Contact c) throws DbException;
/**
* Called when a contact is being removed
*
* @param txn A read-write transaction
* @param c The contact that is being removed
*/
void removingContact(Transaction txn, Contact c) throws DbException;
}
}

View File

@@ -7,7 +7,7 @@ import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings;
@@ -128,9 +128,9 @@ public interface DatabaseComponent {
HandshakeKeys k) throws DbException;
/**
* Stores a local pseudonym.
* Stores an identity.
*/
void addLocalAuthor(Transaction txn, LocalAuthor a) throws DbException;
void addIdentity(Transaction txn, Identity i) throws DbException;
/**
* Stores a local message.
@@ -174,12 +174,12 @@ public interface DatabaseComponent {
boolean containsGroup(Transaction txn, GroupId g) throws DbException;
/**
* Returns true if the database contains the given local author.
* Returns true if the database contains an identity for the given
* pseudonym.
* <p/>
* Read-only.
*/
boolean containsLocalAuthor(Transaction txn, AuthorId local)
throws DbException;
boolean containsIdentity(Transaction txn, AuthorId a) throws DbException;
/**
* Returns true if the database contains the given pending contact.
@@ -317,18 +317,18 @@ public interface DatabaseComponent {
throws DbException;
/**
* Returns the local pseudonym with the given ID.
* Returns the identity for the local pseudonym with the given ID.
* <p/>
* Read-only.
*/
LocalAuthor getLocalAuthor(Transaction txn, AuthorId a) throws DbException;
Identity getIdentity(Transaction txn, AuthorId a) throws DbException;
/**
* Returns all local pseudonyms.
* Returns the identities for all local pseudonyms.
* <p/>
* Read-only.
*/
Collection<LocalAuthor> getLocalAuthors(Transaction txn) throws DbException;
Collection<Identity> getIdentities(Transaction txn) throws DbException;
/**
* Returns the message with the given ID.
@@ -559,9 +559,9 @@ public interface DatabaseComponent {
HandshakeKeySetId k) throws DbException;
/**
* Removes a local pseudonym (and all associated state) from the database.
* Removes an identity (and all associated state) from the database.
*/
void removeLocalAuthor(Transaction txn, AuthorId a) throws DbException;
void removeIdentity(Transaction txn, AuthorId a) throws DbException;
/**
* Removes a message (and all associated state) from the database.
@@ -619,6 +619,12 @@ public interface DatabaseComponent {
void addMessageDependencies(Transaction txn, Message dependent,
Collection<MessageId> dependencies) throws DbException;
/**
* Sets the handshake key pair for the identity with the given ID.
*/
void setHandshakeKeyPair(Transaction txn, AuthorId local, byte[] publicKey,
byte[] privateKey) throws DbException;
/**
* Sets the reordering window for the given transport key set in the given
* time period.

View File

@@ -1,9 +1,9 @@
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a pseudonym that is not in
* Thrown when a database operation is attempted for an identity that is not in
* the database. This exception may occur due to concurrent updates and does
* not indicate a database error.
*/
public class NoSuchLocalAuthorException extends DbException {
public class NoSuchIdentityException extends DbException {
}

View File

@@ -18,14 +18,7 @@ public interface AuthorFactory {
/**
* Creates a local author with the current format version and the given
* name and keys.
* name.
*/
LocalAuthor createLocalAuthor(String name, byte[] publicKey,
byte[] privateKey);
/**
* Creates a local author with the given format version, name and keys.
*/
LocalAuthor createLocalAuthor(int formatVersion, String name,
byte[] publicKey, byte[] privateKey);
LocalAuthor createLocalAuthor(String name);
}

View File

@@ -0,0 +1,96 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Arrays;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
@Immutable
@NotNullByDefault
public class Identity {
private final LocalAuthor localAuthor;
@Nullable
private final byte[] handshakePublicKey, handshakePrivateKey;
private final long created;
public Identity(LocalAuthor localAuthor,
@Nullable byte[] handshakePublicKey,
@Nullable byte[] handshakePrivateKey, long created) {
if (handshakePublicKey != null) {
int keyLength = handshakePublicKey.length;
if (keyLength == 0 || keyLength > MAX_AGREEMENT_PUBLIC_KEY_BYTES)
throw new IllegalArgumentException();
}
this.localAuthor = localAuthor;
this.handshakePublicKey = handshakePublicKey;
this.handshakePrivateKey = handshakePrivateKey;
this.created = created;
}
/**
* Returns the ID of the user's pseudonym.
*/
public AuthorId getId() {
return localAuthor.getId();
}
/**
* Returns the user's pseudonym.
*/
public LocalAuthor getLocalAuthor() {
return localAuthor;
}
/**
* Returns true if the identity has a handshake key pair.
*/
public boolean hasHandshakeKeyPair() {
return handshakePublicKey != null && handshakePrivateKey != null;
}
/**
* Returns the public key used for handshaking, or null if no key exists.
*/
@Nullable
public byte[] getHandshakePublicKey() {
return handshakePublicKey;
}
/**
* Returns the private key used for handshaking, or null if no key exists.
*/
@Nullable
public byte[] getHandshakePrivateKey() {
return handshakePrivateKey;
}
/**
* Returns the time the identity was created, in milliseconds since the
* Unix epoch.
*/
public long getTimeCreated() {
return created;
}
@Override
public int hashCode() {
return localAuthor.getId().hashCode();
}
@Override
public boolean equals(Object o) {
if (o instanceof Identity) {
Identity i = (Identity) o;
return created == i.created &&
localAuthor.equals(i.localAuthor) &&
Arrays.equals(handshakePublicKey, i.handshakePublicKey) &&
Arrays.equals(handshakePrivateKey, i.handshakePrivateKey);
}
return false;
}
}

View File

@@ -1,30 +1,29 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface IdentityManager {
/**
* Creates a local identity with the given name.
* Creates an identity with the given name. The identity includes a
* handshake key pair.
*/
@CryptoExecutor
LocalAuthor createLocalAuthor(String name);
Identity createIdentity(String name);
/**
* Registers the given local identity with the manager. The identity is
* not stored until {@link #storeLocalAuthor()} is called.
* Registers the given identity with the manager. This method should be
* called before {@link LifecycleManager#startServices(SecretKey)}. The
* identity is stored when {@link LifecycleManager#startServices(SecretKey)}
* is called. The identity must include a handshake key pair.
*/
void registerLocalAuthor(LocalAuthor a);
/**
* Stores the local identity registered with
* {@link #registerLocalAuthor(LocalAuthor)}, if any.
*/
void storeLocalAuthor() throws DbException;
void registerIdentity(Identity i);
/**
* Returns the cached local identity or loads it from the database.
@@ -33,7 +32,18 @@ public interface IdentityManager {
/**
* Returns the cached local identity or loads it from the database.
* <p/>
* Read-only.
*/
LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
/**
* Returns the cached handshake keys or loads them from the database.
* <p/>
* Read-only.
*
* @return A two-element array containing the public key in the first
* element and the private key in the second
*/
byte[][] getHandshakeKeys(Transaction txn) throws DbException;
}

View File

@@ -2,11 +2,8 @@ package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
/**
* A pseudonym for the local user.
*/
@@ -15,31 +12,11 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
public class LocalAuthor extends Author {
private final byte[] privateKey;
@Nullable
private final byte[] handshakePublicKey, handshakePrivateKey;
private final long created;
public LocalAuthor(AuthorId id, int formatVersion, String name,
byte[] publicKey, byte[] privateKey, long created) {
byte[] publicKey, byte[] privateKey) {
super(id, formatVersion, name, publicKey);
this.privateKey = privateKey;
this.created = created;
handshakePublicKey = null;
handshakePrivateKey = null;
}
public LocalAuthor(AuthorId id, int formatVersion, String name,
byte[] publicKey, byte[] privateKey, byte[] handshakePublicKey,
byte[] handshakePrivateKey, long created) {
super(id, formatVersion, name, publicKey);
if (handshakePublicKey.length == 0 ||
handshakePublicKey.length > MAX_PUBLIC_KEY_LENGTH) {
throw new IllegalArgumentException();
}
this.privateKey = privateKey;
this.handshakePublicKey = handshakePublicKey;
this.handshakePrivateKey = handshakePrivateKey;
this.created = created;
}
/**
@@ -48,28 +25,4 @@ public class LocalAuthor extends Author {
public byte[] getPrivateKey() {
return privateKey;
}
/**
* Returns the public key used for handshaking, or null if no key exists.
*/
@Nullable
public byte[] getHandshakePublicKey() {
return handshakePublicKey;
}
/**
* Returns the private key used for handshaking, or null if no key exists.
*/
@Nullable
public byte[] getHandshakePrivateKey() {
return handshakePrivateKey;
}
/**
* Returns the time the pseudonym was created, in milliseconds since the
* Unix epoch.
*/
public long getTimeCreated() {
return created;
}
}

View File

@@ -7,15 +7,15 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a local pseudonym is added.
* An event that is broadcast when an identity is added.
*/
@Immutable
@NotNullByDefault
public class LocalAuthorAddedEvent extends Event {
public class IdentityAddedEvent extends Event {
private final AuthorId authorId;
public LocalAuthorAddedEvent(AuthorId authorId) {
public IdentityAddedEvent(AuthorId authorId) {
this.authorId = authorId;
}

View File

@@ -7,15 +7,15 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a local pseudonym is removed.
* An event that is broadcast when an identity is removed.
*/
@Immutable
@NotNullByDefault
public class LocalAuthorRemovedEvent extends Event {
public class IdentityRemovedEvent extends Event {
private final AuthorId authorId;
public LocalAuthorRemovedEvent(AuthorId authorId) {
public IdentityRemovedEvent(AuthorId authorId) {
this.authorId = authorId;
}

View File

@@ -2,16 +2,16 @@ package org.briarproject.bramble.api.lifecycle;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import java.util.concurrent.ExecutorService;
/**
* Manages the lifecycle of the app, starting {@link Client Clients}, starting
* and stopping {@link Service Services}, shutting down
* {@link ExecutorService ExecutorServices}, and opening and closing the
* {@link DatabaseComponent}.
* Manages the lifecycle of the app: opening and closing the
* {@link DatabaseComponent} starting and stopping {@link Service Services},
* and shutting down {@link ExecutorService ExecutorServices}.
*/
@NotNullByDefault
public interface LifecycleManager {
@@ -42,18 +42,19 @@ public interface LifecycleManager {
}
}
/**
* Registers a hook to be called after the database is opened and before
* {@link Service services} are started. This method should be called
* before {@link #startServices(SecretKey)}.
*/
void registerOpenDatabaseHook(OpenDatabaseHook hook);
/**
* Registers a {@link Service} to be started and stopped. This method
* should be called before {@link #startServices(SecretKey)}.
*/
void registerService(Service s);
/**
* Registers a {@link Client} to be started. This method should be called
* before {@link #startServices(SecretKey)}.
*/
void registerClient(Client c);
/**
* Registers an {@link ExecutorService} to be shut down. This method
* should be called before {@link #startServices(SecretKey)}.
@@ -62,7 +63,7 @@ public interface LifecycleManager {
/**
* Opens the {@link DatabaseComponent} using the given key and starts any
* registered {@link Client Clients} and {@link Service Services}.
* registered {@link Service Services}.
*/
StartResult startServices(SecretKey dbKey);
@@ -80,8 +81,7 @@ public interface LifecycleManager {
/**
* Waits for the {@link DatabaseComponent} to be opened and all registered
* {@link Client Clients} and {@link Service Services} to start before
* returning.
* {@link Service Services} to start before returning.
*/
void waitForStartup() throws InterruptedException;
@@ -97,4 +97,13 @@ public interface LifecycleManager {
*/
LifecycleState getLifecycleState();
interface OpenDatabaseHook {
/**
* Called when the database is being opened, before
* {@link #waitForDatabase()} returns.
*
* @param txn A read-write transaction
*/
void onDatabaseOpened(Transaction txn) throws DbException;
}
}

View File

@@ -1,14 +0,0 @@
package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Client {
/**
* Called at startup to create any local state needed by the client.
*/
void createLocalState(Transaction txn) throws DbException;
}

View File

@@ -11,7 +11,8 @@ public interface IncomingMessageHook {
/**
* Called once for each incoming message that passes validation.
*
* @return whether or not this message should be shared
* @param txn A read-write transaction
* @return Whether or not this message should be shared
* @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup,
* whereas if an InvalidMessageException is thrown,

View File

@@ -46,7 +46,14 @@ public interface ClientVersioningManager {
ClientId clientId, int majorVersion) throws DbException;
interface ClientVersioningHook {
/**
* Called when the visibility of a client with respect to a contact is
* changing.
*
* @param txn A read-write transaction
* @param c The contact affected by the visibility change
* @param v The new visibility of the client
*/
void onClientVisibilityChanging(Transaction txn, Contact c,
Visibility v) throws DbException;
}

View File

@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
@@ -30,6 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Arrays.asList;
import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
@@ -99,25 +101,26 @@ public class TestUtils {
return new SecretKey(getRandomBytes(SecretKey.LENGTH));
}
public static LocalAuthor getLocalAuthor() {
return getLocalAuthor(1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH));
}
public static LocalAuthor getLocalAuthor(int nameLength) {
AuthorId id = new AuthorId(getRandomId());
String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey,
public static Identity getIdentity() {
LocalAuthor localAuthor = getLocalAuthor();
byte[] handshakePub = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES);
byte[] handshakePriv = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES);
return new Identity(localAuthor, handshakePub, handshakePriv,
timestamp);
}
public static Author getAuthor() {
return getAuthor(1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH));
public static LocalAuthor getLocalAuthor() {
AuthorId id = new AuthorId(getRandomId());
int nameLength = 1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH);
String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey);
}
public static Author getAuthor(int nameLength) {
public static Author getAuthor() {
AuthorId id = new AuthorId(getRandomId());
int nameLength = 1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH);
String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new Author(id, FORMAT_VERSION, name, publicKey);

View File

@@ -4,8 +4,8 @@ import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.util.IoUtils;
@@ -161,8 +161,8 @@ class AccountManagerImpl implements AccountManager {
synchronized (stateChangeLock) {
if (hasDatabaseKey())
throw new AssertionError("Already have a database key");
LocalAuthor localAuthor = identityManager.createLocalAuthor(name);
identityManager.registerLocalAuthor(localAuthor);
Identity identity = identityManager.createIdentity(name);
identityManager.registerIdentity(identity);
SecretKey key = crypto.generateSecretKey();
if (!encryptAndStoreDatabaseKey(key, password)) return false;
databaseKey = key;

View File

@@ -15,7 +15,7 @@ import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings;
@@ -120,9 +120,9 @@ interface Database<T> {
HandshakeKeys k) throws DbException;
/**
* Stores a local pseudonym.
* Stores an identity.
*/
void addLocalAuthor(T txn, LocalAuthor a) throws DbException;
void addIdentity(T txn, Identity i) throws DbException;
/**
* Stores a message.
@@ -187,11 +187,12 @@ interface Database<T> {
boolean containsGroup(T txn, GroupId g) throws DbException;
/**
* Returns true if the database contains the given local pseudonym.
* Returns true if the database contains an identity for the given
* pseudonym.
* <p/>
* Read-only.
*/
boolean containsLocalAuthor(T txn, AuthorId a) throws DbException;
boolean containsIdentity(T txn, AuthorId a) throws DbException;
/**
* Returns true if the database contains the given message.
@@ -323,18 +324,18 @@ interface Database<T> {
throws DbException;
/**
* Returns the local pseudonym with the given ID.
* Returns the identity for local pseudonym with the given ID.
* <p/>
* Read-only.
*/
LocalAuthor getLocalAuthor(T txn, AuthorId a) throws DbException;
Identity getIdentity(T txn, AuthorId a) throws DbException;
/**
* Returns all local pseudonyms.
* Returns the identities for all local pseudonyms.
* <p/>
* Read-only.
*/
Collection<LocalAuthor> getLocalAuthors(T txn) throws DbException;
Collection<Identity> getIdentities(T txn) throws DbException;
/**
* Returns the message with the given ID.
@@ -629,9 +630,9 @@ interface Database<T> {
throws DbException;
/**
* Removes a local pseudonym (and all associated state) from the database.
* Removes an identity (and all associated state) from the database.
*/
void removeLocalAuthor(T txn, AuthorId a) throws DbException;
void removeIdentity(T txn, AuthorId a) throws DbException;
/**
* Removes a message (and all associated state) from the database.
@@ -685,6 +686,12 @@ interface Database<T> {
void setGroupVisibility(T txn, ContactId c, GroupId g, boolean shared)
throws DbException;
/**
* Sets the handshake key pair for the identity with the given ID.
*/
void setHandshakeKeyPair(T txn, AuthorId local, byte[] publicKey,
byte[] privateKey) throws DbException;
/**
* Marks the given message as shared.
*/

View File

@@ -20,7 +20,7 @@ import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.NoSuchGroupException;
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
import org.briarproject.bramble.api.db.NoSuchIdentityException;
import org.briarproject.bramble.api.db.NoSuchMessageException;
import org.briarproject.bramble.api.db.NoSuchPendingContactException;
import org.briarproject.bramble.api.db.NoSuchTransportException;
@@ -32,9 +32,9 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventExecutor;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.identity.event.LocalAuthorAddedEvent;
import org.briarproject.bramble.api.identity.event.LocalAuthorRemovedEvent;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.event.IdentityAddedEvent;
import org.briarproject.bramble.api.identity.event.IdentityRemovedEvent;
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
@@ -237,9 +237,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, local))
throw new NoSuchLocalAuthorException();
if (db.containsLocalAuthor(txn, remote.getId()))
if (!db.containsIdentity(txn, local))
throw new NoSuchIdentityException();
if (db.containsIdentity(txn, remote.getId()))
throw new ContactExistsException();
if (db.containsContact(txn, remote.getId(), local))
throw new ContactExistsException();
@@ -283,13 +283,13 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public void addLocalAuthor(Transaction transaction, LocalAuthor a)
public void addIdentity(Transaction transaction, Identity i)
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, a.getId())) {
db.addLocalAuthor(txn, a);
transaction.attach(new LocalAuthorAddedEvent(a.getId()));
if (!db.containsIdentity(txn, i.getId())) {
db.addIdentity(txn, i);
transaction.attach(new IdentityAddedEvent(i.getId()));
}
}
@@ -345,8 +345,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
public boolean containsContact(Transaction transaction, AuthorId remote,
AuthorId local) throws DbException {
T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, local))
throw new NoSuchLocalAuthorException();
if (!db.containsIdentity(txn, local))
throw new NoSuchIdentityException();
return db.containsContact(txn, remote, local);
}
@@ -358,10 +358,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public boolean containsLocalAuthor(Transaction transaction, AuthorId local)
public boolean containsIdentity(Transaction transaction, AuthorId a)
throws DbException {
T txn = unbox(transaction);
return db.containsLocalAuthor(txn, local);
return db.containsIdentity(txn, a);
}
@Override
@@ -505,8 +505,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
public Collection<ContactId> getContacts(Transaction transaction,
AuthorId a) throws DbException {
T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, a))
throw new NoSuchLocalAuthorException();
if (!db.containsIdentity(txn, a))
throw new NoSuchIdentityException();
return db.getContacts(txn, a);
}
@@ -554,19 +554,19 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public LocalAuthor getLocalAuthor(Transaction transaction, AuthorId a)
public Identity getIdentity(Transaction transaction, AuthorId a)
throws DbException {
T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, a))
throw new NoSuchLocalAuthorException();
return db.getLocalAuthor(txn, a);
if (!db.containsIdentity(txn, a))
throw new NoSuchIdentityException();
return db.getIdentity(txn, a);
}
@Override
public Collection<LocalAuthor> getLocalAuthors(Transaction transaction)
public Collection<Identity> getIdentities(Transaction transaction)
throws DbException {
T txn = unbox(transaction);
return db.getLocalAuthors(txn);
return db.getIdentities(txn);
}
@Override
@@ -905,14 +905,14 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public void removeLocalAuthor(Transaction transaction, AuthorId a)
public void removeIdentity(Transaction transaction, AuthorId a)
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsLocalAuthor(txn, a))
throw new NoSuchLocalAuthorException();
db.removeLocalAuthor(txn, a);
transaction.attach(new LocalAuthorRemovedEvent(a));
if (!db.containsIdentity(txn, a))
throw new NoSuchIdentityException();
db.removeIdentity(txn, a);
transaction.attach(new IdentityRemovedEvent(a));
}
@Override
@@ -1035,6 +1035,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
}
@Override
public void setHandshakeKeyPair(Transaction transaction, AuthorId local,
byte[] publicKey, byte[] privateKey) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsIdentity(txn, local))
throw new NoSuchIdentityException();
db.setHandshakeKeyPair(txn, local, publicKey, privateKey);
}
@Override
public void setReorderingWindow(Transaction transaction,
TransportKeySetId k, TransportId t, long timePeriod, long base,

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
@@ -874,8 +875,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
@Override
public void addLocalAuthor(Connection txn, LocalAuthor a)
throws DbException {
public void addIdentity(Connection txn, Identity i) throws DbException {
PreparedStatement ps = null;
try {
String sql = "INSERT INTO localAuthors"
@@ -883,16 +883,17 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " handshakePublicKey, handshakePrivateKey, created)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql);
ps.setBytes(1, a.getId().getBytes());
ps.setInt(2, a.getFormatVersion());
ps.setString(3, a.getName());
ps.setBytes(4, a.getPublicKey());
ps.setBytes(5, a.getPrivateKey());
if (a.getHandshakePublicKey() == null) ps.setNull(6, BINARY);
else ps.setBytes(6, a.getHandshakePublicKey());
if (a.getHandshakePrivateKey() == null) ps.setNull(7, BINARY);
else ps.setBytes(7, a.getHandshakePrivateKey());
ps.setLong(8, a.getTimeCreated());
LocalAuthor local = i.getLocalAuthor();
ps.setBytes(1, local.getId().getBytes());
ps.setInt(2, local.getFormatVersion());
ps.setString(3, local.getName());
ps.setBytes(4, local.getPublicKey());
ps.setBytes(5, local.getPrivateKey());
if (i.getHandshakePublicKey() == null) ps.setNull(6, BINARY);
else ps.setBytes(6, i.getHandshakePublicKey());
if (i.getHandshakePrivateKey() == null) ps.setNull(7, BINARY);
else ps.setBytes(7, i.getHandshakePrivateKey());
ps.setLong(8, i.getTimeCreated());
int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException();
ps.close();
@@ -1248,7 +1249,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
@Override
public boolean containsLocalAuthor(Connection txn, AuthorId a)
public boolean containsIdentity(Connection txn, AuthorId a)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
@@ -1660,41 +1661,6 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public LocalAuthor getLocalAuthor(Connection txn, AuthorId a)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT formatVersion, name, publicKey, privateKey,"
+ " handshakePublicKey, handshakePrivateKey, created"
+ " FROM localAuthors"
+ " WHERE authorId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, a.getBytes());
rs = ps.executeQuery();
if (!rs.next()) throw new DbStateException();
int formatVersion = rs.getInt(1);
String name = rs.getString(2);
byte[] publicKey = rs.getBytes(3);
byte[] privateKey = rs.getBytes(4);
byte[] handshakePublicKey = rs.getBytes(5);
byte[] handshakePrivateKey = rs.getBytes(6);
long created = rs.getLong(7);
LocalAuthor localAuthor = new LocalAuthor(a, formatVersion, name,
publicKey, privateKey, handshakePublicKey,
handshakePrivateKey, created);
if (rs.next()) throw new DbStateException();
rs.close();
ps.close();
return localAuthor;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public Collection<HandshakeKeySet> getHandshakeKeys(Connection txn,
TransportId t) throws DbException {
@@ -1776,30 +1742,69 @@ abstract class JdbcDatabase implements Database<Connection> {
}
@Override
public Collection<LocalAuthor> getLocalAuthors(Connection txn)
public Identity getIdentity(Connection txn, AuthorId a) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT formatVersion, name, publicKey, privateKey,"
+ " handshakePublicKey, handshakePrivateKey, created"
+ " FROM localAuthors"
+ " WHERE authorId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, a.getBytes());
rs = ps.executeQuery();
if (!rs.next()) throw new DbStateException();
int formatVersion = rs.getInt(1);
String name = rs.getString(2);
byte[] publicKey = rs.getBytes(3);
byte[] privateKey = rs.getBytes(4);
byte[] handshakePublicKey = rs.getBytes(5);
byte[] handshakePrivateKey = rs.getBytes(6);
long created = rs.getLong(7);
if (rs.next()) throw new DbStateException();
rs.close();
ps.close();
LocalAuthor local = new LocalAuthor(a, formatVersion, name,
publicKey, privateKey);
return new Identity(local, handshakePublicKey, handshakePrivateKey,
created);
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public Collection<Identity> getIdentities(Connection txn)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT authorId, formatVersion, name, publicKey,"
+ " privateKey, created"
+ " privateKey, handshakePublicKey, handshakePrivateKey,"
+ " created"
+ " FROM localAuthors";
ps = txn.prepareStatement(sql);
rs = ps.executeQuery();
List<LocalAuthor> authors = new ArrayList<>();
List<Identity> identities = new ArrayList<>();
while (rs.next()) {
AuthorId authorId = new AuthorId(rs.getBytes(1));
int formatVersion = rs.getInt(2);
String name = rs.getString(3);
byte[] publicKey = rs.getBytes(4);
byte[] privateKey = rs.getBytes(5);
long created = rs.getLong(6);
authors.add(new LocalAuthor(authorId, formatVersion, name,
publicKey, privateKey, created));
byte[] handshakePublicKey = rs.getBytes(6);
byte[] handshakePrivateKey = rs.getBytes(7);
long created = rs.getLong(8);
LocalAuthor local = new LocalAuthor(authorId, formatVersion,
name, publicKey, privateKey);
identities.add(new Identity(local, handshakePublicKey,
handshakePrivateKey, created));
}
rs.close();
ps.close();
return authors;
return identities;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
@@ -2958,8 +2963,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
@Override
public void removeLocalAuthor(Connection txn, AuthorId a)
throws DbException {
public void removeIdentity(Connection txn, AuthorId a) throws DbException {
PreparedStatement ps = null;
try {
String sql = "DELETE FROM localAuthors WHERE authorId = ?";
@@ -3176,6 +3180,27 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public void setHandshakeKeyPair(Connection txn, AuthorId local,
byte[] publicKey, byte[] privateKey) throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE localAuthors"
+ " SET handshakePublicKey = ?, handshakePrivateKey = ?"
+ " WHERE authorId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, publicKey);
ps.setBytes(2, privateKey);
ps.setBytes(3, local.getBytes());
int affected = ps.executeUpdate();
if (affected < 0 || affected > 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public void setMessageShared(Connection txn, MessageId m)
throws DbException {

View File

@@ -1,12 +1,12 @@
package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils;
@@ -22,12 +22,10 @@ import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
class AuthorFactoryImpl implements AuthorFactory {
private final CryptoComponent crypto;
private final Clock clock;
@Inject
AuthorFactoryImpl(CryptoComponent crypto, Clock clock) {
AuthorFactoryImpl(CryptoComponent crypto) {
this.crypto = crypto;
this.clock = clock;
}
@Override
@@ -43,17 +41,12 @@ class AuthorFactoryImpl implements AuthorFactory {
}
@Override
public LocalAuthor createLocalAuthor(String name, byte[] publicKey,
byte[] privateKey) {
return createLocalAuthor(FORMAT_VERSION, name, publicKey, privateKey);
}
@Override
public LocalAuthor createLocalAuthor(int formatVersion, String name,
byte[] publicKey, byte[] privateKey) {
AuthorId id = getId(formatVersion, name, publicKey);
return new LocalAuthor(id, formatVersion, name, publicKey, privateKey,
clock.currentTimeMillis());
public LocalAuthor createLocalAuthor(String name) {
KeyPair signatureKeyPair = crypto.generateSignatureKeyPair();
byte[] publicKey = signatureKeyPair.getPublic().getEncoded();
byte[] privateKey = signatureKeyPair.getPrivate().getEncoded();
AuthorId id = getId(FORMAT_VERSION, name, publicKey);
return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey);
}
private AuthorId getId(int formatVersion, String name, byte[] publicKey) {

View File

@@ -6,97 +6,164 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import java.util.Collection;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
@ThreadSafe
@NotNullByDefault
class IdentityManagerImpl implements IdentityManager {
class IdentityManagerImpl implements IdentityManager, OpenDatabaseHook {
private static final Logger LOG =
Logger.getLogger(IdentityManagerImpl.class.getName());
getLogger(IdentityManagerImpl.class.getName());
private final DatabaseComponent db;
private final CryptoComponent crypto;
private final AuthorFactory authorFactory;
private final Clock clock;
// The local author is immutable so we can cache it
/**
* The user's identity, or null if no identity has been registered or
* loaded. If non-null, this identity always has handshake keys.
*/
@Nullable
private volatile LocalAuthor cachedAuthor;
private volatile Identity cachedIdentity = null;
/**
* True if {@code cachedIdentity} was registered via
* {@link #registerIdentity(Identity)} and should be stored when
* {@link #onDatabaseOpened(Transaction)} is called.
*/
private volatile boolean shouldStoreIdentity = false;
/**
* True if the handshake keys in {@code cachedIdentity} were generated
* when the identity was loaded and should be stored when
* {@link #onDatabaseOpened(Transaction)} is called.
*/
private volatile boolean shouldStoreKeys = false;
@Inject
IdentityManagerImpl(DatabaseComponent db, CryptoComponent crypto,
AuthorFactory authorFactory) {
AuthorFactory authorFactory, Clock clock) {
this.db = db;
this.crypto = crypto;
this.authorFactory = authorFactory;
this.clock = clock;
}
@Override
public LocalAuthor createLocalAuthor(String name) {
public Identity createIdentity(String name) {
long start = now();
KeyPair keyPair = crypto.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded();
LocalAuthor localAuthor = authorFactory.createLocalAuthor(name,
publicKey, privateKey);
logDuration(LOG, "Creating local author", start);
return localAuthor;
LocalAuthor localAuthor = authorFactory.createLocalAuthor(name);
KeyPair handshakeKeyPair = crypto.generateAgreementKeyPair();
byte[] handshakePub = handshakeKeyPair.getPublic().getEncoded();
byte[] handshakePriv = handshakeKeyPair.getPrivate().getEncoded();
logDuration(LOG, "Creating identity", start);
return new Identity(localAuthor, handshakePub, handshakePriv,
clock.currentTimeMillis());
}
@Override
public void registerLocalAuthor(LocalAuthor a) {
cachedAuthor = a;
LOG.info("Local author registered");
public void registerIdentity(Identity i) {
if (!i.hasHandshakeKeyPair()) throw new IllegalArgumentException();
cachedIdentity = i;
shouldStoreIdentity = true;
LOG.info("Identity registered");
}
@Override
public void storeLocalAuthor() throws DbException {
LocalAuthor cached = cachedAuthor;
if (cached == null) {
LOG.info("No local author to store");
return;
public void onDatabaseOpened(Transaction txn) throws DbException {
Identity cached = getCachedIdentity(txn);
if (shouldStoreIdentity) {
// The identity was registered at startup - store it
db.addIdentity(txn, cached);
LOG.info("Identity stored");
} else if (shouldStoreKeys) {
// Handshake keys were generated when loading the identity -
// store them
byte[] handshakePub =
requireNonNull(cached.getHandshakePublicKey());
byte[] handshakePriv =
requireNonNull(cached.getHandshakePrivateKey());
db.setHandshakeKeyPair(txn, cached.getId(), handshakePub,
handshakePriv);
LOG.info("Handshake key pair stored");
}
db.transaction(false, txn -> db.addLocalAuthor(txn, cached));
LOG.info("Local author stored");
}
@Override
public LocalAuthor getLocalAuthor() throws DbException {
if (cachedAuthor == null) {
cachedAuthor =
db.transactionWithResult(true, this::loadLocalAuthor);
LOG.info("Local author loaded");
}
LocalAuthor cached = cachedAuthor;
if (cached == null) throw new AssertionError();
return cached;
Identity cached = cachedIdentity;
if (cached == null)
cached = db.transactionWithResult(true, this::getCachedIdentity);
return cached.getLocalAuthor();
}
@Override
public LocalAuthor getLocalAuthor(Transaction txn) throws DbException {
if (cachedAuthor == null) {
cachedAuthor = loadLocalAuthor(txn);
LOG.info("Local author loaded");
}
LocalAuthor cached = cachedAuthor;
if (cached == null) throw new AssertionError();
return getCachedIdentity(txn).getLocalAuthor();
}
@Override
public byte[][] getHandshakeKeys(Transaction txn) throws DbException {
Identity cached = getCachedIdentity(txn);
return new byte[][] {
cached.getHandshakePublicKey(),
cached.getHandshakePrivateKey()
};
}
/**
* Loads the identity if necessary and returns it. If
* {@code cachedIdentity} was not already set by calling
* {@link #registerIdentity(Identity)}, this method sets it. If
* {@code cachedIdentity} was already set, either by calling
* {@link #registerIdentity(Identity)} or by a previous call to this
* method, then this method returns the cached identity without hitting
* the database.
*/
private Identity getCachedIdentity(Transaction txn) throws DbException {
Identity cached = cachedIdentity;
if (cached == null)
cachedIdentity = cached = loadIdentityWithKeyPair(txn);
return cached;
}
private LocalAuthor loadLocalAuthor(Transaction txn) throws DbException {
return db.getLocalAuthors(txn).iterator().next();
/**
* Loads and returns the identity, generating a handshake key pair if
* necessary and setting {@code shouldStoreKeys} if a handshake key pair
* was generated.
*/
private Identity loadIdentityWithKeyPair(Transaction txn)
throws DbException {
Collection<Identity> identities = db.getIdentities(txn);
if (identities.size() != 1) throw new DbException();
Identity i = identities.iterator().next();
LOG.info("Identity loaded");
if (i.hasHandshakeKeyPair()) return i;
KeyPair handshakeKeyPair = crypto.generateAgreementKeyPair();
byte[] handshakePub = handshakeKeyPair.getPublic().getEncoded();
byte[] handshakePriv = handshakeKeyPair.getPrivate().getEncoded();
LOG.info("Handshake key pair generated");
shouldStoreKeys = true;
return new Identity(i.getLocalAuthor(), handshakePub, handshakePriv,
i.getTimeCreated());
}
}

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -24,8 +25,9 @@ public class IdentityModule {
@Provides
@Singleton
IdentityManager provideIdentityManager(
IdentityManager provideIdentityManager(LifecycleManager lifecycleManager,
IdentityManagerImpl identityManager) {
lifecycleManager.registerOpenDatabaseHook(identityManager);
return identityManager;
}
}

View File

@@ -7,13 +7,11 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -28,6 +26,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
@@ -49,14 +48,13 @@ import static org.briarproject.bramble.util.LogUtils.now;
class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
private static final Logger LOG =
Logger.getLogger(LifecycleManagerImpl.class.getName());
getLogger(LifecycleManagerImpl.class.getName());
private final DatabaseComponent db;
private final EventBus eventBus;
private final List<Service> services;
private final List<Client> clients;
private final List<OpenDatabaseHook> openDatabaseHooks;
private final List<ExecutorService> executors;
private final IdentityManager identityManager;
private final Semaphore startStopSemaphore = new Semaphore(1);
private final CountDownLatch dbLatch = new CountDownLatch(1);
private final CountDownLatch startupLatch = new CountDownLatch(1);
@@ -65,13 +63,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
private volatile LifecycleState state = STARTING;
@Inject
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus,
IdentityManager identityManager) {
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus) {
this.db = db;
this.eventBus = eventBus;
this.identityManager = identityManager;
services = new CopyOnWriteArrayList<>();
clients = new CopyOnWriteArrayList<>();
openDatabaseHooks = new CopyOnWriteArrayList<>();
executors = new CopyOnWriteArrayList<>();
}
@@ -83,10 +79,12 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
}
@Override
public void registerClient(Client c) {
if (LOG.isLoggable(INFO))
LOG.info("Registering client " + c.getClass().getSimpleName());
clients.add(c);
public void registerOpenDatabaseHook(OpenDatabaseHook hook) {
if (LOG.isLoggable(INFO)) {
LOG.info("Registering open database hook "
+ hook.getClass().getSimpleName());
}
openDatabaseHooks.add(hook);
}
@Override
@@ -102,28 +100,28 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
return ALREADY_RUNNING;
}
try {
LOG.info("Starting services");
LOG.info("Opening database");
long start = now();
boolean reopened = db.open(dbKey, this);
if (reopened) logDuration(LOG, "Reopening database", start);
else logDuration(LOG, "Creating database", start);
identityManager.storeLocalAuthor();
db.transaction(false, txn -> {
for (OpenDatabaseHook hook : openDatabaseHooks) {
long start1 = now();
hook.onDatabaseOpened(txn);
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Calling open database hook "
+ hook.getClass().getSimpleName(), start1);
}
}
});
LOG.info("Starting services");
state = STARTING_SERVICES;
dbLatch.countDown();
eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES));
db.transaction(false, txn -> {
for (Client c : clients) {
long start1 = now();
c.createLocalState(txn);
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Starting client "
+ c.getClass().getSimpleName(), start1);
}
}
});
for (Service s : services) {
start = now();
s.startService();

View File

@@ -48,7 +48,7 @@ public class PropertiesModule {
ValidationManager validationManager, ContactManager contactManager,
ClientVersioningManager clientVersioningManager,
TransportPropertyManagerImpl transportPropertyManager) {
lifecycleManager.registerClient(transportPropertyManager);
lifecycleManager.registerOpenDatabaseHook(transportPropertyManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
transportPropertyManager);
contactManager.registerContactHook(transportPropertyManager);

View File

@@ -13,11 +13,11 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId;
@@ -40,7 +40,8 @@ import javax.inject.Inject;
@Immutable
@NotNullByDefault
class TransportPropertyManagerImpl implements TransportPropertyManager,
Client, ContactHook, ClientVersioningHook, IncomingMessageHook {
OpenDatabaseHook, ContactHook, ClientVersioningHook,
IncomingMessageHook {
private final DatabaseComponent db;
private final ClientHelper clientHelper;
@@ -67,7 +68,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
}
@Override
public void createLocalState(Transaction txn) throws DbException {
public void onDatabaseOpened(Transaction txn) throws DbException {
if (db.containsGroup(txn, localGroup.getId())) return;
db.addGroup(txn, localGroup);
// Set things up for any pre-existing contacts

View File

@@ -12,10 +12,10 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
@@ -53,8 +53,8 @@ import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION;
@NotNullByDefault
class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
Service, ContactHook, IncomingMessageHook {
class ClientVersioningManagerImpl implements ClientVersioningManager,
Service, OpenDatabaseHook, ContactHook, IncomingMessageHook {
private final DatabaseComponent db;
private final ClientHelper clientHelper;
@@ -124,7 +124,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
}
@Override
public void createLocalState(Transaction txn) throws DbException {
public void onDatabaseOpened(Transaction txn) throws DbException {
if (db.containsGroup(txn, localGroup.getId())) return;
db.addGroup(txn, localGroup);
// Set things up for any pre-existing contacts

View File

@@ -34,7 +34,7 @@ public class VersioningModule {
ClientVersioningManagerImpl clientVersioningManager,
LifecycleManager lifecycleManager, ContactManager contactManager,
ValidationManager validationManager) {
lifecycleManager.registerClient(clientVersioningManager);
lifecycleManager.registerOpenDatabaseHook(clientVersioningManager);
lifecycleManager.registerService(clientVersioningManager);
contactManager.registerContactHook(clientVersioningManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.account;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.test.BrambleMockTestCase;
@@ -24,7 +25,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
@@ -47,7 +48,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
private final String encryptedKeyHex = toHexString(encryptedKey);
private final byte[] newEncryptedKey = getRandomBytes(123);
private final String newEncryptedKeyHex = toHexString(newEncryptedKey);
private final LocalAuthor localAuthor = getLocalAuthor();
private final Identity identity = getIdentity();
private final LocalAuthor localAuthor = identity.getLocalAuthor();
private final String authorName = localAuthor.getName();
private final String password = getRandomString(10);
private final String newPassword = getRandomString(10);
@@ -251,9 +253,9 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
@Test
public void testCreateAccountStoresDbKey() throws Exception {
context.checking(new Expectations() {{
oneOf(identityManager).createLocalAuthor(authorName);
will(returnValue(localAuthor));
oneOf(identityManager).registerLocalAuthor(localAuthor);
oneOf(identityManager).createIdentity(authorName);
will(returnValue(identity));
oneOf(identityManager).registerIdentity(identity);
oneOf(crypto).generateSecretKey();
will(returnValue(key));
oneOf(crypto).encryptWithPassword(key.getBytes(), password);

View File

@@ -11,16 +11,17 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.NoSuchGroupException;
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
import org.briarproject.bramble.api.db.NoSuchIdentityException;
import org.briarproject.bramble.api.db.NoSuchMessageException;
import org.briarproject.bramble.api.db.NoSuchPendingContactException;
import org.briarproject.bramble.api.db.NoSuchTransportException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.identity.event.LocalAuthorAddedEvent;
import org.briarproject.bramble.api.identity.event.LocalAuthorRemovedEvent;
import org.briarproject.bramble.api.identity.event.IdentityAddedEvent;
import org.briarproject.bramble.api.identity.event.IdentityRemovedEvent;
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings;
@@ -65,6 +66,7 @@ import java.util.concurrent.atomic.AtomicReference;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
@@ -77,8 +79,9 @@ import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getClientId;
import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTransportId;
@@ -104,6 +107,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
private final GroupId groupId;
private final Group group;
private final Author author;
private final Identity identity;
private final LocalAuthor localAuthor;
private final String alias;
private final Message message, message1;
@@ -122,7 +126,8 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
group = getGroup(clientId, majorVersion);
groupId = group.getId();
author = getAuthor();
localAuthor = getLocalAuthor();
identity = getIdentity();
localAuthor = identity.getLocalAuthor();
message = getMessage(groupId);
message1 = getMessage(groupId);
messageId = message.getId();
@@ -157,15 +162,15 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
// startTransaction()
oneOf(database).startTransaction();
will(returnValue(txn));
// registerLocalAuthor()
oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
// addIdentity()
oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(false));
oneOf(database).addLocalAuthor(txn, localAuthor);
oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class)));
oneOf(database).addIdentity(txn, identity);
oneOf(eventBus).broadcast(with(any(IdentityAddedEvent.class)));
// addContact()
oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(true));
oneOf(database).containsLocalAuthor(txn, author.getId());
oneOf(database).containsIdentity(txn, author.getId());
will(returnValue(false));
oneOf(database).containsContact(txn, author.getId(),
localAuthor.getId());
@@ -201,11 +206,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
will(returnValue(true));
oneOf(database).removeContact(txn, contactId);
oneOf(eventBus).broadcast(with(any(ContactRemovedEvent.class)));
// removeLocalAuthor()
oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
// removeIdentity()
oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(true));
oneOf(database).removeLocalAuthor(txn, localAuthor.getId());
oneOf(eventBus).broadcast(with(any(LocalAuthorRemovedEvent.class)));
oneOf(database).removeIdentity(txn, localAuthor.getId());
oneOf(eventBus).broadcast(with(any(IdentityRemovedEvent.class)));
// endTransaction()
oneOf(database).commitTransaction(txn);
// close()
@@ -216,7 +221,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
assertFalse(db.open(key, null));
db.transaction(false, transaction -> {
db.addLocalAuthor(transaction, localAuthor);
db.addIdentity(transaction, identity);
assertEquals(contactId, db.addContact(transaction, author,
localAuthor.getId(), true));
assertEquals(singletonList(contact),
@@ -227,7 +232,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
db.getGroups(transaction, clientId, majorVersion));
db.removeGroup(transaction, group);
db.removeContact(transaction, contactId);
db.removeLocalAuthor(transaction, localAuthor.getId());
db.removeIdentity(transaction, localAuthor.getId());
});
db.close();
}
@@ -432,16 +437,15 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
}
@Test
public void testVariousMethodsThrowExceptionIfLocalAuthorIsMissing()
public void testVariousMethodsThrowExceptionIfIdentityIsMissing()
throws Exception {
context.checking(new Expectations() {{
// Check whether the pseudonym is in the DB (which it's not)
exactly(3).of(database).startTransaction();
// Check whether the identity is in the DB (which it's not)
exactly(4).of(database).startTransaction();
will(returnValue(txn));
exactly(3).of(database).containsLocalAuthor(txn,
localAuthor.getId());
exactly(4).of(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(false));
exactly(3).of(database).abortTransaction(txn);
exactly(4).of(database).abortTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager);
@@ -451,23 +455,34 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
db.addContact(transaction, author, localAuthor.getId(),
true));
fail();
} catch (NoSuchLocalAuthorException expected) {
} catch (NoSuchIdentityException expected) {
// Expected
}
try {
db.transaction(false, transaction ->
db.getLocalAuthor(transaction, localAuthor.getId()));
db.getIdentity(transaction, localAuthor.getId()));
fail();
} catch (NoSuchLocalAuthorException expected) {
} catch (NoSuchIdentityException expected) {
// Expected
}
try {
db.transaction(false, transaction ->
db.removeLocalAuthor(transaction, localAuthor.getId()));
db.removeIdentity(transaction, localAuthor.getId()));
fail();
} catch (NoSuchLocalAuthorException expected) {
} catch (NoSuchIdentityException expected) {
// Expected
}
try {
byte[] publicKey = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES);
byte[] privateKey = getRandomBytes(123);
db.transaction(false, transaction ->
db.setHandshakeKeyPair(transaction, localAuthor.getId(),
publicKey, privateKey));
fail();
} catch (NoSuchIdentityException expected) {
// Expected
}
}
@@ -1403,10 +1418,10 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{
oneOf(database).startTransaction();
will(returnValue(txn));
oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(true));
// Contact is a local identity
oneOf(database).containsLocalAuthor(txn, author.getId());
oneOf(database).containsIdentity(txn, author.getId());
will(returnValue(true));
oneOf(database).abortTransaction(txn);
}});
@@ -1429,9 +1444,9 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{
oneOf(database).startTransaction();
will(returnValue(txn));
oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
oneOf(database).containsIdentity(txn, localAuthor.getId());
will(returnValue(true));
oneOf(database).containsLocalAuthor(txn, author.getId());
oneOf(database).containsIdentity(txn, author.getId());
will(returnValue(false));
// Contact already exists for this local identity
oneOf(database).containsContact(txn, author.getId(),
@@ -1454,7 +1469,6 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
}
@Test
@SuppressWarnings("unchecked")
public void testMessageDependencies() throws Exception {
int shutdownHandle = 12345;
MessageId messageId2 = new MessageId(getRandomId());

View File

@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
@@ -37,7 +38,7 @@ import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERE
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
@@ -161,11 +162,11 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
}
@Test
public void testContainsLocalAuthor() throws Exception {
String name = "containsLocalAuthor(T, AuthorId)";
public void testContainsIdentity() throws Exception {
String name = "containsIdentity(T, AuthorId)";
benchmark(name, db -> {
Connection txn = db.startTransaction();
db.containsLocalAuthor(txn, localAuthor.getId());
db.containsIdentity(txn, localAuthor.getId());
db.commitTransaction(txn);
});
}
@@ -295,21 +296,21 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
}
@Test
public void testGetLocalAuthor() throws Exception {
String name = "getLocalAuthor(T, AuthorId)";
public void testGetIdentity() throws Exception {
String name = "getIdentity(T, AuthorId)";
benchmark(name, db -> {
Connection txn = db.startTransaction();
db.getLocalAuthor(txn, localAuthor.getId());
db.getIdentity(txn, localAuthor.getId());
db.commitTransaction(txn);
});
}
@Test
public void testGetLocalAuthors() throws Exception {
String name = "getLocalAuthors(T)";
public void testGetIdentities() throws Exception {
String name = "getIdentities(T)";
benchmark(name, db -> {
Connection txn = db.startTransaction();
db.getLocalAuthors(txn);
db.getIdentities(txn);
db.commitTransaction(txn);
});
}
@@ -531,7 +532,8 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
}
void populateDatabase(Database<Connection> db) throws DbException {
localAuthor = getLocalAuthor();
Identity identity = getIdentity();
localAuthor = identity.getLocalAuthor();
clientIds = new ArrayList<>();
contacts = new ArrayList<>();
groups = new ArrayList<>();
@@ -543,7 +545,7 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
for (int i = 0; i < CLIENTS; i++) clientIds.add(getClientId());
Connection txn = db.startTransaction();
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
for (int i = 0; i < CONTACTS; i++) {
ContactId c = db.addContact(txn, getAuthor(), localAuthor.getId(),
random.nextBoolean());

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MessageDeletedException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings;
@@ -57,6 +58,7 @@ import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.briarproject.bramble.api.contact.PendingContactState.FAILED;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
import static org.briarproject.bramble.api.db.Metadata.REMOVE;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
@@ -73,9 +75,10 @@ import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getClientId;
import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getPendingContact;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
@@ -103,6 +106,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
private final int majorVersion;
private final Group group;
private final Author author;
private final Identity identity;
private final LocalAuthor localAuthor;
private final Message message;
private final MessageId messageId;
@@ -119,7 +123,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
group = getGroup(clientId, majorVersion);
groupId = group.getId();
author = getAuthor();
localAuthor = getLocalAuthor();
identity = getIdentity();
localAuthor = identity.getLocalAuthor();
message = getMessage(groupId);
messageId = message.getId();
transportId = getTransportId();
@@ -145,7 +150,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
assertFalse(db.containsContact(txn, contactId));
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertTrue(db.containsContact(txn, contactId));
@@ -208,7 +213,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -239,7 +244,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared but unvalidated message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -284,7 +289,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, an invisible group and a shared message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -335,7 +340,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and an unshared message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -366,7 +371,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -393,7 +398,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact and a visible group
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -434,7 +439,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -566,7 +571,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact and a shared group
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -586,7 +591,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
@@ -604,7 +609,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, an invisible group and a message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -623,7 +628,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact and a group
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -675,7 +680,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(emptyList(), db.getTransportKeys(txn, transportId));
// Add the contact, the transport and the transport keys
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123);
@@ -776,7 +781,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(emptyList(), db.getHandshakeKeys(txn, transportId));
// Add the contact, the transport and the handshake keys
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123);
@@ -929,7 +934,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add the contact, transport and transport keys
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123);
@@ -973,7 +978,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add the contact, transport and handshake keys
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123);
@@ -1020,7 +1025,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add the contact, transport and transport keys
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123);
@@ -1067,7 +1072,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add the contact, transport and handshake keys
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addTransport(txn, transportId, 123);
@@ -1109,14 +1114,15 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a local author - no contacts should be associated
db.addLocalAuthor(txn, localAuthor);
// Add an identity for a local author - no contacts should be
// associated
db.addIdentity(txn, identity);
// Add a contact associated with the local author
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
// Ensure contact is returned from database by Author ID
// Ensure contact is returned from database by author ID
Collection<Contact> contacts =
db.getContactsByAuthorId(txn, author.getId());
assertEquals(1, contacts.size());
@@ -1136,8 +1142,9 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add a local author - no contacts should be associated
db.addLocalAuthor(txn, localAuthor);
// Add an identity for a local author - no contacts should be
// associated
db.addIdentity(txn, identity);
Collection<ContactId> contacts =
db.getContacts(txn, localAuthor.getId());
assertEquals(emptyList(), contacts);
@@ -1148,8 +1155,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
contacts = db.getContacts(txn, localAuthor.getId());
assertEquals(singletonList(contactId), contacts);
// Remove the local author - the contact should be removed
db.removeLocalAuthor(txn, localAuthor.getId());
// Remove the identity - the contact should be removed
db.removeIdentity(txn, localAuthor.getId());
contacts = db.getContacts(txn, localAuthor.getId());
assertEquals(emptyList(), contacts);
assertFalse(db.containsContact(txn, contactId));
@@ -1164,7 +1171,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact - initially there should be no offered messages
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
assertEquals(0, db.countOfferedMessages(txn, contactId));
@@ -1748,7 +1755,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -1850,14 +1857,15 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
@Test
public void testDifferentLocalAuthorsCanHaveTheSameContact()
throws Exception {
LocalAuthor localAuthor1 = getLocalAuthor();
Identity identity1 = getIdentity();
LocalAuthor localAuthor1 = identity1.getLocalAuthor();
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
// Add two local authors
db.addLocalAuthor(txn, localAuthor);
db.addLocalAuthor(txn, localAuthor1);
// Add identities for two local authors
db.addIdentity(txn, identity);
db.addIdentity(txn, identity1);
// Add the same contact for each local author
ContactId contactId =
@@ -1881,7 +1889,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -1935,7 +1943,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
@@ -1992,7 +2000,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a group and a message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -2076,7 +2084,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -2121,7 +2129,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor);
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), true));
db.addGroup(txn, group);
@@ -2237,6 +2245,30 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.close();
}
@Test
public void testSetHandshakeKeyPair() throws Exception {
Identity withoutKeys =
new Identity(localAuthor, null, null, identity.getTimeCreated());
assertFalse(withoutKeys.hasHandshakeKeyPair());
byte[] publicKey = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES);
byte[] privateKey = getRandomBytes(123);
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
db.addIdentity(txn, withoutKeys);
Identity retrieved = db.getIdentity(txn, localAuthor.getId());
assertFalse(retrieved.hasHandshakeKeyPair());
db.setHandshakeKeyPair(txn, localAuthor.getId(), publicKey, privateKey);
retrieved = db.getIdentity(txn, localAuthor.getId());
assertTrue(retrieved.hasHandshakeKeyPair());
assertArrayEquals(publicKey, retrieved.getHandshakePublicKey());
assertArrayEquals(privateKey, retrieved.getHandshakePrivateKey());
db.commitTransaction(txn);
db.close();
}
private Database<Connection> open(boolean resume) throws Exception {
return open(resume, new TestMessageFactory(), new SystemClock());
}

View File

@@ -8,18 +8,17 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.jmock.Expectations;
import org.junit.Before;
import org.junit.Test;
import java.util.Collection;
import java.util.Collections;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.test.TestUtils.getIdentity;
import static org.junit.Assert.assertEquals;
public class IdentityManagerImplTest extends BrambleMockTestCase {
@@ -28,67 +27,100 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
private final CryptoComponent crypto = context.mock(CryptoComponent.class);
private final AuthorFactory authorFactory =
context.mock(AuthorFactory.class);
private final PublicKey publicKey = context.mock(PublicKey.class);
private final PrivateKey privateKey = context.mock(PrivateKey.class);
private final Clock clock = context.mock(Clock.class);
private final PublicKey handshakePublicKey = context.mock(PublicKey.class);
private final PrivateKey handshakePrivateKey =
context.mock(PrivateKey.class);
private final Transaction txn = new Transaction(null, false);
private final LocalAuthor localAuthor = getLocalAuthor();
private final Collection<LocalAuthor> localAuthors =
Collections.singletonList(localAuthor);
private final String authorName = localAuthor.getName();
private final KeyPair keyPair = new KeyPair(publicKey, privateKey);
private final byte[] publicKeyBytes = localAuthor.getPublicKey();
private final byte[] privateKeyBytes = localAuthor.getPrivateKey();
private IdentityManager identityManager;
private final Identity identityWithKeys = getIdentity();
private final LocalAuthor localAuthor = identityWithKeys.getLocalAuthor();
private final Identity identityWithoutKeys = new Identity(localAuthor,
null, null, identityWithKeys.getTimeCreated());
private final KeyPair handshakeKeyPair =
new KeyPair(handshakePublicKey, handshakePrivateKey);
private final byte[] handshakePublicKeyBytes =
identityWithKeys.getHandshakePublicKey();
private final byte[] handshakePrivateKeyBytes =
identityWithKeys.getHandshakePrivateKey();
private IdentityManagerImpl identityManager;
@Before
public void setUp() {
identityManager = new IdentityManagerImpl(db, crypto, authorFactory);
identityManager =
new IdentityManagerImpl(db, crypto, authorFactory, clock);
}
@Test
public void testCreateLocalAuthor() {
public void testOpenDatabaseIdentityRegistered() throws Exception {
context.checking(new Expectations() {{
oneOf(crypto).generateSignatureKeyPair();
will(returnValue(keyPair));
oneOf(publicKey).getEncoded();
will(returnValue(publicKeyBytes));
oneOf(privateKey).getEncoded();
will(returnValue(privateKeyBytes));
oneOf(authorFactory).createLocalAuthor(authorName,
publicKeyBytes, privateKeyBytes);
will(returnValue(localAuthor));
oneOf(db).addIdentity(txn, identityWithKeys);
}});
assertEquals(localAuthor,
identityManager.createLocalAuthor(authorName));
identityManager.registerIdentity(identityWithKeys);
identityManager.onDatabaseOpened(txn);
}
@Test
public void testRegisterAndStoreLocalAuthor() throws Exception {
context.checking(new DbExpectations() {{
oneOf(db).transaction(with(false), withDbRunnable(txn));
oneOf(db).addLocalAuthor(txn, localAuthor);
public void testOpenDatabaseHandshakeKeysGenerated() throws Exception {
context.checking(new Expectations() {{
oneOf(db).getIdentities(txn);
will(returnValue(singletonList(identityWithoutKeys)));
oneOf(crypto).generateAgreementKeyPair();
will(returnValue(handshakeKeyPair));
oneOf(handshakePublicKey).getEncoded();
will(returnValue(handshakePublicKeyBytes));
oneOf(handshakePrivateKey).getEncoded();
will(returnValue(handshakePrivateKeyBytes));
oneOf(db).setHandshakeKeyPair(txn, localAuthor.getId(),
handshakePublicKeyBytes, handshakePrivateKeyBytes);
}});
identityManager.registerLocalAuthor(localAuthor);
identityManager.onDatabaseOpened(txn);
}
@Test
public void testOpenDatabaseNoHandshakeKeysGenerated() throws Exception {
context.checking(new Expectations() {{
oneOf(db).getIdentities(txn);
will(returnValue(singletonList(identityWithKeys)));
}});
identityManager.onDatabaseOpened(txn);
}
@Test
public void testGetLocalAuthorIdentityRegistered() throws DbException {
identityManager.registerIdentity(identityWithKeys);
assertEquals(localAuthor, identityManager.getLocalAuthor());
identityManager.storeLocalAuthor();
}
@Test
public void testGetLocalAuthor() throws Exception {
public void testGetLocalAuthorHandshakeKeysGenerated() throws Exception {
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getLocalAuthors(txn);
will(returnValue(localAuthors));
oneOf(db).getIdentities(txn);
will(returnValue(singletonList(identityWithoutKeys)));
oneOf(crypto).generateAgreementKeyPair();
will(returnValue(handshakeKeyPair));
oneOf(handshakePublicKey).getEncoded();
will(returnValue(handshakePublicKeyBytes));
oneOf(handshakePrivateKey).getEncoded();
will(returnValue(handshakePrivateKeyBytes));
}});
assertEquals(localAuthor, identityManager.getLocalAuthor());
}
@Test
public void testGetCachedLocalAuthor() throws DbException {
identityManager.registerLocalAuthor(localAuthor);
public void testGetLocalAuthorNoHandshakeKeysGenerated() throws Exception {
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(db).getIdentities(txn);
will(returnValue(singletonList(identityWithKeys)));
}});
assertEquals(localAuthor, identityManager.getLocalAuthor());
}

View File

@@ -0,0 +1,53 @@
package org.briarproject.bramble.lifecycle;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicBoolean;
import static junit.framework.TestCase.assertTrue;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.junit.Assert.assertEquals;
public class LifecycleManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final EventBus eventBus = context.mock(EventBus.class);
private final SecretKey dbKey = getSecretKey();
private LifecycleManagerImpl lifecycleManager;
@Before
public void setUp() {
lifecycleManager = new LifecycleManagerImpl(db, eventBus);
}
@Test
public void testOpenDatabaseHooksAreCalledAtStartup() throws Exception {
Transaction txn = new Transaction(null, false);
AtomicBoolean called = new AtomicBoolean(false);
OpenDatabaseHook hook = transaction -> called.set(true);
context.checking(new DbExpectations() {{
oneOf(db).open(dbKey, lifecycleManager);
will(returnValue(false));
oneOf(db).transaction(with(false), withDbRunnable(txn));
allowing(eventBus).broadcast(with(any(LifecycleEvent.class)));
}});
lifecycleManager.registerOpenDatabaseHook(hook);
assertEquals(SUCCESS, lifecycleManager.startServices(dbKey));
assertTrue(called.get());
}
}

View File

@@ -115,7 +115,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
1, true, true);
TransportPropertyManagerImpl t = createInstance();
t.createLocalState(txn);
t.onDatabaseOpened(txn);
}
@Test
@@ -129,7 +129,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
}});
TransportPropertyManagerImpl t = createInstance();
t.createLocalState(txn);
t.onDatabaseOpened(txn);
}
@Test

View File

@@ -6,7 +6,6 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
@@ -32,7 +31,7 @@ public class TestLifecycleModule {
}
@Override
public void registerClient(Client c) {
public void registerOpenDatabaseHook(OpenDatabaseHook hook) {
}
@Override

View File

@@ -83,7 +83,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
expectAddingContact();
ClientVersioningManagerImpl c = createInstance();
c.createLocalState(txn);
c.onDatabaseOpened(txn);
}
@Test
@@ -95,7 +95,7 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
}});
ClientVersioningManagerImpl c = createInstance();
c.createLocalState(txn);
c.onDatabaseOpened(txn);
}
@Test

View File

@@ -226,7 +226,7 @@ public class AppModule {
@Singleton
RecentEmoji provideRecentEmoji(LifecycleManager lifecycleManager,
RecentEmojiImpl recentEmoji) {
lifecycleManager.registerClient(recentEmoji);
lifecycleManager.registerOpenDatabaseHook(recentEmoji);
return recentEmoji;
}
}

View File

@@ -8,11 +8,11 @@ import com.vanniktech.emoji.emoji.Emoji;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.util.StringUtils;
@@ -30,7 +30,7 @@ import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class RecentEmojiImpl implements RecentEmoji, Client {
class RecentEmojiImpl implements RecentEmoji, OpenDatabaseHook {
private static final Logger LOG =
Logger.getLogger(RecentEmojiImpl.class.getName());
@@ -72,7 +72,7 @@ class RecentEmojiImpl implements RecentEmoji, Client {
}
@Override
public void createLocalState(Transaction txn) throws DbException {
public void onDatabaseOpened(Transaction txn) throws DbException {
Settings settings =
settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
String serialized = settings.get(EMOJI_LRU_PREFERENCE);

View File

@@ -124,6 +124,12 @@ public interface BlogManager {
void registerRemoveBlogHook(RemoveBlogHook hook);
interface RemoveBlogHook {
/**
* Called when a blog is being removed.
*
* @param txn A read-write transaction
* @param b The blog that is being removed
*/
void removingBlog(Transaction txn, Blog b) throws DbException;
}

View File

@@ -100,6 +100,12 @@ public interface ForumManager {
void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException;
interface RemoveForumHook {
/**
* Called when a forum is being removed.
*
* @param txn A read-write transaction
* @param f The forum that is being removed
*/
void removingForum(Transaction txn, Forum f) throws DbException;
}
}

View File

@@ -140,9 +140,22 @@ public interface PrivateGroupManager {
@NotNullByDefault
interface PrivateGroupHook {
/**
* Called when a member is being added to a private group.
*
* @param txn A read-write transaction
* @param g The ID of the private group
* @param a The member that is being added
*/
void addingMember(Transaction txn, GroupId g, Author a)
throws DbException;
/**
* Called when a private group is being removed.
*
* @param txn A read-write transaction
* @param g The ID of the private group that is being removed
*/
void removingGroup(Transaction txn, GroupId g) throws DbException;
}

View File

@@ -18,8 +18,8 @@ import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
@@ -68,7 +68,7 @@ import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
@NotNullByDefault
class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
ContactHook, Client {
OpenDatabaseHook, ContactHook {
private final ContactManager contactManager;
private final IdentityManager identityManager;
@@ -90,7 +90,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
}
@Override
public void createLocalState(Transaction txn) throws DbException {
public void onDatabaseOpened(Transaction txn) throws DbException {
// Create our personal blog if necessary
LocalAuthor a = identityManager.getLocalAuthor(txn);
Blog b = blogFactory.createBlog(a);

View File

@@ -36,7 +36,7 @@ public class BlogModule {
BlogManager provideBlogManager(BlogManagerImpl blogManager,
LifecycleManager lifecycleManager, ContactManager contactManager,
ValidationManager validationManager) {
lifecycleManager.registerClient(blogManager);
lifecycleManager.registerOpenDatabaseHook(blogManager);
contactManager.registerContactHook(blogManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
blogManager);

View File

@@ -4,8 +4,6 @@ import com.rometools.rome.feed.synd.SyndFeed;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList;
@@ -32,17 +30,14 @@ import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_URL;
class FeedFactoryImpl implements FeedFactory {
private final CryptoComponent cryptoComponent;
private final AuthorFactory authorFactory;
private final BlogFactory blogFactory;
private final ClientHelper clientHelper;
private final Clock clock;
@Inject
FeedFactoryImpl(CryptoComponent cryptoComponent,
AuthorFactory authorFactory, BlogFactory blogFactory,
FeedFactoryImpl(AuthorFactory authorFactory, BlogFactory blogFactory,
ClientHelper clientHelper, Clock clock) {
this.cryptoComponent = cryptoComponent;
this.authorFactory = authorFactory;
this.blogFactory = blogFactory;
this.clientHelper = clientHelper;
@@ -55,10 +50,7 @@ class FeedFactoryImpl implements FeedFactory {
if (title == null) title = "RSS";
else title = StringUtils.truncateUtf8(title, MAX_AUTHOR_NAME_LENGTH);
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
LocalAuthor localAuthor = authorFactory.createLocalAuthor(title,
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
LocalAuthor localAuthor = authorFactory.createLocalAuthor(title);
Blog blog = blogFactory.createFeedBlog(localAuthor);
long added = clock.currentTimeMillis();
@@ -80,7 +72,7 @@ class FeedFactoryImpl implements FeedFactory {
BdfList authorList = d.getList(KEY_FEED_AUTHOR);
byte[] privateKey = d.getRaw(KEY_FEED_PRIVATE_KEY);
Author author = clientHelper.parseAndValidateAuthor(authorList);
LocalAuthor localAuthor = authorFactory.createLocalAuthor(
LocalAuthor localAuthor = new LocalAuthor(author.getId(),
author.getFormatVersion(), author.getName(),
author.getPublicKey(), privateKey);
Blog blog = blogFactory.createFeedBlog(localAuthor);

View File

@@ -20,11 +20,11 @@ import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.system.Clock;
@@ -32,6 +32,7 @@ import org.briarproject.bramble.api.system.Scheduler;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogManager.RemoveBlogHook;
import org.briarproject.briar.api.blog.BlogPost;
import org.briarproject.briar.api.blog.BlogPostFactory;
import org.briarproject.briar.api.feed.Feed;
@@ -75,8 +76,8 @@ import static org.briarproject.briar.util.HtmlUtils.clean;
@ThreadSafe
@NotNullByDefault
class FeedManagerImpl implements FeedManager, Client, EventListener,
BlogManager.RemoveBlogHook {
class FeedManagerImpl implements FeedManager, EventListener, OpenDatabaseHook,
RemoveBlogHook {
private static final Logger LOG =
Logger.getLogger(FeedManagerImpl.class.getName());
@@ -136,7 +137,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
}
@Override
public void createLocalState(Transaction txn) throws DbException {
public void onDatabaseOpened(Transaction txn) throws DbException {
Group g = getLocalGroup();
// Return if we've already set the local group up
if (db.containsGroup(txn, g.getId())) return;

View File

@@ -24,8 +24,7 @@ public class FeedModule {
FeedManager provideFeedManager(FeedManagerImpl feedManager,
LifecycleManager lifecycleManager, EventBus eventBus,
BlogManager blogManager) {
lifecycleManager.registerClient(feedManager);
lifecycleManager.registerOpenDatabaseHook(feedManager);
eventBus.addListener(feedManager);
blogManager.registerRemoveBlogHook(feedManager);
return feedManager;

View File

@@ -19,8 +19,8 @@ import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId;
@@ -67,7 +67,7 @@ import static org.briarproject.briar.introduction.MessageType.REQUEST;
@Immutable
@NotNullByDefault
class IntroductionManagerImpl extends ConversationClientImpl
implements IntroductionManager, Client, ContactHook,
implements IntroductionManager, OpenDatabaseHook, ContactHook,
ClientVersioningHook {
private final ClientVersioningManager clientVersioningManager;
@@ -115,7 +115,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
}
@Override
public void createLocalState(Transaction txn) throws DbException {
public void onDatabaseOpened(Transaction txn) throws DbException {
// Create a local group to store protocol sessions
if (db.containsGroup(txn, localGroup.getId())) return;
db.addGroup(txn, localGroup);

View File

@@ -51,7 +51,7 @@ public class IntroductionModule {
ConversationManager conversationManager,
ClientVersioningManager clientVersioningManager,
IntroductionManagerImpl introductionManager) {
lifecycleManager.registerClient(introductionManager);
lifecycleManager.registerOpenDatabaseHook(introductionManager);
contactManager.registerContactHook(introductionManager);
validationManager.registerIncomingMessageHook(CLIENT_ID,
MAJOR_VERSION, introductionManager);

View File

@@ -12,8 +12,8 @@ import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId;
@@ -50,7 +50,8 @@ import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ
@Immutable
@NotNullByDefault
class MessagingManagerImpl extends ConversationClientImpl
implements MessagingManager, Client, ContactHook, ClientVersioningHook {
implements MessagingManager, OpenDatabaseHook, ContactHook,
ClientVersioningHook {
private final ClientVersioningManager clientVersioningManager;
private final ContactGroupFactory contactGroupFactory;
@@ -66,7 +67,7 @@ class MessagingManagerImpl extends ConversationClientImpl
}
@Override
public void createLocalState(Transaction txn) throws DbException {
public void onDatabaseOpened(Transaction txn) throws DbException {
// Create a local group to indicate that we've set this client up
Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
MAJOR_VERSION);

View File

@@ -58,7 +58,7 @@ public class MessagingModule {
ConversationManager conversationManager,
ClientVersioningManager clientVersioningManager,
MessagingManagerImpl messagingManager) {
lifecycleManager.registerClient(messagingManager);
lifecycleManager.registerOpenDatabaseHook(messagingManager);
contactManager.registerContactHook(messagingManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
messagingManager);

View File

@@ -14,8 +14,8 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId;
@@ -62,7 +62,7 @@ import static org.briarproject.briar.privategroup.invitation.Role.PEER;
@Immutable
@NotNullByDefault
class GroupInvitationManagerImpl extends ConversationClientImpl
implements GroupInvitationManager, Client, ContactHook,
implements GroupInvitationManager, OpenDatabaseHook, ContactHook,
PrivateGroupHook, ClientVersioningHook {
private final ClientVersioningManager clientVersioningManager;
@@ -101,7 +101,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
}
@Override
public void createLocalState(Transaction txn) throws DbException {
public void onDatabaseOpened(Transaction txn) throws DbException {
// Create a local group to indicate that we've set this client up
Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
MAJOR_VERSION);

View File

@@ -42,7 +42,7 @@ public class GroupInvitationModule {
PrivateGroupManager privateGroupManager,
ConversationManager conversationManager,
ClientVersioningManager clientVersioningManager) {
lifecycleManager.registerClient(groupInvitationManager);
lifecycleManager.registerOpenDatabaseHook(groupInvitationManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
groupInvitationManager);
contactManager.registerContactHook(groupInvitationManager);

View File

@@ -13,8 +13,8 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
@@ -55,7 +55,7 @@ import static org.briarproject.briar.sharing.State.SHARING;
@NotNullByDefault
abstract class SharingManagerImpl<S extends Shareable>
extends ConversationClientImpl
implements SharingManager<S>, Client, ContactHook,
implements SharingManager<S>, OpenDatabaseHook, ContactHook,
ClientVersioningHook {
private final ClientVersioningManager clientVersioningManager;
@@ -92,7 +92,7 @@ abstract class SharingManagerImpl<S extends Shareable>
protected abstract int getShareableMajorVersion();
@Override
public void createLocalState(Transaction txn) throws DbException {
public void onDatabaseOpened(Transaction txn) throws DbException {
// Create a local group to indicate that we've set this client up
Group localGroup = contactGroupFactory.createLocalGroup(getClientId(),
getMajorVersion());

View File

@@ -76,7 +76,7 @@ public class SharingModule {
ConversationManager conversationManager, BlogManager blogManager,
ClientVersioningManager clientVersioningManager,
BlogSharingManagerImpl blogSharingManager) {
lifecycleManager.registerClient(blogSharingManager);
lifecycleManager.registerOpenDatabaseHook(blogSharingManager);
contactManager.registerContactHook(blogSharingManager);
validationManager.registerIncomingMessageHook(
BlogSharingManager.CLIENT_ID, BlogSharingManager.MAJOR_VERSION,
@@ -135,7 +135,7 @@ public class SharingModule {
ConversationManager conversationManager, ForumManager forumManager,
ClientVersioningManager clientVersioningManager,
ForumSharingManagerImpl forumSharingManager) {
lifecycleManager.registerClient(forumSharingManager);
lifecycleManager.registerOpenDatabaseHook(forumSharingManager);
contactManager.registerContactHook(forumSharingManager);
validationManager.registerIncomingMessageHook(
ForumSharingManager.CLIENT_ID,

View File

@@ -5,8 +5,6 @@ import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.db.DatabaseComponent;
@@ -74,7 +72,6 @@ public class TestDataCreatorImpl implements TestDataCreator {
private final ClientHelper clientHelper;
private final MessageTracker messageTracker;
private final BlogPostFactory blogPostFactory;
private final CryptoComponent cryptoComponent;
private final DatabaseComponent db;
private final IdentityManager identityManager;
@@ -94,9 +91,8 @@ public class TestDataCreatorImpl implements TestDataCreator {
TestDataCreatorImpl(AuthorFactory authorFactory, Clock clock,
PrivateMessageFactory privateMessageFactory,
ClientHelper clientHelper, MessageTracker messageTracker,
BlogPostFactory blogPostFactory, CryptoComponent cryptoComponent,
DatabaseComponent db, IdentityManager identityManager,
ContactManager contactManager,
BlogPostFactory blogPostFactory, DatabaseComponent db,
IdentityManager identityManager, ContactManager contactManager,
TransportPropertyManager transportPropertyManager,
MessagingManager messagingManager, BlogManager blogManager,
ForumManager forumManager, @IoExecutor Executor ioExecutor) {
@@ -106,7 +102,6 @@ public class TestDataCreatorImpl implements TestDataCreator {
this.clientHelper = clientHelper;
this.messageTracker = messageTracker;
this.blogPostFactory = blogPostFactory;
this.cryptoComponent = cryptoComponent;
this.db = db;
this.identityManager = identityManager;
this.contactManager = contactManager;
@@ -150,14 +145,14 @@ public class TestDataCreatorImpl implements TestDataCreator {
List<Contact> contacts = new ArrayList<>(numContacts);
LocalAuthor localAuthor = identityManager.getLocalAuthor();
for (int i = 0; i < numContacts; i++) {
LocalAuthor author = getRandomAuthor();
Contact contact = addContact(localAuthor.getId(), author);
LocalAuthor remote = getRandomAuthor();
Contact contact = addContact(localAuthor.getId(), remote);
contacts.add(contact);
}
return contacts;
}
private Contact addContact(AuthorId localAuthorId, LocalAuthor author)
private Contact addContact(AuthorId localAuthorId, LocalAuthor remote)
throws DbException {
// prepare to add contact
@@ -173,7 +168,7 @@ public class TestDataCreatorImpl implements TestDataCreator {
Transaction txn = db.startTransaction(false);
try {
ContactId contactId = contactManager
.addContact(txn, author, localAuthorId, secretKey,
.addContact(txn, remote, localAuthorId, secretKey,
timestamp, true, verified, true);
if (random.nextBoolean()) {
contactManager
@@ -187,24 +182,18 @@ public class TestDataCreatorImpl implements TestDataCreator {
}
if (LOG.isLoggable(INFO)) {
LOG.info("Added contact " + author.getName());
LOG.info("Added contact " + remote.getName());
LOG.info("with transport properties: " + props.toString());
}
localAuthors.put(contact, author);
localAuthors.put(contact, remote);
return contact;
}
@Override
public Contact addContact(String name) throws DbException {
LocalAuthor localAuthor = identityManager.getLocalAuthor();
return addContact(localAuthor.getId(), getAuthor(name));
}
private LocalAuthor getAuthor(String name) {
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded();
return authorFactory.createLocalAuthor(name, publicKey, privateKey);
LocalAuthor remote = authorFactory.createLocalAuthor(name);
return addContact(localAuthor.getId(), remote);
}
private String getRandomAuthorName() {
@@ -213,7 +202,7 @@ public class TestDataCreatorImpl implements TestDataCreator {
}
private LocalAuthor getRandomAuthor() {
return getAuthor(getRandomAuthorName());
return authorFactory.createLocalAuthor(getRandomAuthorName());
}
private SecretKey getSecretKey() {

View File

@@ -112,7 +112,7 @@ public class BlogManagerImplTest extends BriarTestCase {
}
@Test
public void testCreateLocalState() throws DbException {
public void testOpenDatabaseHook() throws DbException {
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
@@ -123,7 +123,7 @@ public class BlogManagerImplTest extends BriarTestCase {
oneOf(db).addGroup(txn, blog1.getGroup());
}});
blogManager.createLocalState(txn);
blogManager.onDatabaseOpened(txn);
context.assertIsSatisfied();
}

View File

@@ -21,9 +21,7 @@ import java.util.Iterator;
import static junit.framework.Assert.assertNotNull;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.blog.MessageType.COMMENT;
import static org.briarproject.briar.api.blog.MessageType.POST;
@@ -50,10 +48,8 @@ public class BlogManagerIntegrationTest
author0 = identityManager0.getLocalAuthor();
author1 = identityManager1.getLocalAuthor();
rssAuthor = c0.getAuthorFactory().createLocalAuthor(
getRandomString(MAX_AUTHOR_NAME_LENGTH),
getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
getRandomBytes(123));
String rssTitle = getRandomString(MAX_AUTHOR_NAME_LENGTH);
rssAuthor = c0.getAuthorFactory().createLocalAuthor(rssTitle);
blogManager0 = c0.getBlogManager();
blogManager1 = c1.getBlogManager();

View File

@@ -1,7 +1,7 @@
package org.briarproject.briar.feed;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.contact.ContactModule;
import org.briarproject.bramble.crypto.CryptoExecutorModule;
@@ -51,8 +51,8 @@ public class FeedManagerIntegrationTest extends BriarTestCase {
injectEagerSingletons(component);
IdentityManager identityManager = component.getIdentityManager();
LocalAuthor localAuthor = identityManager.createLocalAuthor("feedTest");
identityManager.registerLocalAuthor(localAuthor);
Identity identity = identityManager.createIdentity("feedTest");
identityManager.registerIdentity(identity);
lifecycleManager = component.getLifecycleManager();
lifecycleManager.startServices(getSecretKey());

View File

@@ -58,10 +58,8 @@ public class IntroductionCryptoIntegrationTest extends BrambleTestCase {
crypto = new IntroductionCryptoImpl(cryptoComponent, clientHelper);
introducer = getRealAuthor(authorFactory);
LocalAuthor introducee1 =
getRealLocalAuthor(cryptoComponent, authorFactory);
LocalAuthor introducee2 =
getRealLocalAuthor(cryptoComponent, authorFactory);
LocalAuthor introducee1 = getRealLocalAuthor(authorFactory);
LocalAuthor introducee2 = getRealLocalAuthor(authorFactory);
boolean isAlice =
crypto.isAlice(introducee1.getId(), introducee2.getId());
alice = isAlice ? introducee1 : introducee2;

View File

@@ -2,7 +2,6 @@ package org.briarproject.briar.messaging;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.GroupId;
@@ -70,12 +69,8 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
@Test
public void testForumPostFitsIntoRecord() throws Exception {
// Create a maximum-length author
int formatVersion = Integer.MAX_VALUE;
String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
LocalAuthor author = authorFactory.createLocalAuthor(formatVersion,
authorName, authorPublic, privateKey.getEncoded());
LocalAuthor author = authorFactory.createLocalAuthor(authorName);
// Create a maximum-length forum post
GroupId groupId = new GroupId(getRandomId());
long timestamp = Long.MAX_VALUE;

View File

@@ -6,8 +6,8 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
@@ -75,13 +75,14 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
@Test
public void testWriteAndRead() throws Exception {
// Create the identities
LocalAuthor aliceAuthor =
alice.getIdentityManager().createLocalAuthor("Alice");
LocalAuthor bobAuthor =
bob.getIdentityManager().createLocalAuthor("Bob");
Identity aliceIdentity =
alice.getIdentityManager().createIdentity("Alice");
Identity bobIdentity = bob.getIdentityManager().createIdentity("Bob");
// Set up the devices and get the contact IDs
ContactId bobId = setUp(alice, aliceAuthor, bobAuthor, true);
ContactId aliceId = setUp(bob, bobAuthor, aliceAuthor, false);
ContactId bobId = setUp(alice, aliceIdentity,
bobIdentity.getLocalAuthor(), true);
ContactId aliceId = setUp(bob, bobIdentity,
aliceIdentity.getLocalAuthor(), false);
// Add a private message listener
PrivateMessageListener listener = new PrivateMessageListener();
bob.getEventBus().addListener(listener);
@@ -100,10 +101,10 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
}
private ContactId setUp(SimplexMessagingIntegrationTestComponent device,
LocalAuthor local, Author remote, boolean alice) throws Exception {
Identity local, Author remote, boolean alice) throws Exception {
// Add an identity for the user
IdentityManager identityManager = device.getIdentityManager();
identityManager.registerLocalAuthor(local);
identityManager.registerIdentity(local);
// Start the lifecycle manager
LifecycleManager lifecycleManager = device.getLifecycleManager();
lifecycleManager.startServices(getSecretKey());

View File

@@ -149,7 +149,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
}
@Test
public void testCreateLocalStateFirstTime() throws Exception {
public void testDatabaseOpenHookFirstTime() throws Exception {
context.checking(new Expectations() {{
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID,
MAJOR_VERSION);
@@ -161,11 +161,11 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
will(returnValue(Collections.singletonList(contact)));
}});
expectAddingContact(contact);
groupInvitationManager.createLocalState(txn);
groupInvitationManager.onDatabaseOpened(txn);
}
@Test
public void testCreateLocalStateSubsequentTime() throws Exception {
public void testOpenDatabaseHookSubsequentTime() throws Exception {
context.checking(new Expectations() {{
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID,
MAJOR_VERSION);
@@ -173,7 +173,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
oneOf(db).containsGroup(txn, localGroup.getId());
will(returnValue(true));
}});
groupInvitationManager.createLocalState(txn);
groupInvitationManager.onDatabaseOpened(txn);
}
private void expectAddingContact(Contact c) throws Exception {

View File

@@ -94,7 +94,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
}
@Test
public void testCreateLocalStateFirstTimeWithExistingContact()
public void testOpenDatabaseHookFirstTimeWithExistingContact()
throws Exception {
Transaction txn = new Transaction(null, false);
@@ -113,7 +113,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
// Set things up for the contact
expectAddingContact(txn);
blogSharingManager.createLocalState(txn);
blogSharingManager.onDatabaseOpened(txn);
}
private void expectAddingContact(Transaction txn) throws Exception {
@@ -149,7 +149,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
}
@Test
public void testCreateLocalStateSubsequentTime() throws Exception {
public void testOpenDatabaseHookSubsequentTime() throws Exception {
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
@@ -161,7 +161,7 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
will(returnValue(true));
}});
blogSharingManager.createLocalState(txn);
blogSharingManager.onDatabaseOpened(txn);
}
@Test

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -274,12 +275,15 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
}
private void createAndRegisterIdentities() {
author0 = identityManager0.createLocalAuthor(AUTHOR0);
identityManager0.registerLocalAuthor(author0);
author1 = identityManager1.createLocalAuthor(AUTHOR1);
identityManager1.registerLocalAuthor(author1);
author2 = identityManager2.createLocalAuthor(AUTHOR2);
identityManager2.registerLocalAuthor(author2);
Identity identity0 = identityManager0.createIdentity(AUTHOR0);
identityManager0.registerIdentity(identity0);
author0 = identity0.getLocalAuthor();
Identity identity1 = identityManager0.createIdentity(AUTHOR1);
identityManager1.registerIdentity(identity1);
author1 = identity1.getLocalAuthor();
Identity identity2 = identityManager0.createIdentity(AUTHOR2);
identityManager2.registerIdentity(identity2);
author2 = identity2.getLocalAuthor();
}
protected void addDefaultContacts() throws Exception {

View File

@@ -1,7 +1,5 @@
package org.briarproject.briar.test;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
@@ -10,8 +8,7 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
@@ -27,23 +24,20 @@ public class BriarTestUtils {
}
public static void assertGroupCount(MessageTracker tracker, GroupId g,
long msgCount, long unreadCount) throws DbException {
long msgCount, long unreadCount) throws DbException {
GroupCount c1 = tracker.getGroupCount(g);
assertEquals(msgCount, c1.getMsgCount());
assertEquals(unreadCount, c1.getUnreadCount());
}
public static Author getRealAuthor(AuthorFactory authorFactory) {
return authorFactory.createAuthor(getRandomString(5),
getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
return authorFactory.createLocalAuthor(name);
}
public static LocalAuthor getRealLocalAuthor(
CryptoComponent cryptoComponent, AuthorFactory authorFactory) {
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
return authorFactory.createLocalAuthor(getRandomString(5),
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
public static LocalAuthor getRealLocalAuthor(AuthorFactory authorFactory) {
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
return authorFactory.createLocalAuthor(name);
}
}