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