mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Merge branch '209-contact-manager-hooks' into 'master'
Run hooks when contacts/identities are added/removed. #209 Now that the sync layer is separated from its clients, actions that used to occur within the DatabaseComponent, such as adding or removing private groups when adding or removing a contact, have to be handled by clients. This patch adds a mechanism for clients to register hooks with the Contact/IdentityManager to be run when contacts/identities are being added/removed. The MessagingManager uses ContactManager hooks for adding and removing private groups, and the ContactManager uses IdentityManager hooks for removing contacts when an identity is removed. I've also changed the way some components register with the LifecycleManager and EventBus. This merge request depends on !64 - I'll merge them at the same time. Closes #209. See merge request !68
This commit is contained in:
@@ -1,23 +1,24 @@
|
||||
package org.briarproject.android;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import android.app.Application;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
import org.briarproject.api.android.AndroidExecutor;
|
||||
import org.briarproject.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.api.android.ReferenceManager;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.db.DatabaseConfig;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.ui.UiCallback;
|
||||
|
||||
import android.app.Application;
|
||||
import java.io.File;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
|
||||
public class AndroidModule extends AbstractModule {
|
||||
|
||||
@@ -81,9 +82,10 @@ public class AndroidModule extends AbstractModule {
|
||||
|
||||
@Provides @Singleton
|
||||
AndroidNotificationManager getAndroidNotificationManager(
|
||||
LifecycleManager lifecycleManager,
|
||||
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||
AndroidNotificationManagerImpl notificationManager) {
|
||||
lifecycleManager.register(notificationManager);
|
||||
eventBus.addListener(notificationManager);
|
||||
return notificationManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.EventListener;
|
||||
import org.briarproject.api.event.MessageValidatedEvent;
|
||||
import org.briarproject.api.event.SettingsUpdatedEvent;
|
||||
import org.briarproject.api.forum.ForumManager;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
@@ -46,7 +46,7 @@ import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
EventListener {
|
||||
Service, EventListener {
|
||||
|
||||
private static final int PRIVATE_MESSAGE_NOTIFICATION_ID = 3;
|
||||
private static final int FORUM_POST_NOTIFICATION_ID = 4;
|
||||
@@ -60,7 +60,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final Executor dbExecutor;
|
||||
private final EventBus eventBus;
|
||||
private final MessagingManager messagingManager;
|
||||
private final ForumManager forumManager;
|
||||
private final AndroidExecutor androidExecutor;
|
||||
@@ -79,20 +78,19 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
@Inject
|
||||
public AndroidNotificationManagerImpl(DatabaseComponent db,
|
||||
@DatabaseExecutor Executor dbExecutor, EventBus eventBus,
|
||||
@DatabaseExecutor Executor dbExecutor,
|
||||
MessagingManager messagingManager, ForumManager forumManager,
|
||||
AndroidExecutor androidExecutor, Application app) {
|
||||
this.db = db;
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.eventBus = eventBus;
|
||||
this.messagingManager = messagingManager;
|
||||
this.forumManager = forumManager;
|
||||
this.androidExecutor = androidExecutor;
|
||||
appContext = app.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
eventBus.addListener(this);
|
||||
loadSettings();
|
||||
return true;
|
||||
}
|
||||
@@ -110,8 +108,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
eventBus.removeListener(this);
|
||||
clearNotifications();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package org.briarproject.api.android;
|
||||
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
/** Manages notifications for private messages and forum posts. */
|
||||
public interface AndroidNotificationManager extends Service {
|
||||
public interface AndroidNotificationManager {
|
||||
|
||||
void showPrivateMessageNotification(GroupId g);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.api.contact;
|
||||
|
||||
import org.briarproject.api.db.StorageStatus;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
|
||||
@@ -8,11 +9,14 @@ public class Contact {
|
||||
private final ContactId id;
|
||||
private final Author author;
|
||||
private final AuthorId localAuthorId;
|
||||
private final StorageStatus status;
|
||||
|
||||
public Contact(ContactId id, Author author, AuthorId localAuthorId) {
|
||||
public Contact(ContactId id, Author author, AuthorId localAuthorId,
|
||||
StorageStatus status) {
|
||||
this.id = id;
|
||||
this.author = author;
|
||||
this.localAuthorId = localAuthorId;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public ContactId getId() {
|
||||
@@ -27,6 +31,10 @@ public class Contact {
|
||||
return localAuthorId;
|
||||
}
|
||||
|
||||
public StorageStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
@@ -34,7 +42,6 @@ public class Contact {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Contact) return id.equals(((Contact) o).id);
|
||||
return false;
|
||||
return o instanceof Contact && id.equals(((Contact) o).id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ public class ContactId {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof ContactId) return id == ((ContactId) o).id;
|
||||
return false;
|
||||
return o instanceof ContactId && id == ((ContactId) o).id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,12 @@ import java.util.Collection;
|
||||
|
||||
public interface ContactManager {
|
||||
|
||||
/** Registers a hook to be called whenever a contact is added. */
|
||||
void registerAddContactHook(AddContactHook hook);
|
||||
|
||||
/** Registers a hook to be called whenever a contact is removed. */
|
||||
void registerRemoveContactHook(RemoveContactHook hook);
|
||||
|
||||
/**
|
||||
* Stores a contact associated with the given local and remote pseudonyms,
|
||||
* and returns an ID for the contact.
|
||||
@@ -22,4 +28,12 @@ public interface ContactManager {
|
||||
|
||||
/** Removes a contact and all associated state. */
|
||||
void removeContact(ContactId c) throws DbException;
|
||||
|
||||
interface AddContactHook {
|
||||
void addingContact(ContactId c);
|
||||
}
|
||||
|
||||
interface RemoveContactHook {
|
||||
void removingContact(ContactId c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +152,9 @@ public interface DatabaseComponent {
|
||||
/** Returns all contacts. */
|
||||
Collection<Contact> getContacts() throws DbException;
|
||||
|
||||
/** Returns all contacts associated with the given local pseudonym. */
|
||||
Collection<ContactId> getContacts(AuthorId a) throws DbException;
|
||||
|
||||
/** Returns the group with the given ID, if the user subscribes to it. */
|
||||
Group getGroup(GroupId g) throws DbException;
|
||||
|
||||
@@ -297,6 +300,13 @@ public interface DatabaseComponent {
|
||||
*/
|
||||
void removeTransport(TransportId t) throws DbException;
|
||||
|
||||
/** Sets the status of the given contact. */
|
||||
void setContactStatus(ContactId c, StorageStatus s) throws DbException;
|
||||
|
||||
/** Sets the status of the given local pseudonym. */
|
||||
void setLocalAuthorStatus(AuthorId a, StorageStatus s)
|
||||
throws DbException;
|
||||
|
||||
/** Marks the given message as valid or invalid. */
|
||||
void setMessageValidity(Message m, ClientId c, boolean valid)
|
||||
throws DbException;
|
||||
|
||||
21
briar-api/src/org/briarproject/api/db/StorageStatus.java
Normal file
21
briar-api/src/org/briarproject/api/db/StorageStatus.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package org.briarproject.api.db;
|
||||
|
||||
public enum StorageStatus {
|
||||
|
||||
ADDING(0), ACTIVE(1), REMOVING(2);
|
||||
|
||||
private final int value;
|
||||
|
||||
StorageStatus(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static StorageStatus fromValue(int value) {
|
||||
for (StorageStatus s : values()) if (s.value == value) return s;
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,12 @@ import java.util.Collection;
|
||||
|
||||
public interface IdentityManager {
|
||||
|
||||
/** Registers a hook to be called whenever a local pseudonym is added. */
|
||||
void registerAddIdentityHook(AddIdentityHook hook);
|
||||
|
||||
/** Registers a hook to be called whenever a local pseudonym is removed. */
|
||||
void registerRemoveIdentityHook(RemoveIdentityHook hook);
|
||||
|
||||
/** Stores a local pseudonym. */
|
||||
void addLocalAuthor(LocalAuthor a) throws DbException;
|
||||
|
||||
@@ -17,4 +23,12 @@ public interface IdentityManager {
|
||||
|
||||
/** Removes a local pseudonym and all associated state. */
|
||||
void removeLocalAuthor(AuthorId a) throws DbException;
|
||||
|
||||
interface AddIdentityHook {
|
||||
void addingIdentity(AuthorId a);
|
||||
}
|
||||
|
||||
interface RemoveIdentityHook {
|
||||
void removingIdentity(AuthorId a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
package org.briarproject.api.identity;
|
||||
|
||||
import org.briarproject.api.db.StorageStatus;
|
||||
|
||||
/** A pseudonym for the local user. */
|
||||
public class LocalAuthor extends Author {
|
||||
|
||||
private final byte[] privateKey;
|
||||
private final long created;
|
||||
private final StorageStatus status;
|
||||
|
||||
public LocalAuthor(AuthorId id, String name, byte[] publicKey,
|
||||
byte[] privateKey, long created) {
|
||||
byte[] privateKey, long created, StorageStatus status) {
|
||||
super(id, name, publicKey);
|
||||
this.privateKey = privateKey;
|
||||
this.created = created;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/** Returns the private key used to generate the pseudonym's signatures. */
|
||||
@@ -18,7 +22,16 @@ public class LocalAuthor extends Author {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time the pseudonym was created, in milliseconds since the
|
||||
* Unix epoch.
|
||||
*/
|
||||
public long getTimeCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
/** Returns the status of the pseudonym. */
|
||||
public StorageStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,6 @@ public interface MessagingManager {
|
||||
/** Returns the unique ID of the messaging client. */
|
||||
ClientId getClientId();
|
||||
|
||||
/**
|
||||
* Informs the messaging manager that a new contact has been added.
|
||||
* Creates a private conversation with the contact.
|
||||
*/
|
||||
void addContact(ContactId c) throws DbException;
|
||||
|
||||
/** Stores a local private message. */
|
||||
void addLocalMessage(PrivateMessage m) throws DbException;
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package org.briarproject.api.plugins;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Responsible for starting transport plugins at startup, stopping them at
|
||||
* shutdown, and providing access to plugins for exchanging invitations.
|
||||
*/
|
||||
public interface PluginManager extends Service {
|
||||
public interface PluginManager {
|
||||
|
||||
/**
|
||||
* Returns the plugin for the given transport, or null if no such plugin
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package org.briarproject.api.sync;
|
||||
|
||||
import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
|
||||
public interface MessageValidator extends Service {
|
||||
public interface MessageValidator {
|
||||
|
||||
/**
|
||||
* Validates the given message and returns its metadata if the message
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
package org.briarproject.api.sync;
|
||||
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
|
||||
/**
|
||||
* Responsible for managing message validators and passing them messages to
|
||||
* validate.
|
||||
*/
|
||||
public interface ValidationManager extends Service {
|
||||
public interface ValidationManager {
|
||||
|
||||
enum Status {
|
||||
|
||||
UNKNOWN(0), INVALID(1), VALID(2);
|
||||
|
||||
private final int value;
|
||||
|
||||
Status(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Status fromValue(int value) {
|
||||
for (Status s : values()) if (s.value == value) return s;
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the message validator for the given client. */
|
||||
void setMessageValidator(ClientId c, MessageValidator v);
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.briarproject.api.transport;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -11,7 +10,7 @@ import java.util.Collection;
|
||||
* Responsible for managing transport keys and recognising the pseudo-random
|
||||
* tags of incoming streams.
|
||||
*/
|
||||
public interface KeyManager extends Service {
|
||||
public interface KeyManager {
|
||||
|
||||
/**
|
||||
* Informs the key manager that a new contact has been added. Derives and
|
||||
|
||||
@@ -7,38 +7,127 @@ import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.NoSuchContactException;
|
||||
import org.briarproject.api.event.ContactAddedEvent;
|
||||
import org.briarproject.api.event.ContactRemovedEvent;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.IdentityManager.RemoveIdentityHook;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
class ContactManagerImpl implements ContactManager {
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.db.StorageStatus.ACTIVE;
|
||||
import static org.briarproject.api.db.StorageStatus.ADDING;
|
||||
import static org.briarproject.api.db.StorageStatus.REMOVING;
|
||||
|
||||
class ContactManagerImpl implements ContactManager, Service,
|
||||
RemoveIdentityHook {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(ContactManagerImpl.class.getName());
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final EventBus eventBus;
|
||||
private final List<AddContactHook> addHooks;
|
||||
private final List<RemoveContactHook> removeHooks;
|
||||
|
||||
@Inject
|
||||
ContactManagerImpl(DatabaseComponent db) {
|
||||
ContactManagerImpl(DatabaseComponent db, EventBus eventBus) {
|
||||
this.db = db;
|
||||
this.eventBus = eventBus;
|
||||
addHooks = new CopyOnWriteArrayList<AddContactHook>();
|
||||
removeHooks = new CopyOnWriteArrayList<RemoveContactHook>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
// Finish adding/removing any partly added/removed contacts
|
||||
try {
|
||||
for (Contact c : db.getContacts()) {
|
||||
if (c.getStatus().equals(ADDING)) {
|
||||
for (AddContactHook hook : addHooks)
|
||||
hook.addingContact(c.getId());
|
||||
db.setContactStatus(c.getId(), ACTIVE);
|
||||
eventBus.broadcast(new ContactAddedEvent(c.getId()));
|
||||
} else if (c.getStatus().equals(REMOVING)) {
|
||||
for (RemoveContactHook hook : removeHooks)
|
||||
hook.removingContact(c.getId());
|
||||
db.removeContact(c.getId());
|
||||
eventBus.broadcast(new ContactRemovedEvent(c.getId()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAddContactHook(AddContactHook hook) {
|
||||
addHooks.add(hook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRemoveContactHook(RemoveContactHook hook) {
|
||||
removeHooks.add(hook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactId addContact(Author remote, AuthorId local)
|
||||
throws DbException {
|
||||
return db.addContact(remote, local);
|
||||
ContactId c = db.addContact(remote, local);
|
||||
for (AddContactHook hook : addHooks) hook.addingContact(c);
|
||||
db.setContactStatus(c, ACTIVE);
|
||||
eventBus.broadcast(new ContactAddedEvent(c));
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Contact getContact(ContactId c) throws DbException {
|
||||
return db.getContact(c);
|
||||
Contact contact = db.getContact(c);
|
||||
if (contact.getStatus().equals(ACTIVE)) return contact;
|
||||
throw new NoSuchContactException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Contact> getContacts() throws DbException {
|
||||
return db.getContacts();
|
||||
Collection<Contact> contacts = db.getContacts();
|
||||
// Filter out any contacts that are being added or removed
|
||||
List<Contact> active = new ArrayList<Contact>(contacts.size());
|
||||
for (Contact c : contacts)
|
||||
if (c.getStatus().equals(ACTIVE)) active.add(c);
|
||||
return Collections.unmodifiableList(active);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeContact(ContactId c) throws DbException {
|
||||
db.setContactStatus(c, REMOVING);
|
||||
for (RemoveContactHook hook : removeHooks) hook.removingContact(c);
|
||||
db.removeContact(c);
|
||||
eventBus.broadcast(new ContactRemovedEvent(c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removingIdentity(AuthorId a) {
|
||||
// Remove any contacts of the local pseudonym that's being removed
|
||||
try {
|
||||
for (ContactId c : db.getContacts(a)) removeContact(c);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
package org.briarproject.contact;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.identity.IdentityManager;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
public class ContactModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ContactManager.class).to(ContactManagerImpl.class);
|
||||
protected void configure() {}
|
||||
|
||||
@Provides @Singleton
|
||||
ContactManager getContactManager(LifecycleManager lifecycleManager,
|
||||
IdentityManager identityManager,
|
||||
ContactManagerImpl contactManager) {
|
||||
lifecycleManager.register(contactManager);
|
||||
identityManager.registerRemoveIdentityHook(contactManager);
|
||||
return contactManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.db.StorageStatus;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
@@ -334,7 +335,7 @@ interface Database<T> {
|
||||
* Locking: read
|
||||
*/
|
||||
Collection<MessageStatus> getMessageStatus(T txn, ContactId c, GroupId g)
|
||||
throws DbException;
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the status of the given message with respect to the given
|
||||
@@ -343,7 +344,7 @@ interface Database<T> {
|
||||
* Locking: read
|
||||
*/
|
||||
MessageStatus getMessageStatus(T txn, ContactId c, MessageId m)
|
||||
throws DbException;
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the IDs of some messages received from the given contact that
|
||||
@@ -388,7 +389,7 @@ interface Database<T> {
|
||||
* Locking: read.
|
||||
*/
|
||||
Collection<MessageId> getMessagesToValidate(T txn, ClientId c)
|
||||
throws DbException;
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the message with the given ID, in serialised form.
|
||||
@@ -631,7 +632,27 @@ interface Database<T> {
|
||||
*/
|
||||
void resetExpiryTime(T txn, ContactId c, MessageId m) throws DbException;
|
||||
|
||||
/** Marks the given message as valid or invalid. */
|
||||
/**
|
||||
* Sets the status of the given contact.
|
||||
* <p>
|
||||
* Locking: write.
|
||||
*/
|
||||
void setContactStatus(T txn, ContactId c, StorageStatus s)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the status of the given local pseudonym.
|
||||
* <p>
|
||||
* Locking: write.
|
||||
*/
|
||||
void setLocalAuthorStatus(T txn, AuthorId a, StorageStatus s)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Marks the given message as valid or invalid.
|
||||
* <p>
|
||||
* Locking: write.
|
||||
*/
|
||||
void setMessageValidity(T txn, MessageId m, boolean valid)
|
||||
throws DbException;
|
||||
|
||||
|
||||
@@ -16,11 +16,8 @@ import org.briarproject.api.db.NoSuchLocalAuthorException;
|
||||
import org.briarproject.api.db.NoSuchMessageException;
|
||||
import org.briarproject.api.db.NoSuchSubscriptionException;
|
||||
import org.briarproject.api.db.NoSuchTransportException;
|
||||
import org.briarproject.api.event.ContactAddedEvent;
|
||||
import org.briarproject.api.event.ContactRemovedEvent;
|
||||
import org.briarproject.api.db.StorageStatus;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.LocalAuthorAddedEvent;
|
||||
import org.briarproject.api.event.LocalAuthorRemovedEvent;
|
||||
import org.briarproject.api.event.LocalSubscriptionsUpdatedEvent;
|
||||
import org.briarproject.api.event.LocalTransportsUpdatedEvent;
|
||||
import org.briarproject.api.event.MessageAddedEvent;
|
||||
@@ -147,7 +144,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
|
||||
public ContactId addContact(Author remote, AuthorId local)
|
||||
throws DbException {
|
||||
ContactId c;
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
@@ -156,8 +152,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
throw new ContactExistsException();
|
||||
if (!db.containsLocalAuthor(txn, local))
|
||||
throw new NoSuchLocalAuthorException();
|
||||
c = db.addContact(txn, remote, local);
|
||||
ContactId c = db.addContact(txn, remote, local);
|
||||
db.commitTransaction(txn);
|
||||
return c;
|
||||
} catch (DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
@@ -165,8 +162,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
eventBus.broadcast(new ContactAddedEvent(c));
|
||||
return c;
|
||||
}
|
||||
|
||||
public void addContactGroup(ContactId c, Group g) throws DbException {
|
||||
@@ -221,7 +216,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
eventBus.broadcast(new LocalAuthorAddedEvent(a.getId()));
|
||||
}
|
||||
|
||||
public void addLocalMessage(Message m, ClientId c, Metadata meta)
|
||||
@@ -575,6 +569,25 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<ContactId> getContacts(AuthorId a) throws DbException {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if (!db.containsLocalAuthor(txn, a))
|
||||
throw new NoSuchLocalAuthorException();
|
||||
Collection<ContactId> contacts = db.getContacts(txn, a);
|
||||
db.commitTransaction(txn);
|
||||
return contacts;
|
||||
} catch (DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Group getGroup(GroupId g) throws DbException {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
@@ -1219,7 +1232,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
eventBus.broadcast(new ContactRemovedEvent(c));
|
||||
}
|
||||
|
||||
public void removeGroup(Group g) throws DbException {
|
||||
@@ -1246,14 +1258,12 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
}
|
||||
|
||||
public void removeLocalAuthor(AuthorId a) throws DbException {
|
||||
Collection<ContactId> affected;
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if (!db.containsLocalAuthor(txn, a))
|
||||
throw new NoSuchLocalAuthorException();
|
||||
affected = db.getContacts(txn, a);
|
||||
db.removeLocalAuthor(txn, a);
|
||||
db.commitTransaction(txn);
|
||||
} catch (DbException e) {
|
||||
@@ -1263,9 +1273,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
for (ContactId c : affected)
|
||||
eventBus.broadcast(new ContactRemovedEvent(c));
|
||||
eventBus.broadcast(new LocalAuthorRemovedEvent(a));
|
||||
}
|
||||
|
||||
public void removeTransport(TransportId t) throws DbException {
|
||||
@@ -1287,6 +1294,44 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
eventBus.broadcast(new TransportRemovedEvent(t));
|
||||
}
|
||||
|
||||
public void setContactStatus(ContactId c, StorageStatus s)
|
||||
throws DbException {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if (!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
db.setContactStatus(txn, c, s);
|
||||
db.commitTransaction(txn);
|
||||
} catch (DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setLocalAuthorStatus(AuthorId a, StorageStatus s)
|
||||
throws DbException {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if (!db.containsLocalAuthor(txn, a))
|
||||
throw new NoSuchLocalAuthorException();
|
||||
db.setLocalAuthorStatus(txn, a, s);
|
||||
db.commitTransaction(txn);
|
||||
} catch (DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMessageValidity(Message m, ClientId c, boolean valid)
|
||||
throws DbException {
|
||||
lock.writeLock().lock();
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.db.DbClosedException;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.db.StorageStatus;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
@@ -51,7 +52,11 @@ import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.db.Metadata.REMOVE;
|
||||
import static org.briarproject.api.db.StorageStatus.ADDING;
|
||||
import static org.briarproject.api.sync.SyncConstants.MAX_SUBSCRIPTIONS;
|
||||
import static org.briarproject.api.sync.ValidationManager.Status.INVALID;
|
||||
import static org.briarproject.api.sync.ValidationManager.Status.UNKNOWN;
|
||||
import static org.briarproject.api.sync.ValidationManager.Status.VALID;
|
||||
import static org.briarproject.db.ExponentialBackoff.calculateExpiry;
|
||||
|
||||
/**
|
||||
@@ -60,12 +65,8 @@ import static org.briarproject.db.ExponentialBackoff.calculateExpiry;
|
||||
*/
|
||||
abstract class JdbcDatabase implements Database<Connection> {
|
||||
|
||||
private static final int SCHEMA_VERSION = 14;
|
||||
private static final int MIN_SCHEMA_VERSION = 14;
|
||||
|
||||
private static final int VALIDATION_UNKNOWN = 0;
|
||||
private static final int VALIDATION_INVALID = 1;
|
||||
private static final int VALIDATION_VALID = 2;
|
||||
private static final int SCHEMA_VERSION = 16;
|
||||
private static final int MIN_SCHEMA_VERSION = 16;
|
||||
|
||||
private static final String CREATE_SETTINGS =
|
||||
"CREATE TABLE settings"
|
||||
@@ -81,6 +82,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " publicKey BINARY NOT NULL,"
|
||||
+ " privateKey BINARY NOT NULL,"
|
||||
+ " created BIGINT NOT NULL,"
|
||||
+ " status INT NOT NULL,"
|
||||
+ " PRIMARY KEY (authorId))";
|
||||
|
||||
private static final String CREATE_CONTACTS =
|
||||
@@ -90,6 +92,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " name VARCHAR NOT NULL,"
|
||||
+ " publicKey BINARY NOT NULL,"
|
||||
+ " localAuthorId HASH NOT NULL,"
|
||||
+ " status INT NOT NULL,"
|
||||
+ " PRIMARY KEY (contactId),"
|
||||
+ " UNIQUE (authorId),"
|
||||
+ " FOREIGN KEY (localAuthorId)"
|
||||
@@ -533,13 +536,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
try {
|
||||
// Create a contact row
|
||||
String sql = "INSERT INTO contacts"
|
||||
+ " (authorId, name, publicKey, localAuthorId)"
|
||||
+ " VALUES (?, ?, ?, ?)";
|
||||
+ " (authorId, name, publicKey, localAuthorId, status)"
|
||||
+ " VALUES (?, ?, ?, ?, ?)";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, remote.getId().getBytes());
|
||||
ps.setString(2, remote.getName());
|
||||
ps.setBytes(3, remote.getPublicKey());
|
||||
ps.setBytes(4, local.getBytes());
|
||||
ps.setInt(5, ADDING.getValue());
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
@@ -717,15 +721,16 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "INSERT INTO localAuthors"
|
||||
+ " (authorId, name, publicKey, privateKey, created)"
|
||||
+ " VALUES (?, ?, ?, ?, ?)";
|
||||
String sql = "INSERT INTO localAuthors (authorId, name, publicKey,"
|
||||
+ " privateKey, created, status)"
|
||||
+ " VALUES (?, ?, ?, ?, ?, ?)";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, a.getId().getBytes());
|
||||
ps.setString(2, a.getName());
|
||||
ps.setBytes(3, a.getPublicKey());
|
||||
ps.setBytes(4, a.getPrivateKey());
|
||||
ps.setLong(5, a.getTimeCreated());
|
||||
ps.setInt(6, a.getStatus().getValue());
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
@@ -747,7 +752,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.setBytes(2, m.getGroupId().getBytes());
|
||||
ps.setLong(3, m.getTimestamp());
|
||||
ps.setBoolean(4, local);
|
||||
ps.setInt(5, local ? VALIDATION_VALID : VALIDATION_UNKNOWN);
|
||||
ps.setInt(5, local ? VALID.getValue() : UNKNOWN.getValue());
|
||||
byte[] raw = m.getRaw();
|
||||
ps.setInt(6, raw.length);
|
||||
ps.setBytes(7, raw);
|
||||
@@ -1192,7 +1197,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT authorId, name, publicKey, localAuthorId"
|
||||
String sql = "SELECT authorId, name, publicKey, localAuthorId,"
|
||||
+ " status"
|
||||
+ " FROM contacts"
|
||||
+ " WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
@@ -1203,10 +1209,11 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
String name = rs.getString(2);
|
||||
byte[] publicKey = rs.getBytes(3);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(4));
|
||||
StorageStatus status = StorageStatus.fromValue(rs.getInt(5));
|
||||
rs.close();
|
||||
ps.close();
|
||||
Author author = new Author(authorId, name, publicKey);
|
||||
return new Contact(c, author, localAuthorId);
|
||||
return new Contact(c, author, localAuthorId, status);
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
@@ -1240,7 +1247,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT contactId, authorId, name, publicKey,"
|
||||
+ " localAuthorId"
|
||||
+ " localAuthorId, status"
|
||||
+ " FROM contacts";
|
||||
ps = txn.prepareStatement(sql);
|
||||
rs = ps.executeQuery();
|
||||
@@ -1252,7 +1259,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
byte[] publicKey = rs.getBytes(4);
|
||||
Author author = new Author(authorId, name, publicKey);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(5));
|
||||
contacts.add(new Contact(contactId, author, localAuthorId));
|
||||
StorageStatus status = StorageStatus.fromValue(rs.getInt(6));
|
||||
contacts.add(new Contact(contactId, author, localAuthorId,
|
||||
status));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -1339,7 +1348,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT name, publicKey, privateKey, created"
|
||||
String sql = "SELECT name, publicKey, privateKey, created, status"
|
||||
+ " FROM localAuthors"
|
||||
+ " WHERE authorId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
@@ -1350,8 +1359,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
byte[] publicKey = rs.getBytes(2);
|
||||
byte[] privateKey = rs.getBytes(3);
|
||||
long created = rs.getLong(4);
|
||||
StorageStatus status = StorageStatus.fromValue(rs.getInt(5));
|
||||
LocalAuthor localAuthor = new LocalAuthor(a, name, publicKey,
|
||||
privateKey, created);
|
||||
privateKey, created, status);
|
||||
if (rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -1368,7 +1378,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT authorId, name, publicKey, privateKey, created"
|
||||
String sql = "SELECT authorId, name, publicKey, privateKey,"
|
||||
+ " created, status"
|
||||
+ " FROM localAuthors";
|
||||
ps = txn.prepareStatement(sql);
|
||||
rs = ps.executeQuery();
|
||||
@@ -1379,8 +1390,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
byte[] publicKey = rs.getBytes(3);
|
||||
byte[] privateKey = rs.getBytes(4);
|
||||
long created = rs.getLong(5);
|
||||
StorageStatus status = StorageStatus.fromValue(rs.getInt(6));
|
||||
authors.add(new LocalAuthor(authorId, name, publicKey,
|
||||
privateKey, created));
|
||||
privateKey, created, status));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -1612,7 +1624,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " ORDER BY timestamp DESC LIMIT ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
ps.setInt(2, VALIDATION_VALID);
|
||||
ps.setInt(2, VALID.getValue());
|
||||
ps.setLong(3, now);
|
||||
ps.setInt(4, maxMessages);
|
||||
rs = ps.executeQuery();
|
||||
@@ -1674,7 +1686,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " ORDER BY timestamp DESC";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
ps.setInt(2, VALIDATION_VALID);
|
||||
ps.setInt(2, VALID.getValue());
|
||||
ps.setLong(3, now);
|
||||
rs = ps.executeQuery();
|
||||
List<MessageId> ids = new ArrayList<MessageId>();
|
||||
@@ -1704,7 +1716,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " JOIN groups AS g ON m.groupId = g.groupId"
|
||||
+ " WHERE valid = ? AND clientId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, VALIDATION_UNKNOWN);
|
||||
ps.setInt(1, UNKNOWN.getValue());
|
||||
ps.setBytes(2, c.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
List<MessageId> ids = new ArrayList<MessageId>();
|
||||
@@ -1799,7 +1811,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " ORDER BY timestamp DESC";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
ps.setInt(2, VALIDATION_VALID);
|
||||
ps.setInt(2, VALID.getValue());
|
||||
ps.setLong(3, now);
|
||||
rs = ps.executeQuery();
|
||||
List<MessageId> ids = new ArrayList<MessageId>();
|
||||
@@ -1846,7 +1858,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT c.contactId, authorId, c.name, publicKey,"
|
||||
+ " localAuthorId"
|
||||
+ " localAuthorId, status"
|
||||
+ " FROM contacts AS c"
|
||||
+ " JOIN contactGroups AS cg"
|
||||
+ " ON c.contactId = cg.contactId"
|
||||
@@ -1862,7 +1874,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
byte[] publicKey = rs.getBytes(4);
|
||||
Author author = new Author(authorId, name, publicKey);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(5));
|
||||
contacts.add(new Contact(contactId, author, localAuthorId));
|
||||
StorageStatus status = StorageStatus.fromValue(rs.getInt(6));
|
||||
contacts.add(new Contact(contactId, author, localAuthorId,
|
||||
status));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -2390,7 +2404,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void mergeSettings(Connection txn, Settings s, String namespace) throws DbException {
|
||||
public void mergeSettings(Connection txn, Settings s, String namespace)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
// Update any settings that already exist
|
||||
@@ -2687,13 +2702,48 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void setContactStatus(Connection txn, ContactId c, StorageStatus s)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE contacts SET status = ? WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, s.getValue());
|
||||
ps.setInt(2, c.getInt());
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setLocalAuthorStatus(Connection txn, AuthorId a,
|
||||
StorageStatus s) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE localAuthors SET status = ?"
|
||||
+ " WHERE authorId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, s.getValue());
|
||||
ps.setBytes(2, a.getBytes());
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMessageValidity(Connection txn, MessageId m, boolean valid)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE messages SET valid = ? WHERE messageId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, valid ? VALIDATION_VALID : VALIDATION_INVALID);
|
||||
ps.setInt(1, valid ? VALID.getValue() : INVALID.getValue());
|
||||
ps.setBytes(2, m.getBytes());
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected < 0) throw new DbStateException();
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.briarproject.api.data.ObjectReader;
|
||||
import org.briarproject.api.forum.ForumManager;
|
||||
import org.briarproject.api.forum.ForumPostFactory;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
@@ -26,16 +25,17 @@ public class ForumModule extends AbstractModule {
|
||||
}
|
||||
|
||||
@Provides @Singleton
|
||||
ForumPostValidator getValidator(LifecycleManager lifecycleManager,
|
||||
CryptoComponent crypto, ValidationManager validationManager,
|
||||
ForumPostValidator getValidator(ValidationManager validationManager,
|
||||
ForumManager forumManager, CryptoComponent crypto,
|
||||
BdfReaderFactory bdfReaderFactory,
|
||||
BdfWriterFactory bdfWriterFactory,
|
||||
ObjectReader<Author> authorReader, MetadataEncoder metadataEncoder,
|
||||
Clock clock) {
|
||||
ForumPostValidator validator = new ForumPostValidator(crypto,
|
||||
validationManager, bdfReaderFactory, bdfWriterFactory,
|
||||
authorReader, metadataEncoder, clock);
|
||||
lifecycleManager.register(validator);
|
||||
bdfReaderFactory, bdfWriterFactory, authorReader,
|
||||
metadataEncoder, clock);
|
||||
validationManager.setMessageValidator(forumManager.getClientId(),
|
||||
validator);
|
||||
return validator;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.sync.MessageValidator;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -34,7 +33,6 @@ import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENG
|
||||
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||
import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||
import static org.briarproject.forum.ForumManagerImpl.CLIENT_ID;
|
||||
|
||||
class ForumPostValidator implements MessageValidator {
|
||||
|
||||
@@ -42,7 +40,6 @@ class ForumPostValidator implements MessageValidator {
|
||||
Logger.getLogger(ForumPostValidator.class.getName());
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final ValidationManager validationManager;
|
||||
private final BdfReaderFactory bdfReaderFactory;
|
||||
private final BdfWriterFactory bdfWriterFactory;
|
||||
private final ObjectReader<Author> authorReader;
|
||||
@@ -52,13 +49,11 @@ class ForumPostValidator implements MessageValidator {
|
||||
|
||||
@Inject
|
||||
ForumPostValidator(CryptoComponent crypto,
|
||||
ValidationManager validationManager,
|
||||
BdfReaderFactory bdfReaderFactory,
|
||||
BdfWriterFactory bdfWriterFactory,
|
||||
ObjectReader<Author> authorReader,
|
||||
MetadataEncoder metadataEncoder, Clock clock) {
|
||||
this.crypto = crypto;
|
||||
this.validationManager = validationManager;
|
||||
this.bdfReaderFactory = bdfReaderFactory;
|
||||
this.bdfWriterFactory = bdfWriterFactory;
|
||||
this.authorReader = authorReader;
|
||||
@@ -67,17 +62,6 @@ class ForumPostValidator implements MessageValidator {
|
||||
keyParser = crypto.getSignatureKeyParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
validationManager.setMessageValidator(CLIENT_ID, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metadata validateMessage(Message m) {
|
||||
// Reject the message if it's too far in the future
|
||||
|
||||
@@ -4,38 +4,114 @@ import com.google.inject.Inject;
|
||||
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.NoSuchLocalAuthorException;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.LocalAuthorAddedEvent;
|
||||
import org.briarproject.api.event.LocalAuthorRemovedEvent;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.IdentityManager;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
class IdentityManagerImpl implements IdentityManager {
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.db.StorageStatus.ACTIVE;
|
||||
import static org.briarproject.api.db.StorageStatus.ADDING;
|
||||
import static org.briarproject.api.db.StorageStatus.REMOVING;
|
||||
|
||||
class IdentityManagerImpl implements IdentityManager, Service {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(IdentityManagerImpl.class.getName());
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final EventBus eventBus;
|
||||
private final List<AddIdentityHook> addHooks;
|
||||
private final List<RemoveIdentityHook> removeHooks;
|
||||
|
||||
@Inject
|
||||
IdentityManagerImpl(DatabaseComponent db) {
|
||||
IdentityManagerImpl(DatabaseComponent db, EventBus eventBus) {
|
||||
this.db = db;
|
||||
this.eventBus = eventBus;
|
||||
addHooks = new CopyOnWriteArrayList<AddIdentityHook>();
|
||||
removeHooks = new CopyOnWriteArrayList<RemoveIdentityHook>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
// Finish adding/removing any partly added/removed pseudonyms
|
||||
try {
|
||||
for (LocalAuthor a : db.getLocalAuthors()) {
|
||||
if (a.getStatus().equals(ADDING)) {
|
||||
for (AddIdentityHook hook : addHooks)
|
||||
hook.addingIdentity(a.getId());
|
||||
db.setLocalAuthorStatus(a.getId(), ACTIVE);
|
||||
eventBus.broadcast(new LocalAuthorAddedEvent(a.getId()));
|
||||
} else if (a.getStatus().equals(REMOVING)) {
|
||||
for (RemoveIdentityHook hook : removeHooks)
|
||||
hook.removingIdentity(a.getId());
|
||||
db.removeLocalAuthor(a.getId());
|
||||
eventBus.broadcast(new LocalAuthorRemovedEvent(a.getId()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAddIdentityHook(AddIdentityHook hook) {
|
||||
addHooks.add(hook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRemoveIdentityHook(RemoveIdentityHook hook) {
|
||||
removeHooks.add(hook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLocalAuthor(LocalAuthor a) throws DbException {
|
||||
db.addLocalAuthor(a);
|
||||
for (AddIdentityHook hook : addHooks) hook.addingIdentity(a.getId());
|
||||
db.setLocalAuthorStatus(a.getId(), ACTIVE);
|
||||
eventBus.broadcast(new LocalAuthorAddedEvent(a.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalAuthor getLocalAuthor(AuthorId a) throws DbException {
|
||||
return db.getLocalAuthor(a);
|
||||
LocalAuthor author = db.getLocalAuthor(a);
|
||||
if (author.getStatus().equals(ACTIVE)) return author;
|
||||
throw new NoSuchLocalAuthorException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<LocalAuthor> getLocalAuthors() throws DbException {
|
||||
return db.getLocalAuthors();
|
||||
Collection<LocalAuthor> authors = db.getLocalAuthors();
|
||||
// Filter out any pseudonyms that are being added or removed
|
||||
List<LocalAuthor> active = new ArrayList<LocalAuthor>(authors.size());
|
||||
for (LocalAuthor a : authors)
|
||||
if (a.getStatus().equals(ACTIVE)) active.add(a);
|
||||
return Collections.unmodifiableList(active);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLocalAuthor(AuthorId a) throws DbException {
|
||||
db.setLocalAuthorStatus(a, REMOVING);
|
||||
for (RemoveIdentityHook hook : removeHooks) hook.removingIdentity(a);
|
||||
db.removeLocalAuthor(a);
|
||||
eventBus.broadcast(new LocalAuthorRemovedEvent(a));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorFactory;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
@@ -48,7 +47,7 @@ class AliceConnector extends Connector {
|
||||
StreamWriterFactory streamWriterFactory,
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
ContactManager contactManager, MessagingManager messagingManager,
|
||||
ContactManager contactManager,
|
||||
TransportPropertyManager transportPropertyManager, Clock clock,
|
||||
boolean reuseConnection, ConnectorGroup group, DuplexPlugin plugin,
|
||||
LocalAuthor localAuthor,
|
||||
@@ -57,9 +56,8 @@ class AliceConnector extends Connector {
|
||||
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
|
||||
streamWriterFactory, authorFactory, groupFactory,
|
||||
keyManager, connectionManager, contactManager,
|
||||
messagingManager, transportPropertyManager, clock,
|
||||
reuseConnection, group, plugin, localAuthor, localProps,
|
||||
random);
|
||||
transportPropertyManager, clock, reuseConnection, group,
|
||||
plugin, localAuthor, localProps, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorFactory;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
@@ -48,7 +47,7 @@ class BobConnector extends Connector {
|
||||
StreamWriterFactory streamWriterFactory,
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
ContactManager contactManager, MessagingManager messagingManager,
|
||||
ContactManager contactManager,
|
||||
TransportPropertyManager transportPropertyManager, Clock clock,
|
||||
boolean reuseConnection, ConnectorGroup group, DuplexPlugin plugin,
|
||||
LocalAuthor localAuthor,
|
||||
@@ -57,9 +56,8 @@ class BobConnector extends Connector {
|
||||
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
|
||||
streamWriterFactory, authorFactory, groupFactory,
|
||||
keyManager, connectionManager, contactManager,
|
||||
messagingManager, transportPropertyManager, clock,
|
||||
reuseConnection, group, plugin, localAuthor, localProps,
|
||||
random);
|
||||
transportPropertyManager, clock, reuseConnection, group,
|
||||
plugin, localAuthor, localProps, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorFactory;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
@@ -65,7 +64,6 @@ abstract class Connector extends Thread {
|
||||
protected final KeyManager keyManager;
|
||||
protected final ConnectionManager connectionManager;
|
||||
protected final ContactManager contactManager;
|
||||
protected final MessagingManager messagingManager;
|
||||
protected final TransportPropertyManager transportPropertyManager;
|
||||
protected final Clock clock;
|
||||
protected final boolean reuseConnection;
|
||||
@@ -89,7 +87,7 @@ abstract class Connector extends Thread {
|
||||
StreamWriterFactory streamWriterFactory,
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
ContactManager contactManager, MessagingManager messagingManager,
|
||||
ContactManager contactManager,
|
||||
TransportPropertyManager transportPropertyManager, Clock clock,
|
||||
boolean reuseConnection, ConnectorGroup group, DuplexPlugin plugin,
|
||||
LocalAuthor localAuthor,
|
||||
@@ -106,7 +104,6 @@ abstract class Connector extends Thread {
|
||||
this.keyManager = keyManager;
|
||||
this.connectionManager = connectionManager;
|
||||
this.contactManager = contactManager;
|
||||
this.messagingManager = messagingManager;
|
||||
this.transportPropertyManager = transportPropertyManager;
|
||||
this.clock = clock;
|
||||
this.reuseConnection = reuseConnection;
|
||||
@@ -287,8 +284,6 @@ abstract class Connector extends Thread {
|
||||
// Derive transport keys for each transport shared with the contact
|
||||
keyManager.addContact(contactId, remoteProps.keySet(), master,
|
||||
timestamp, alice);
|
||||
// Create a private messaging conversation
|
||||
messagingManager.addContact(contactId);
|
||||
}
|
||||
|
||||
protected void tryToClose(DuplexTransportConnection conn,
|
||||
|
||||
@@ -16,7 +16,6 @@ import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.invitation.InvitationListener;
|
||||
import org.briarproject.api.invitation.InvitationState;
|
||||
import org.briarproject.api.invitation.InvitationTask;
|
||||
import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.PluginManager;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
@@ -58,7 +57,6 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
private final ConnectionManager connectionManager;
|
||||
private final IdentityManager identityManager;
|
||||
private final ContactManager contactManager;
|
||||
private final MessagingManager messagingManager;
|
||||
private final TransportPropertyManager transportPropertyManager;
|
||||
private final Clock clock;
|
||||
private final PluginManager pluginManager;
|
||||
@@ -85,7 +83,6 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
IdentityManager identityManager, ContactManager contactManager,
|
||||
MessagingManager messagingManager,
|
||||
TransportPropertyManager transportPropertyManager, Clock clock,
|
||||
PluginManager pluginManager, AuthorId localAuthorId,
|
||||
int localInvitationCode, int remoteInvitationCode,
|
||||
@@ -102,7 +99,6 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
this.connectionManager = connectionManager;
|
||||
this.identityManager = identityManager;
|
||||
this.contactManager = contactManager;
|
||||
this.messagingManager = messagingManager;
|
||||
this.transportPropertyManager = transportPropertyManager;
|
||||
this.clock = clock;
|
||||
this.pluginManager = pluginManager;
|
||||
@@ -201,8 +197,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
return new AliceConnector(crypto, bdfReaderFactory, bdfWriterFactory,
|
||||
streamReaderFactory, streamWriterFactory, authorFactory,
|
||||
groupFactory, keyManager, connectionManager, contactManager,
|
||||
messagingManager, transportPropertyManager, clock,
|
||||
reuseConnection, this, plugin, localAuthor, localProps, random);
|
||||
transportPropertyManager, clock, reuseConnection, this, plugin,
|
||||
localAuthor, localProps, random);
|
||||
}
|
||||
|
||||
private Connector createBobConnector(DuplexPlugin plugin,
|
||||
@@ -213,8 +209,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
||||
return new BobConnector(crypto, bdfReaderFactory, bdfWriterFactory,
|
||||
streamReaderFactory, streamWriterFactory, authorFactory,
|
||||
groupFactory, keyManager, connectionManager, contactManager,
|
||||
messagingManager, transportPropertyManager, clock,
|
||||
reuseConnection, this, plugin, localAuthor, localProps, random);
|
||||
transportPropertyManager, clock, reuseConnection, this, plugin,
|
||||
localAuthor, localProps, random);
|
||||
}
|
||||
|
||||
public void localConfirmationSucceeded() {
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.IdentityManager;
|
||||
import org.briarproject.api.invitation.InvitationTask;
|
||||
import org.briarproject.api.invitation.InvitationTaskFactory;
|
||||
import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.PluginManager;
|
||||
import org.briarproject.api.property.TransportPropertyManager;
|
||||
@@ -34,7 +33,6 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
|
||||
private final ConnectionManager connectionManager;
|
||||
private final IdentityManager identityManager;
|
||||
private final ContactManager contactManager;
|
||||
private final MessagingManager messagingManager;
|
||||
private final TransportPropertyManager transportPropertyManager;
|
||||
private final Clock clock;
|
||||
private final PluginManager pluginManager;
|
||||
@@ -47,7 +45,6 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
|
||||
AuthorFactory authorFactory, GroupFactory groupFactory,
|
||||
KeyManager keyManager, ConnectionManager connectionManager,
|
||||
IdentityManager identityManager, ContactManager contactManager,
|
||||
MessagingManager messagingManager,
|
||||
TransportPropertyManager transportPropertyManager,
|
||||
Clock clock, PluginManager pluginManager) {
|
||||
this.crypto = crypto;
|
||||
@@ -61,7 +58,6 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
|
||||
this.connectionManager = connectionManager;
|
||||
this.identityManager = identityManager;
|
||||
this.contactManager = contactManager;
|
||||
this.messagingManager = messagingManager;
|
||||
this.transportPropertyManager = transportPropertyManager;
|
||||
this.clock = clock;
|
||||
this.pluginManager = pluginManager;
|
||||
@@ -72,8 +68,7 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
|
||||
return new ConnectorGroup(crypto, bdfReaderFactory, bdfWriterFactory,
|
||||
streamReaderFactory, streamWriterFactory, authorFactory,
|
||||
groupFactory, keyManager, connectionManager, identityManager,
|
||||
contactManager, messagingManager, transportPropertyManager,
|
||||
clock, pluginManager, localAuthorId, localCode, remoteCode,
|
||||
reuseConnection);
|
||||
contactManager, transportPropertyManager, clock, pluginManager,
|
||||
localAuthorId, localCode, remoteCode, reuseConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.UniqueId;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager.AddContactHook;
|
||||
import org.briarproject.api.contact.ContactManager.RemoveContactHook;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfReader;
|
||||
import org.briarproject.api.data.BdfReaderFactory;
|
||||
@@ -42,7 +44,8 @@ import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
|
||||
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||
|
||||
class MessagingManagerImpl implements MessagingManager {
|
||||
class MessagingManagerImpl implements MessagingManager, AddContactHook,
|
||||
RemoveContactHook {
|
||||
|
||||
static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
|
||||
"6bcdc006c0910b0f44e40644c3b31f1a"
|
||||
@@ -72,21 +75,20 @@ class MessagingManagerImpl implements MessagingManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientId getClientId() {
|
||||
return CLIENT_ID;
|
||||
public void addingContact(ContactId c) {
|
||||
try {
|
||||
// Create the conversation group
|
||||
Group g = getConversationGroup(db.getContact(c));
|
||||
// Subscribe to the group and share it with the contact
|
||||
db.addGroup(g);
|
||||
db.addContactGroup(c, g);
|
||||
db.setVisibility(g.getId(), Collections.singletonList(c));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addContact(ContactId c) throws DbException {
|
||||
// Create the conversation group
|
||||
Group conversation = createConversationGroup(db.getContact(c));
|
||||
// Subscribe to the group and share it with the contact
|
||||
db.addGroup(conversation);
|
||||
db.addContactGroup(c, conversation);
|
||||
db.setVisibility(conversation.getId(), Collections.singletonList(c));
|
||||
}
|
||||
|
||||
private Group createConversationGroup(Contact c) {
|
||||
private Group getConversationGroup(Contact c) {
|
||||
AuthorId local = c.getLocalAuthorId();
|
||||
AuthorId remote = c.getAuthor().getId();
|
||||
byte[] descriptor = createGroupDescriptor(local, remote);
|
||||
@@ -113,6 +115,20 @@ class MessagingManagerImpl implements MessagingManager {
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removingContact(ContactId c) {
|
||||
try {
|
||||
db.removeGroup(getConversationGroup(db.getContact(c)));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientId getClientId() {
|
||||
return CLIENT_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLocalMessage(PrivateMessage m) throws DbException {
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
@@ -131,9 +147,9 @@ class MessagingManagerImpl implements MessagingManager {
|
||||
|
||||
@Override
|
||||
public ContactId getContactId(GroupId g) throws DbException {
|
||||
// TODO: Make this more efficient
|
||||
// TODO: Use metadata to attach the contact ID to the group
|
||||
for (Contact c : db.getContacts()) {
|
||||
Group conversation = createConversationGroup(c);
|
||||
Group conversation = getConversationGroup(c);
|
||||
if (conversation.getId().equals(g)) return c.getId();
|
||||
}
|
||||
throw new NoSuchContactException();
|
||||
@@ -141,7 +157,7 @@ class MessagingManagerImpl implements MessagingManager {
|
||||
|
||||
@Override
|
||||
public GroupId getConversationId(ContactId c) throws DbException {
|
||||
return createConversationGroup(db.getContact(c)).getId();
|
||||
return getConversationGroup(db.getContact(c)).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,9 +3,9 @@ package org.briarproject.messaging;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.data.BdfReaderFactory;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
@@ -17,18 +17,26 @@ public class MessagingModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(MessagingManager.class).to(MessagingManagerImpl.class);
|
||||
bind(PrivateMessageFactory.class).to(PrivateMessageFactoryImpl.class);
|
||||
}
|
||||
|
||||
@Provides @Singleton
|
||||
PrivateMessageValidator getValidator(LifecycleManager lifecycleManager,
|
||||
ValidationManager validationManager,
|
||||
PrivateMessageValidator getValidator(ValidationManager validationManager,
|
||||
MessagingManager messagingManager,
|
||||
BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
|
||||
Clock clock) {
|
||||
PrivateMessageValidator validator = new PrivateMessageValidator(
|
||||
validationManager, bdfReaderFactory, metadataEncoder, clock);
|
||||
lifecycleManager.register(validator);
|
||||
bdfReaderFactory, metadataEncoder, clock);
|
||||
validationManager.setMessageValidator(messagingManager.getClientId(),
|
||||
validator);
|
||||
return validator;
|
||||
}
|
||||
|
||||
@Provides @Singleton
|
||||
MessagingManager getMessagingManager(ContactManager contactManager,
|
||||
MessagingManagerImpl messagingManager) {
|
||||
contactManager.registerAddContactHook(messagingManager);
|
||||
contactManager.registerRemoveContactHook(messagingManager);
|
||||
return messagingManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.sync.MessageValidator;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
import org.briarproject.api.system.Clock;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -23,39 +22,24 @@ import static org.briarproject.api.messaging.MessagingConstants.MAX_CONTENT_TYPE
|
||||
import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
|
||||
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||
import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||
import static org.briarproject.messaging.MessagingManagerImpl.CLIENT_ID;
|
||||
|
||||
class PrivateMessageValidator implements MessageValidator {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(PrivateMessageValidator.class.getName());
|
||||
|
||||
private final ValidationManager validationManager;
|
||||
private final BdfReaderFactory bdfReaderFactory;
|
||||
private final MetadataEncoder metadataEncoder;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
PrivateMessageValidator(ValidationManager validationManager,
|
||||
BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
|
||||
Clock clock) {
|
||||
this.validationManager = validationManager;
|
||||
PrivateMessageValidator(BdfReaderFactory bdfReaderFactory,
|
||||
MetadataEncoder metadataEncoder, Clock clock) {
|
||||
this.bdfReaderFactory = bdfReaderFactory;
|
||||
this.metadataEncoder = metadataEncoder;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
validationManager.setMessageValidator(CLIENT_ID, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metadata validateMessage(Message m) {
|
||||
// Reject the message if it's too far in the future
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.TransportDisabledEvent;
|
||||
import org.briarproject.api.event.TransportEnabledEvent;
|
||||
import org.briarproject.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
import org.briarproject.api.plugins.ConnectionManager;
|
||||
import org.briarproject.api.plugins.Plugin;
|
||||
import org.briarproject.api.plugins.PluginCallback;
|
||||
@@ -46,7 +47,7 @@ import javax.inject.Inject;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
class PluginManagerImpl implements PluginManager {
|
||||
class PluginManagerImpl implements PluginManager, Service {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(PluginManagerImpl.class.getName());
|
||||
@@ -88,6 +89,7 @@ class PluginManagerImpl implements PluginManager {
|
||||
duplexPlugins = new CopyOnWriteArrayList<DuplexPlugin>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
// Instantiate and start the simplex plugins
|
||||
LOG.info("Starting simplex plugins");
|
||||
@@ -115,6 +117,7 @@ class PluginManagerImpl implements PluginManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
// Stop the poller
|
||||
LOG.info("Stopping poller");
|
||||
|
||||
@@ -14,6 +14,8 @@ import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.api.db.StorageStatus.ADDING;
|
||||
|
||||
class AuthorFactoryImpl implements AuthorFactory {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
@@ -35,7 +37,7 @@ class AuthorFactoryImpl implements AuthorFactory {
|
||||
public LocalAuthor createLocalAuthor(String name, byte[] publicKey,
|
||||
byte[] privateKey) {
|
||||
return new LocalAuthor(getId(name, publicKey), name, publicKey,
|
||||
privateKey, clock.currentTimeMillis());
|
||||
privateKey, clock.currentTimeMillis(), ADDING);
|
||||
}
|
||||
|
||||
private AuthorId getId(String name, byte[] publicKey) {
|
||||
|
||||
@@ -4,9 +4,9 @@ import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
import org.briarproject.api.data.ObjectReader;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorFactory;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.sync.MessageFactory;
|
||||
@@ -48,9 +48,9 @@ public class SyncModule extends AbstractModule {
|
||||
}
|
||||
|
||||
@Provides @Singleton
|
||||
ValidationManager getValidationManager(LifecycleManager lifecycleManager,
|
||||
ValidationManager getValidationManager(EventBus eventBus,
|
||||
ValidationManagerImpl validationManager) {
|
||||
lifecycleManager.register(validationManager);
|
||||
eventBus.addListener(validationManager);
|
||||
return validationManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.db.NoSuchMessageException;
|
||||
import org.briarproject.api.db.NoSuchSubscriptionException;
|
||||
import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.EventListener;
|
||||
import org.briarproject.api.event.MessageAddedEvent;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
@@ -38,32 +37,18 @@ class ValidationManagerImpl implements ValidationManager, EventListener {
|
||||
private final DatabaseComponent db;
|
||||
private final Executor dbExecutor;
|
||||
private final Executor cryptoExecutor;
|
||||
private final EventBus eventBus;
|
||||
private final Map<ClientId, MessageValidator> validators;
|
||||
|
||||
@Inject
|
||||
ValidationManagerImpl(DatabaseComponent db,
|
||||
@DatabaseExecutor Executor dbExecutor,
|
||||
@CryptoExecutor Executor cryptoExecutor, EventBus eventBus) {
|
||||
@CryptoExecutor Executor cryptoExecutor) {
|
||||
this.db = db;
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.cryptoExecutor = cryptoExecutor;
|
||||
this.eventBus = eventBus;
|
||||
validators = new ConcurrentHashMap<ClientId, MessageValidator>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
eventBus.addListener(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
eventBus.removeListener(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessageValidator(ClientId c, MessageValidator v) {
|
||||
validators.put(c, v);
|
||||
|
||||
@@ -9,10 +9,10 @@ import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.event.ContactRemovedEvent;
|
||||
import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.EventListener;
|
||||
import org.briarproject.api.event.TransportAddedEvent;
|
||||
import org.briarproject.api.event.TransportRemovedEvent;
|
||||
import org.briarproject.api.lifecycle.Service;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.system.Timer;
|
||||
import org.briarproject.api.transport.KeyManager;
|
||||
@@ -29,7 +29,7 @@ import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
class KeyManagerImpl implements KeyManager, EventListener {
|
||||
class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(KeyManagerImpl.class.getName());
|
||||
@@ -37,26 +37,24 @@ class KeyManagerImpl implements KeyManager, EventListener {
|
||||
private final DatabaseComponent db;
|
||||
private final CryptoComponent crypto;
|
||||
private final ExecutorService dbExecutor;
|
||||
private final EventBus eventBus;
|
||||
private final Timer timer;
|
||||
private final Clock clock;
|
||||
private final ConcurrentHashMap<TransportId, TransportKeyManager> managers;
|
||||
|
||||
@Inject
|
||||
KeyManagerImpl(DatabaseComponent db, CryptoComponent crypto,
|
||||
@DatabaseExecutor ExecutorService dbExecutor, EventBus eventBus,
|
||||
Timer timer, Clock clock) {
|
||||
@DatabaseExecutor ExecutorService dbExecutor, Timer timer,
|
||||
Clock clock) {
|
||||
this.db = db;
|
||||
this.crypto = crypto;
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.eventBus = eventBus;
|
||||
this.timer = timer;
|
||||
this.clock = clock;
|
||||
managers = new ConcurrentHashMap<TransportId, TransportKeyManager>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
eventBus.addListener(this);
|
||||
try {
|
||||
Map<TransportId, Integer> latencies = db.getTransportLatencies();
|
||||
for (Entry<TransportId, Integer> e : latencies.entrySet())
|
||||
@@ -68,8 +66,8 @@ class KeyManagerImpl implements KeyManager, EventListener {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
eventBus.removeListener(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.transport;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.transport.KeyManager;
|
||||
import org.briarproject.api.transport.StreamReaderFactory;
|
||||
@@ -20,8 +21,9 @@ public class TransportModule extends AbstractModule {
|
||||
|
||||
@Provides @Singleton
|
||||
KeyManager getKeyManager(LifecycleManager lifecycleManager,
|
||||
KeyManagerImpl keyManager) {
|
||||
EventBus eventBus, KeyManagerImpl keyManager) {
|
||||
lifecycleManager.register(keyManager);
|
||||
eventBus.addListener(keyManager);
|
||||
return keyManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.briarproject.db;
|
||||
|
||||
import org.briarproject.BriarTestCase;
|
||||
import org.briarproject.TestUtils;
|
||||
import org.briarproject.api.Settings;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
@@ -16,11 +15,8 @@ import org.briarproject.api.db.NoSuchLocalAuthorException;
|
||||
import org.briarproject.api.db.NoSuchMessageException;
|
||||
import org.briarproject.api.db.NoSuchSubscriptionException;
|
||||
import org.briarproject.api.db.NoSuchTransportException;
|
||||
import org.briarproject.api.event.ContactAddedEvent;
|
||||
import org.briarproject.api.event.ContactRemovedEvent;
|
||||
import org.briarproject.api.db.StorageStatus;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.LocalAuthorAddedEvent;
|
||||
import org.briarproject.api.event.LocalAuthorRemovedEvent;
|
||||
import org.briarproject.api.event.LocalSubscriptionsUpdatedEvent;
|
||||
import org.briarproject.api.event.LocalTransportsUpdatedEvent;
|
||||
import org.briarproject.api.event.MessageAddedEvent;
|
||||
@@ -98,11 +94,12 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
||||
authorId = new AuthorId(TestUtils.getRandomId());
|
||||
author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||
localAuthorId = new AuthorId(TestUtils.getRandomId());
|
||||
long timestamp = System.currentTimeMillis();
|
||||
localAuthor = new LocalAuthor(localAuthorId, "Bob",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100], 1234);
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp,
|
||||
StorageStatus.ACTIVE);
|
||||
messageId = new MessageId(TestUtils.getRandomId());
|
||||
messageId1 = new MessageId(TestUtils.getRandomId());
|
||||
long timestamp = System.currentTimeMillis();
|
||||
size = 1234;
|
||||
raw = new byte[size];
|
||||
message = new Message(messageId, groupId, timestamp, raw);
|
||||
@@ -113,7 +110,8 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
||||
"bar", "baz"));
|
||||
maxLatency = Integer.MAX_VALUE;
|
||||
contactId = new ContactId(234);
|
||||
contact = new Contact(contactId, author, localAuthorId);
|
||||
contact = new Contact(contactId, author, localAuthorId,
|
||||
StorageStatus.ACTIVE);
|
||||
}
|
||||
|
||||
private <T> DatabaseComponent createDatabaseComponent(Database<T> database,
|
||||
@@ -142,7 +140,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
||||
oneOf(database).containsLocalAuthor(txn, localAuthorId);
|
||||
will(returnValue(false));
|
||||
oneOf(database).addLocalAuthor(txn, localAuthor);
|
||||
oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class)));
|
||||
// addContact()
|
||||
oneOf(database).containsContact(txn, authorId);
|
||||
will(returnValue(false));
|
||||
@@ -150,7 +147,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
||||
will(returnValue(true));
|
||||
oneOf(database).addContact(txn, author, localAuthorId);
|
||||
will(returnValue(contactId));
|
||||
oneOf(eventBus).broadcast(with(any(ContactAddedEvent.class)));
|
||||
// getContacts()
|
||||
oneOf(database).getContacts(txn);
|
||||
will(returnValue(Collections.singletonList(contact)));
|
||||
@@ -183,14 +179,10 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
||||
oneOf(database).containsContact(txn, contactId);
|
||||
will(returnValue(true));
|
||||
oneOf(database).removeContact(txn, contactId);
|
||||
oneOf(eventBus).broadcast(with(any(ContactRemovedEvent.class)));
|
||||
// removeLocalAuthor()
|
||||
oneOf(database).containsLocalAuthor(txn, localAuthorId);
|
||||
will(returnValue(true));
|
||||
oneOf(database).getContacts(txn, localAuthorId);
|
||||
will(returnValue(Collections.emptyList()));
|
||||
oneOf(database).removeLocalAuthor(txn, localAuthorId);
|
||||
oneOf(eventBus).broadcast(with(any(LocalAuthorRemovedEvent.class)));
|
||||
// close()
|
||||
oneOf(shutdown).removeShutdownHook(shutdownHandle);
|
||||
oneOf(database).close();
|
||||
@@ -660,7 +652,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
||||
will(returnValue(false));
|
||||
oneOf(database).addLocalAuthor(txn, localAuthor);
|
||||
oneOf(database).commitTransaction(txn);
|
||||
oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class)));
|
||||
// addContact()
|
||||
oneOf(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
@@ -671,7 +662,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
|
||||
oneOf(database).addContact(txn, author, localAuthorId);
|
||||
will(returnValue(contactId));
|
||||
oneOf(database).commitTransaction(txn);
|
||||
oneOf(eventBus).broadcast(with(any(ContactAddedEvent.class)));
|
||||
// Check whether the transport is in the DB (which it's not)
|
||||
exactly(6).of(database).startTransaction();
|
||||
will(returnValue(txn));
|
||||
|
||||
@@ -3,12 +3,14 @@ package org.briarproject.db;
|
||||
import org.briarproject.BriarTestCase;
|
||||
import org.briarproject.TestDatabaseConfig;
|
||||
import org.briarproject.TestUtils;
|
||||
import org.briarproject.api.Settings;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.TransportProperties;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.db.StorageStatus;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
@@ -21,7 +23,6 @@ import org.briarproject.api.sync.MessageStatus;
|
||||
import org.briarproject.api.transport.IncomingKeys;
|
||||
import org.briarproject.api.transport.OutgoingKeys;
|
||||
import org.briarproject.api.transport.TransportKeys;
|
||||
import org.briarproject.api.Settings;
|
||||
import org.briarproject.system.SystemClock;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -80,10 +81,11 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
AuthorId authorId = new AuthorId(TestUtils.getRandomId());
|
||||
author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||
localAuthorId = new AuthorId(TestUtils.getRandomId());
|
||||
localAuthor = new LocalAuthor(localAuthorId, "Bob",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100], 1234);
|
||||
messageId = new MessageId(TestUtils.getRandomId());
|
||||
timestamp = System.currentTimeMillis();
|
||||
localAuthor = new LocalAuthor(localAuthorId, "Bob",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp,
|
||||
StorageStatus.ACTIVE);
|
||||
messageId = new MessageId(TestUtils.getRandomId());
|
||||
size = 1234;
|
||||
raw = new byte[size];
|
||||
random.nextBytes(raw);
|
||||
@@ -94,7 +96,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
testDir.mkdirs();
|
||||
assertTrue(testDir.mkdirs());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -35,11 +35,13 @@ import org.briarproject.api.sync.PacketWriterFactory;
|
||||
import org.briarproject.api.sync.Request;
|
||||
import org.briarproject.api.sync.SubscriptionUpdate;
|
||||
import org.briarproject.api.sync.TransportUpdate;
|
||||
import org.briarproject.contact.ContactModule;
|
||||
import org.briarproject.crypto.CryptoModule;
|
||||
import org.briarproject.data.DataModule;
|
||||
import org.briarproject.db.DatabaseModule;
|
||||
import org.briarproject.event.EventModule;
|
||||
import org.briarproject.forum.ForumModule;
|
||||
import org.briarproject.identity.IdentityModule;
|
||||
import org.briarproject.messaging.MessagingModule;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -63,6 +65,8 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ConstantsTest extends BriarTestCase {
|
||||
|
||||
// TODO: Break this up into tests that are relevant for each package
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final GroupFactory groupFactory;
|
||||
private final AuthorFactory authorFactory;
|
||||
@@ -73,9 +77,9 @@ public class ConstantsTest extends BriarTestCase {
|
||||
public ConstantsTest() throws Exception {
|
||||
Injector i = Guice.createInjector(new TestDatabaseModule(),
|
||||
new TestLifecycleModule(), new TestSystemModule(),
|
||||
new CryptoModule(), new DatabaseModule(), new DataModule(),
|
||||
new EventModule(), new ForumModule(), new MessagingModule(),
|
||||
new SyncModule());
|
||||
new ContactModule(), new CryptoModule(), new DatabaseModule(),
|
||||
new DataModule(), new EventModule(), new ForumModule(),
|
||||
new IdentityModule(), new MessagingModule(), new SyncModule());
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
groupFactory = i.getInstance(GroupFactory.class);
|
||||
authorFactory = i.getInstance(AuthorFactory.class);
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.google.inject.Injector;
|
||||
|
||||
import org.briarproject.BriarTestCase;
|
||||
import org.briarproject.TestDatabaseModule;
|
||||
import org.briarproject.TestLifecycleModule;
|
||||
import org.briarproject.TestSystemModule;
|
||||
import org.briarproject.TestUtils;
|
||||
import org.briarproject.api.TransportId;
|
||||
@@ -13,6 +12,7 @@ import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.db.DatabaseComponent;
|
||||
import org.briarproject.api.db.StorageStatus;
|
||||
import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.event.EventListener;
|
||||
@@ -21,6 +21,7 @@ import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.identity.IdentityManager;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.messaging.PrivateMessage;
|
||||
import org.briarproject.api.messaging.PrivateMessageFactory;
|
||||
@@ -40,6 +41,7 @@ import org.briarproject.data.DataModule;
|
||||
import org.briarproject.db.DatabaseModule;
|
||||
import org.briarproject.event.EventModule;
|
||||
import org.briarproject.identity.IdentityModule;
|
||||
import org.briarproject.lifecycle.LifecycleModule;
|
||||
import org.briarproject.messaging.MessagingModule;
|
||||
import org.briarproject.plugins.ImmediateExecutor;
|
||||
import org.briarproject.transport.TransportModule;
|
||||
@@ -78,17 +80,17 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
testDir.mkdirs();
|
||||
assertTrue(testDir.mkdirs());
|
||||
alice = createInjector(aliceDir);
|
||||
bob = createInjector(bobDir);
|
||||
}
|
||||
|
||||
private Injector createInjector(File dir) {
|
||||
return Guice.createInjector(new TestDatabaseModule(dir),
|
||||
new TestLifecycleModule(), new TestSystemModule(),
|
||||
new ContactModule(), new CryptoModule(), new DatabaseModule(),
|
||||
new DataModule(), new EventModule(), new IdentityModule(),
|
||||
new SyncModule(), new MessagingModule(), new TransportModule());
|
||||
new TestSystemModule(), new ContactModule(), new CryptoModule(),
|
||||
new DatabaseModule(), new DataModule(), new EventModule(),
|
||||
new IdentityModule(), new LifecycleModule(),
|
||||
new MessagingModule(), new SyncModule(), new TransportModule());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,35 +99,43 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
||||
}
|
||||
|
||||
private byte[] write() throws Exception {
|
||||
// Open Alice's database
|
||||
// Instantiate Alice's services
|
||||
LifecycleManager lifecycleManager =
|
||||
alice.getInstance(LifecycleManager.class);
|
||||
DatabaseComponent db = alice.getInstance(DatabaseComponent.class);
|
||||
assertFalse(db.open());
|
||||
// Add the transport
|
||||
db.addTransport(transportId, MAX_LATENCY);
|
||||
// Start Alice's key manager
|
||||
KeyManager keyManager = alice.getInstance(KeyManager.class);
|
||||
keyManager.start();
|
||||
// Add an identity for Alice
|
||||
LocalAuthor aliceAuthor = new LocalAuthor(aliceId, "Alice",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100], timestamp);
|
||||
IdentityManager identityManager =
|
||||
alice.getInstance(IdentityManager.class);
|
||||
ContactManager contactManager = alice.getInstance(ContactManager.class);
|
||||
MessagingManager messagingManager =
|
||||
alice.getInstance(MessagingManager.class);
|
||||
KeyManager keyManager = alice.getInstance(KeyManager.class);
|
||||
PrivateMessageFactory privateMessageFactory =
|
||||
alice.getInstance(PrivateMessageFactory.class);
|
||||
PacketWriterFactory packetWriterFactory =
|
||||
alice.getInstance(PacketWriterFactory.class);
|
||||
EventBus eventBus = alice.getInstance(EventBus.class);
|
||||
StreamWriterFactory streamWriterFactory =
|
||||
alice.getInstance(StreamWriterFactory.class);
|
||||
|
||||
// Start the lifecycle manager
|
||||
lifecycleManager.startServices();
|
||||
lifecycleManager.waitForStartup();
|
||||
// Add a transport
|
||||
db.addTransport(transportId, MAX_LATENCY);
|
||||
// Add an identity for Alice
|
||||
LocalAuthor aliceAuthor = new LocalAuthor(aliceId, "Alice",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp,
|
||||
StorageStatus.ADDING);
|
||||
identityManager.addLocalAuthor(aliceAuthor);
|
||||
// Add Bob as a contact
|
||||
Author bobAuthor = new Author(bobId, "Bob",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||
ContactManager contactManager = alice.getInstance(ContactManager.class);
|
||||
ContactId contactId = contactManager.addContact(bobAuthor, aliceId);
|
||||
// Create the private conversation
|
||||
MessagingManager messagingManager =
|
||||
alice.getInstance(MessagingManager.class);
|
||||
messagingManager.addContact(contactId);
|
||||
// Derive and store the transport keys
|
||||
keyManager.addContact(contactId, Collections.singletonList(transportId),
|
||||
master, timestamp, true);
|
||||
|
||||
// Send Bob a message
|
||||
PrivateMessageFactory privateMessageFactory =
|
||||
alice.getInstance(PrivateMessageFactory.class);
|
||||
GroupId groupId = messagingManager.getConversationId(contactId);
|
||||
byte[] body = "Hi Bob!".getBytes("UTF-8");
|
||||
PrivateMessage message = privateMessageFactory.createPrivateMessage(
|
||||
@@ -136,14 +146,9 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
||||
assertNotNull(ctx);
|
||||
// Create a stream writer
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
StreamWriterFactory streamWriterFactory =
|
||||
alice.getInstance(StreamWriterFactory.class);
|
||||
OutputStream streamWriter =
|
||||
streamWriterFactory.createStreamWriter(out, ctx);
|
||||
OutputStream streamWriter = streamWriterFactory.createStreamWriter(
|
||||
out, ctx);
|
||||
// Create an outgoing sync session
|
||||
EventBus eventBus = alice.getInstance(EventBus.class);
|
||||
PacketWriterFactory packetWriterFactory =
|
||||
alice.getInstance(PacketWriterFactory.class);
|
||||
PacketWriter packetWriter = packetWriterFactory.createPacketWriter(
|
||||
streamWriter);
|
||||
SyncSession session = new SimplexOutgoingSession(db,
|
||||
@@ -152,40 +157,50 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
||||
// Write whatever needs to be written
|
||||
session.run();
|
||||
streamWriter.close();
|
||||
|
||||
// Clean up
|
||||
keyManager.stop();
|
||||
db.close();
|
||||
lifecycleManager.stopServices();
|
||||
lifecycleManager.waitForShutdown();
|
||||
|
||||
// Return the contents of the stream
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
private void read(byte[] stream) throws Exception {
|
||||
// Open Bob's database
|
||||
// Instantiate Bob's services
|
||||
LifecycleManager lifecycleManager =
|
||||
bob.getInstance(LifecycleManager.class);
|
||||
DatabaseComponent db = bob.getInstance(DatabaseComponent.class);
|
||||
assertFalse(db.open());
|
||||
// Add the transport
|
||||
db.addTransport(transportId, MAX_LATENCY);
|
||||
// Start Bob's key manager
|
||||
KeyManager keyManager = bob.getInstance(KeyManager.class);
|
||||
keyManager.start();
|
||||
// Add an identity for Bob
|
||||
LocalAuthor bobAuthor = new LocalAuthor(bobId, "Bob",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100], timestamp);
|
||||
IdentityManager identityManager =
|
||||
bob.getInstance(IdentityManager.class);
|
||||
ContactManager contactManager = bob.getInstance(ContactManager.class);
|
||||
KeyManager keyManager = bob.getInstance(KeyManager.class);
|
||||
StreamReaderFactory streamReaderFactory =
|
||||
bob.getInstance(StreamReaderFactory.class);
|
||||
PacketReaderFactory packetReaderFactory =
|
||||
bob.getInstance(PacketReaderFactory.class);
|
||||
EventBus eventBus = bob.getInstance(EventBus.class);
|
||||
// Bob needs a MessagingManager even though we're not using it directly
|
||||
bob.getInstance(MessagingManager.class);
|
||||
|
||||
// Start the lifecyle manager
|
||||
lifecycleManager.startServices();
|
||||
lifecycleManager.waitForStartup();
|
||||
// Add a transport
|
||||
db.addTransport(transportId, MAX_LATENCY);
|
||||
// Add an identity for Bob
|
||||
LocalAuthor bobAuthor = new LocalAuthor(bobId, "Bob",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp,
|
||||
StorageStatus.ADDING);
|
||||
identityManager.addLocalAuthor(bobAuthor);
|
||||
// Add Alice as a contact
|
||||
Author aliceAuthor = new Author(aliceId, "Alice",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||
ContactManager contactManager = bob.getInstance(ContactManager.class);
|
||||
ContactId contactId = contactManager.addContact(aliceAuthor, bobId);
|
||||
// Create the private conversation
|
||||
MessagingManager messagingManager =
|
||||
bob.getInstance(MessagingManager.class);
|
||||
messagingManager.addContact(contactId);
|
||||
// Derive and store the transport keys
|
||||
keyManager.addContact(contactId, Collections.singletonList(transportId),
|
||||
master, timestamp, false);
|
||||
|
||||
// Set up an event listener
|
||||
MessageListener listener = new MessageListener();
|
||||
bob.getInstance(EventBus.class).addListener(listener);
|
||||
@@ -197,19 +212,13 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
||||
StreamContext ctx = keyManager.getStreamContext(transportId, tag);
|
||||
assertNotNull(ctx);
|
||||
// Create a stream reader
|
||||
StreamReaderFactory streamReaderFactory =
|
||||
bob.getInstance(StreamReaderFactory.class);
|
||||
InputStream streamReader =
|
||||
streamReaderFactory.createStreamReader(in, ctx);
|
||||
InputStream streamReader = streamReaderFactory.createStreamReader(
|
||||
in, ctx);
|
||||
// Create an incoming sync session
|
||||
EventBus eventBus = bob.getInstance(EventBus.class);
|
||||
PacketReaderFactory packetReaderFactory =
|
||||
bob.getInstance(PacketReaderFactory.class);
|
||||
PacketReader packetReader = packetReaderFactory.createPacketReader(
|
||||
streamReader);
|
||||
SyncSession session = new IncomingSession(db,
|
||||
new ImmediateExecutor(), eventBus, contactId, transportId,
|
||||
packetReader);
|
||||
SyncSession session = new IncomingSession(db, new ImmediateExecutor(),
|
||||
eventBus, contactId, transportId, packetReader);
|
||||
// No messages should have been added yet
|
||||
assertFalse(listener.messageAdded);
|
||||
// Read whatever needs to be read
|
||||
@@ -217,9 +226,10 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
||||
streamReader.close();
|
||||
// The private message from Alice should have been added
|
||||
assertTrue(listener.messageAdded);
|
||||
|
||||
// Clean up
|
||||
keyManager.stop();
|
||||
db.close();
|
||||
lifecycleManager.stopServices();
|
||||
lifecycleManager.waitForShutdown();
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
Reference in New Issue
Block a user