Contact manager hooks. #209

This commit is contained in:
akwizgran
2016-01-19 19:16:35 +00:00
parent 33ef09a6bf
commit 82cf12040f
29 changed files with 333 additions and 195 deletions

View File

@@ -7,38 +7,115 @@ import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.NoSuchContactException;
import org.briarproject.api.event.ContactAddedEvent;
import org.briarproject.api.event.ContactRemovedEvent;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.lifecycle.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Logger;
class ContactManagerImpl implements ContactManager {
import static java.util.logging.Level.WARNING;
import static org.briarproject.api.contact.Contact.Status.ACTIVE;
import static org.briarproject.api.contact.Contact.Status.ADDING;
import static org.briarproject.api.contact.Contact.Status.REMOVING;
class ContactManagerImpl implements ContactManager, Service {
private static final Logger LOG =
Logger.getLogger(ContactManagerImpl.class.getName());
private final DatabaseComponent db;
private final EventBus eventBus;
private final List<ContactAddedHook> addHooks;
private final List<ContactRemovedHook> removeHooks;
@Inject
ContactManagerImpl(DatabaseComponent db) {
ContactManagerImpl(DatabaseComponent db, EventBus eventBus) {
this.db = db;
this.eventBus = eventBus;
addHooks = new CopyOnWriteArrayList<ContactAddedHook>();
removeHooks = new CopyOnWriteArrayList<ContactRemovedHook>();
}
@Override
public boolean start() {
// Finish adding/removing any partly added/removed contacts
try {
for (Contact c : db.getContacts()) {
if (c.getStatus().equals(ADDING)) {
for (ContactAddedHook hook : addHooks)
hook.contactAdded(c.getId());
db.setContactStatus(c.getId(), ACTIVE);
eventBus.broadcast(new ContactAddedEvent(c.getId()));
} else if (c.getStatus().equals(REMOVING)) {
for (ContactRemovedHook hook : removeHooks)
hook.contactRemoved(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 registerContactAddedHook(ContactAddedHook hook) {
addHooks.add(hook);
}
@Override
public void registerContactRemovedHook(ContactRemovedHook hook) {
removeHooks.add(hook);
}
@Override
public ContactId addContact(Author remote, AuthorId local)
throws DbException {
return db.addContact(remote, local);
ContactId c = db.addContact(remote, local);
for (ContactAddedHook hook : addHooks) hook.contactAdded(c);
db.setContactStatus(c, ACTIVE);
eventBus.broadcast(new ContactAddedEvent(c));
return c;
}
@Override
public Contact getContact(ContactId c) throws DbException {
return db.getContact(c);
Contact contact = db.getContact(c);
if (contact.getStatus().equals(ACTIVE)) return contact;
throw new NoSuchContactException();
}
@Override
public Collection<Contact> getContacts() throws DbException {
return db.getContacts();
Collection<Contact> contacts = db.getContacts();
// Filter out any contacts that are being added or removed
List<Contact> active = new ArrayList<Contact>(contacts.size());
for (Contact c : contacts)
if (c.getStatus().equals(ACTIVE)) active.add(c);
return Collections.unmodifiableList(active);
}
@Override
public void removeContact(ContactId c) throws DbException {
db.setContactStatus(c, REMOVING);
for (ContactRemovedHook hook : removeHooks) hook.contactRemoved(c);
db.removeContact(c);
eventBus.broadcast(new ContactRemovedEvent(c));
}
}

View File

@@ -1,13 +1,22 @@
package org.briarproject.contact;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.lifecycle.LifecycleManager;
import javax.inject.Singleton;
public class ContactModule extends AbstractModule {
@Override
protected void configure() {
bind(ContactManager.class).to(ContactManagerImpl.class);
protected void configure() {}
@Provides @Singleton
ContactManager getContactManager(LifecycleManager lifecycleManager,
ContactManagerImpl contactManager) {
lifecycleManager.register(contactManager);
return contactManager;
}
}

View File

@@ -631,7 +631,19 @@ interface Database<T> {
*/
void resetExpiryTime(T txn, ContactId c, MessageId m) throws DbException;
/** Marks the given message as valid or invalid. */
/**
* Sets the status of the given contact.
* <p>
* Locking: write.
*/
void setContactStatus(T txn, ContactId c, Contact.Status s)
throws DbException;
/**
* Marks the given message as valid or invalid.
* <p>
* Locking: write.
*/
void setMessageValidity(T txn, MessageId m, boolean valid)
throws DbException;

View File

@@ -16,7 +16,6 @@ import org.briarproject.api.db.NoSuchLocalAuthorException;
import org.briarproject.api.db.NoSuchMessageException;
import org.briarproject.api.db.NoSuchSubscriptionException;
import org.briarproject.api.db.NoSuchTransportException;
import org.briarproject.api.event.ContactAddedEvent;
import org.briarproject.api.event.ContactRemovedEvent;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.LocalAuthorAddedEvent;
@@ -147,7 +146,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
public ContactId addContact(Author remote, AuthorId local)
throws DbException {
ContactId c;
lock.writeLock().lock();
try {
T txn = db.startTransaction();
@@ -156,8 +154,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
throw new ContactExistsException();
if (!db.containsLocalAuthor(txn, local))
throw new NoSuchLocalAuthorException();
c = db.addContact(txn, remote, local);
ContactId c = db.addContact(txn, remote, local);
db.commitTransaction(txn);
return c;
} catch (DbException e) {
db.abortTransaction(txn);
throw e;
@@ -165,8 +164,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} finally {
lock.writeLock().unlock();
}
eventBus.broadcast(new ContactAddedEvent(c));
return c;
}
public void addContactGroup(ContactId c, Group g) throws DbException {
@@ -1219,7 +1216,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} finally {
lock.writeLock().unlock();
}
eventBus.broadcast(new ContactRemovedEvent(c));
}
public void removeGroup(Group g) throws DbException {
@@ -1287,6 +1283,25 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
eventBus.broadcast(new TransportRemovedEvent(t));
}
public void setContactStatus(ContactId c, Contact.Status 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 setMessageValidity(Message m, ClientId c, boolean valid)
throws DbException {
lock.writeLock().lock();

View File

@@ -50,8 +50,12 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static org.briarproject.api.contact.Contact.Status.ADDING;
import static org.briarproject.api.db.Metadata.REMOVE;
import static org.briarproject.api.sync.SyncConstants.MAX_SUBSCRIPTIONS;
import static org.briarproject.api.sync.ValidationManager.Status.INVALID;
import static org.briarproject.api.sync.ValidationManager.Status.UNKNOWN;
import static org.briarproject.api.sync.ValidationManager.Status.VALID;
import static org.briarproject.db.ExponentialBackoff.calculateExpiry;
/**
@@ -60,12 +64,8 @@ import static org.briarproject.db.ExponentialBackoff.calculateExpiry;
*/
abstract class JdbcDatabase implements Database<Connection> {
private static final int SCHEMA_VERSION = 14;
private static final int MIN_SCHEMA_VERSION = 14;
private static final int VALIDATION_UNKNOWN = 0;
private static final int VALIDATION_INVALID = 1;
private static final int VALIDATION_VALID = 2;
private static final int SCHEMA_VERSION = 15;
private static final int MIN_SCHEMA_VERSION = 15;
private static final String CREATE_SETTINGS =
"CREATE TABLE settings"
@@ -90,6 +90,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " name VARCHAR NOT NULL,"
+ " publicKey BINARY NOT NULL,"
+ " localAuthorId HASH NOT NULL,"
+ " status INT NOT NULL,"
+ " PRIMARY KEY (contactId),"
+ " UNIQUE (authorId),"
+ " FOREIGN KEY (localAuthorId)"
@@ -533,13 +534,14 @@ abstract class JdbcDatabase implements Database<Connection> {
try {
// Create a contact row
String sql = "INSERT INTO contacts"
+ " (authorId, name, publicKey, localAuthorId)"
+ " VALUES (?, ?, ?, ?)";
+ " (authorId, name, publicKey, localAuthorId, status)"
+ " VALUES (?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql);
ps.setBytes(1, remote.getId().getBytes());
ps.setString(2, remote.getName());
ps.setBytes(3, remote.getPublicKey());
ps.setBytes(4, local.getBytes());
ps.setInt(5, ADDING.getValue());
int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException();
ps.close();
@@ -747,7 +749,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setBytes(2, m.getGroupId().getBytes());
ps.setLong(3, m.getTimestamp());
ps.setBoolean(4, local);
ps.setInt(5, local ? VALIDATION_VALID : VALIDATION_UNKNOWN);
ps.setInt(5, local ? VALID.getValue() : UNKNOWN.getValue());
byte[] raw = m.getRaw();
ps.setInt(6, raw.length);
ps.setBytes(7, raw);
@@ -1192,7 +1194,8 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT authorId, name, publicKey, localAuthorId"
String sql = "SELECT authorId, name, publicKey, localAuthorId,"
+ " status"
+ " FROM contacts"
+ " WHERE contactId = ?";
ps = txn.prepareStatement(sql);
@@ -1203,10 +1206,11 @@ abstract class JdbcDatabase implements Database<Connection> {
String name = rs.getString(2);
byte[] publicKey = rs.getBytes(3);
AuthorId localAuthorId = new AuthorId(rs.getBytes(4));
Contact.Status status = Contact.Status.fromValue(rs.getInt(5));
rs.close();
ps.close();
Author author = new Author(authorId, name, publicKey);
return new Contact(c, author, localAuthorId);
return new Contact(c, author, localAuthorId, status);
} catch (SQLException e) {
tryToClose(rs);
tryToClose(ps);
@@ -1240,7 +1244,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ResultSet rs = null;
try {
String sql = "SELECT contactId, authorId, name, publicKey,"
+ " localAuthorId"
+ " localAuthorId, status"
+ " FROM contacts";
ps = txn.prepareStatement(sql);
rs = ps.executeQuery();
@@ -1252,7 +1256,9 @@ abstract class JdbcDatabase implements Database<Connection> {
byte[] publicKey = rs.getBytes(4);
Author author = new Author(authorId, name, publicKey);
AuthorId localAuthorId = new AuthorId(rs.getBytes(5));
contacts.add(new Contact(contactId, author, localAuthorId));
Contact.Status status = Contact.Status.fromValue(rs.getInt(6));
contacts.add(new Contact(contactId, author, localAuthorId,
status));
}
rs.close();
ps.close();
@@ -1612,7 +1618,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " ORDER BY timestamp DESC LIMIT ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setInt(2, VALIDATION_VALID);
ps.setInt(2, VALID.getValue());
ps.setLong(3, now);
ps.setInt(4, maxMessages);
rs = ps.executeQuery();
@@ -1674,7 +1680,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " ORDER BY timestamp DESC";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setInt(2, VALIDATION_VALID);
ps.setInt(2, VALID.getValue());
ps.setLong(3, now);
rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>();
@@ -1704,7 +1710,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " JOIN groups AS g ON m.groupId = g.groupId"
+ " WHERE valid = ? AND clientId = ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, VALIDATION_UNKNOWN);
ps.setInt(1, UNKNOWN.getValue());
ps.setBytes(2, c.getBytes());
rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>();
@@ -1799,7 +1805,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " ORDER BY timestamp DESC";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setInt(2, VALIDATION_VALID);
ps.setInt(2, VALID.getValue());
ps.setLong(3, now);
rs = ps.executeQuery();
List<MessageId> ids = new ArrayList<MessageId>();
@@ -1846,7 +1852,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ResultSet rs = null;
try {
String sql = "SELECT c.contactId, authorId, c.name, publicKey,"
+ " localAuthorId"
+ " localAuthorId, status"
+ " FROM contacts AS c"
+ " JOIN contactGroups AS cg"
+ " ON c.contactId = cg.contactId"
@@ -1862,7 +1868,9 @@ abstract class JdbcDatabase implements Database<Connection> {
byte[] publicKey = rs.getBytes(4);
Author author = new Author(authorId, name, publicKey);
AuthorId localAuthorId = new AuthorId(rs.getBytes(5));
contacts.add(new Contact(contactId, author, localAuthorId));
Contact.Status status = Contact.Status.fromValue(rs.getInt(6));
contacts.add(new Contact(contactId, author, localAuthorId,
status));
}
rs.close();
ps.close();
@@ -2687,13 +2695,30 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public void setContactStatus(Connection txn, ContactId c, Contact.Status 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 setMessageValidity(Connection txn, MessageId m, boolean valid)
throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE messages SET valid = ? WHERE messageId = ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, valid ? VALIDATION_VALID : VALIDATION_INVALID);
ps.setInt(1, valid ? VALID.getValue() : INVALID.getValue());
ps.setBytes(2, m.getBytes());
int affected = ps.executeUpdate();
if (affected < 0) throw new DbStateException();

View File

@@ -11,7 +11,6 @@ import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumPostFactory;
import org.briarproject.api.identity.Author;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.sync.ValidationManager;
import org.briarproject.api.system.Clock;
@@ -26,16 +25,17 @@ public class ForumModule extends AbstractModule {
}
@Provides @Singleton
ForumPostValidator getValidator(LifecycleManager lifecycleManager,
CryptoComponent crypto, ValidationManager validationManager,
ForumPostValidator getValidator(ValidationManager validationManager,
ForumManager forumManager, CryptoComponent crypto,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory,
ObjectReader<Author> authorReader, MetadataEncoder metadataEncoder,
Clock clock) {
ForumPostValidator validator = new ForumPostValidator(crypto,
validationManager, bdfReaderFactory, bdfWriterFactory,
authorReader, metadataEncoder, clock);
lifecycleManager.register(validator);
bdfReaderFactory, bdfWriterFactory, authorReader,
metadataEncoder, clock);
validationManager.setMessageValidator(forumManager.getClientId(),
validator);
return validator;
}
}

View File

@@ -15,11 +15,9 @@ import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.db.Metadata;
import org.briarproject.api.identity.Author;
import org.briarproject.api.lifecycle.Service;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.MessageValidator;
import org.briarproject.api.sync.ValidationManager;
import org.briarproject.api.system.Clock;
import java.io.ByteArrayInputStream;
@@ -35,15 +33,13 @@ import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENG
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
import static org.briarproject.forum.ForumManagerImpl.CLIENT_ID;
class ForumPostValidator implements MessageValidator, Service {
class ForumPostValidator implements MessageValidator {
private static final Logger LOG =
Logger.getLogger(ForumPostValidator.class.getName());
private final CryptoComponent crypto;
private final ValidationManager validationManager;
private final BdfReaderFactory bdfReaderFactory;
private final BdfWriterFactory bdfWriterFactory;
private final ObjectReader<Author> authorReader;
@@ -53,13 +49,11 @@ class ForumPostValidator implements MessageValidator, Service {
@Inject
ForumPostValidator(CryptoComponent crypto,
ValidationManager validationManager,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory,
ObjectReader<Author> authorReader,
MetadataEncoder metadataEncoder, Clock clock) {
this.crypto = crypto;
this.validationManager = validationManager;
this.bdfReaderFactory = bdfReaderFactory;
this.bdfWriterFactory = bdfWriterFactory;
this.authorReader = authorReader;
@@ -68,17 +62,6 @@ class ForumPostValidator implements MessageValidator, Service {
keyParser = crypto.getSignatureKeyParser();
}
@Override
public boolean start() {
validationManager.setMessageValidator(CLIENT_ID, this);
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public Metadata validateMessage(Message m) {
// Reject the message if it's too far in the future

View File

@@ -14,7 +14,6 @@ import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.plugins.ConnectionManager;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
@@ -48,7 +47,7 @@ class AliceConnector extends Connector {
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory,
KeyManager keyManager, ConnectionManager connectionManager,
ContactManager contactManager, MessagingManager messagingManager,
ContactManager contactManager,
TransportPropertyManager transportPropertyManager, Clock clock,
boolean reuseConnection, ConnectorGroup group, DuplexPlugin plugin,
LocalAuthor localAuthor,
@@ -57,9 +56,8 @@ class AliceConnector extends Connector {
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
streamWriterFactory, authorFactory, groupFactory,
keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock,
reuseConnection, group, plugin, localAuthor, localProps,
random);
transportPropertyManager, clock, reuseConnection, group,
plugin, localAuthor, localProps, random);
}
@Override

View File

@@ -14,7 +14,6 @@ import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.plugins.ConnectionManager;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
@@ -48,7 +47,7 @@ class BobConnector extends Connector {
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory,
KeyManager keyManager, ConnectionManager connectionManager,
ContactManager contactManager, MessagingManager messagingManager,
ContactManager contactManager,
TransportPropertyManager transportPropertyManager, Clock clock,
boolean reuseConnection, ConnectorGroup group, DuplexPlugin plugin,
LocalAuthor localAuthor,
@@ -57,9 +56,8 @@ class BobConnector extends Connector {
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
streamWriterFactory, authorFactory, groupFactory,
keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock,
reuseConnection, group, plugin, localAuthor, localProps,
random);
transportPropertyManager, clock, reuseConnection, group,
plugin, localAuthor, localProps, random);
}
@Override

View File

@@ -20,7 +20,6 @@ import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.plugins.ConnectionManager;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
@@ -65,7 +64,6 @@ abstract class Connector extends Thread {
protected final KeyManager keyManager;
protected final ConnectionManager connectionManager;
protected final ContactManager contactManager;
protected final MessagingManager messagingManager;
protected final TransportPropertyManager transportPropertyManager;
protected final Clock clock;
protected final boolean reuseConnection;
@@ -89,7 +87,7 @@ abstract class Connector extends Thread {
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory,
KeyManager keyManager, ConnectionManager connectionManager,
ContactManager contactManager, MessagingManager messagingManager,
ContactManager contactManager,
TransportPropertyManager transportPropertyManager, Clock clock,
boolean reuseConnection, ConnectorGroup group, DuplexPlugin plugin,
LocalAuthor localAuthor,
@@ -106,7 +104,6 @@ abstract class Connector extends Thread {
this.keyManager = keyManager;
this.connectionManager = connectionManager;
this.contactManager = contactManager;
this.messagingManager = messagingManager;
this.transportPropertyManager = transportPropertyManager;
this.clock = clock;
this.reuseConnection = reuseConnection;
@@ -287,8 +284,6 @@ abstract class Connector extends Thread {
// Derive transport keys for each transport shared with the contact
keyManager.addContact(contactId, remoteProps.keySet(), master,
timestamp, alice);
// Create a private messaging conversation
messagingManager.addContact(contactId);
}
protected void tryToClose(DuplexTransportConnection conn,

View File

@@ -16,7 +16,6 @@ import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.invitation.InvitationListener;
import org.briarproject.api.invitation.InvitationState;
import org.briarproject.api.invitation.InvitationTask;
import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.plugins.ConnectionManager;
import org.briarproject.api.plugins.PluginManager;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
@@ -58,7 +57,6 @@ class ConnectorGroup extends Thread implements InvitationTask {
private final ConnectionManager connectionManager;
private final IdentityManager identityManager;
private final ContactManager contactManager;
private final MessagingManager messagingManager;
private final TransportPropertyManager transportPropertyManager;
private final Clock clock;
private final PluginManager pluginManager;
@@ -85,7 +83,6 @@ class ConnectorGroup extends Thread implements InvitationTask {
AuthorFactory authorFactory, GroupFactory groupFactory,
KeyManager keyManager, ConnectionManager connectionManager,
IdentityManager identityManager, ContactManager contactManager,
MessagingManager messagingManager,
TransportPropertyManager transportPropertyManager, Clock clock,
PluginManager pluginManager, AuthorId localAuthorId,
int localInvitationCode, int remoteInvitationCode,
@@ -102,7 +99,6 @@ class ConnectorGroup extends Thread implements InvitationTask {
this.connectionManager = connectionManager;
this.identityManager = identityManager;
this.contactManager = contactManager;
this.messagingManager = messagingManager;
this.transportPropertyManager = transportPropertyManager;
this.clock = clock;
this.pluginManager = pluginManager;
@@ -201,8 +197,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
return new AliceConnector(crypto, bdfReaderFactory, bdfWriterFactory,
streamReaderFactory, streamWriterFactory, authorFactory,
groupFactory, keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock,
reuseConnection, this, plugin, localAuthor, localProps, random);
transportPropertyManager, clock, reuseConnection, this, plugin,
localAuthor, localProps, random);
}
private Connector createBobConnector(DuplexPlugin plugin,
@@ -213,8 +209,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
return new BobConnector(crypto, bdfReaderFactory, bdfWriterFactory,
streamReaderFactory, streamWriterFactory, authorFactory,
groupFactory, keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock,
reuseConnection, this, plugin, localAuthor, localProps, random);
transportPropertyManager, clock, reuseConnection, this, plugin,
localAuthor, localProps, random);
}
public void localConfirmationSucceeded() {

View File

@@ -9,7 +9,6 @@ import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.invitation.InvitationTask;
import org.briarproject.api.invitation.InvitationTaskFactory;
import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.plugins.ConnectionManager;
import org.briarproject.api.plugins.PluginManager;
import org.briarproject.api.property.TransportPropertyManager;
@@ -34,7 +33,6 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
private final ConnectionManager connectionManager;
private final IdentityManager identityManager;
private final ContactManager contactManager;
private final MessagingManager messagingManager;
private final TransportPropertyManager transportPropertyManager;
private final Clock clock;
private final PluginManager pluginManager;
@@ -47,7 +45,6 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
AuthorFactory authorFactory, GroupFactory groupFactory,
KeyManager keyManager, ConnectionManager connectionManager,
IdentityManager identityManager, ContactManager contactManager,
MessagingManager messagingManager,
TransportPropertyManager transportPropertyManager,
Clock clock, PluginManager pluginManager) {
this.crypto = crypto;
@@ -61,7 +58,6 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
this.connectionManager = connectionManager;
this.identityManager = identityManager;
this.contactManager = contactManager;
this.messagingManager = messagingManager;
this.transportPropertyManager = transportPropertyManager;
this.clock = clock;
this.pluginManager = pluginManager;
@@ -72,8 +68,7 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
return new ConnectorGroup(crypto, bdfReaderFactory, bdfWriterFactory,
streamReaderFactory, streamWriterFactory, authorFactory,
groupFactory, keyManager, connectionManager, identityManager,
contactManager, messagingManager, transportPropertyManager,
clock, pluginManager, localAuthorId, localCode, remoteCode,
reuseConnection);
contactManager, transportPropertyManager, clock, pluginManager,
localAuthorId, localCode, remoteCode, reuseConnection);
}
}

View File

@@ -6,6 +6,8 @@ import org.briarproject.api.FormatException;
import org.briarproject.api.UniqueId;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager.ContactAddedHook;
import org.briarproject.api.contact.ContactManager.ContactRemovedHook;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.BdfReaderFactory;
@@ -42,7 +44,8 @@ import static java.util.logging.Level.WARNING;
import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
class MessagingManagerImpl implements MessagingManager {
class MessagingManagerImpl implements MessagingManager, ContactAddedHook,
ContactRemovedHook {
static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
"6bcdc006c0910b0f44e40644c3b31f1a"
@@ -72,18 +75,17 @@ class MessagingManagerImpl implements MessagingManager {
}
@Override
public ClientId getClientId() {
return CLIENT_ID;
}
@Override
public void addContact(ContactId c) throws DbException {
// Create the conversation group
Group conversation = createConversationGroup(db.getContact(c));
// Subscribe to the group and share it with the contact
db.addGroup(conversation);
db.addContactGroup(c, conversation);
db.setVisibility(conversation.getId(), Collections.singletonList(c));
public void contactAdded(ContactId c) {
try {
// Create the conversation group
Group g = createConversationGroup(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);
}
}
private Group createConversationGroup(Contact c) {
@@ -113,6 +115,20 @@ class MessagingManagerImpl implements MessagingManager {
return out.toByteArray();
}
@Override
public void contactRemoved(ContactId c) {
try {
db.removeGroup(createConversationGroup(db.getContact(c)));
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
}
@Override
public ClientId getClientId() {
return CLIENT_ID;
}
@Override
public void addLocalMessage(PrivateMessage m) throws DbException {
BdfDictionary d = new BdfDictionary();
@@ -131,7 +147,7 @@ class MessagingManagerImpl implements MessagingManager {
@Override
public ContactId getContactId(GroupId g) throws DbException {
// TODO: Make this more efficient
// TODO: Use metadata to attach the contact ID to the group
for (Contact c : db.getContacts()) {
Group conversation = createConversationGroup(c);
if (conversation.getId().equals(g)) return c.getId();

View File

@@ -3,9 +3,9 @@ package org.briarproject.messaging;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.messaging.PrivateMessageFactory;
import org.briarproject.api.sync.ValidationManager;
@@ -17,18 +17,26 @@ public class MessagingModule extends AbstractModule {
@Override
protected void configure() {
bind(MessagingManager.class).to(MessagingManagerImpl.class);
bind(PrivateMessageFactory.class).to(PrivateMessageFactoryImpl.class);
}
@Provides @Singleton
PrivateMessageValidator getValidator(LifecycleManager lifecycleManager,
ValidationManager validationManager,
PrivateMessageValidator getValidator(ValidationManager validationManager,
MessagingManager messagingManager,
BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
Clock clock) {
PrivateMessageValidator validator = new PrivateMessageValidator(
validationManager, bdfReaderFactory, metadataEncoder, clock);
lifecycleManager.register(validator);
bdfReaderFactory, metadataEncoder, clock);
validationManager.setMessageValidator(messagingManager.getClientId(),
validator);
return validator;
}
@Provides @Singleton
MessagingManager getMessagingManager(ContactManager contactManager,
MessagingManagerImpl messagingManager) {
contactManager.registerContactAddedHook(messagingManager);
contactManager.registerContactRemovedHook(messagingManager);
return messagingManager;
}
}

View File

@@ -7,11 +7,9 @@ import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.db.Metadata;
import org.briarproject.api.lifecycle.Service;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.MessageValidator;
import org.briarproject.api.sync.ValidationManager;
import org.briarproject.api.system.Clock;
import java.io.ByteArrayInputStream;
@@ -24,39 +22,24 @@ import static org.briarproject.api.messaging.MessagingConstants.MAX_CONTENT_TYPE
import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
import static org.briarproject.messaging.MessagingManagerImpl.CLIENT_ID;
class PrivateMessageValidator implements MessageValidator, Service {
class PrivateMessageValidator implements MessageValidator {
private static final Logger LOG =
Logger.getLogger(PrivateMessageValidator.class.getName());
private final ValidationManager validationManager;
private final BdfReaderFactory bdfReaderFactory;
private final MetadataEncoder metadataEncoder;
private final Clock clock;
@Inject
PrivateMessageValidator(ValidationManager validationManager,
BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
Clock clock) {
this.validationManager = validationManager;
PrivateMessageValidator(BdfReaderFactory bdfReaderFactory,
MetadataEncoder metadataEncoder, Clock clock) {
this.bdfReaderFactory = bdfReaderFactory;
this.metadataEncoder = metadataEncoder;
this.clock = clock;
}
@Override
public boolean start() {
validationManager.setMessageValidator(CLIENT_ID, this);
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public Metadata validateMessage(Message m) {
// Reject the message if it's too far in the future

View File

@@ -4,9 +4,9 @@ import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupFactory;
import org.briarproject.api.sync.MessageFactory;
@@ -48,9 +48,9 @@ public class SyncModule extends AbstractModule {
}
@Provides @Singleton
ValidationManager getValidationManager(LifecycleManager lifecycleManager,
ValidationManager getValidationManager(EventBus eventBus,
ValidationManagerImpl validationManager) {
lifecycleManager.register(validationManager);
eventBus.addListener(validationManager);
return validationManager;
}
}

View File

@@ -11,10 +11,8 @@ import org.briarproject.api.db.Metadata;
import org.briarproject.api.db.NoSuchMessageException;
import org.briarproject.api.db.NoSuchSubscriptionException;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.MessageAddedEvent;
import org.briarproject.api.lifecycle.Service;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
@@ -31,8 +29,7 @@ import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
class ValidationManagerImpl implements ValidationManager, Service,
EventListener {
class ValidationManagerImpl implements ValidationManager, EventListener {
private static final Logger LOG =
Logger.getLogger(ValidationManagerImpl.class.getName());
@@ -40,32 +37,18 @@ class ValidationManagerImpl implements ValidationManager, Service,
private final DatabaseComponent db;
private final Executor dbExecutor;
private final Executor cryptoExecutor;
private final EventBus eventBus;
private final Map<ClientId, MessageValidator> validators;
@Inject
ValidationManagerImpl(DatabaseComponent db,
@DatabaseExecutor Executor dbExecutor,
@CryptoExecutor Executor cryptoExecutor, EventBus eventBus) {
@CryptoExecutor Executor cryptoExecutor) {
this.db = db;
this.dbExecutor = dbExecutor;
this.cryptoExecutor = cryptoExecutor;
this.eventBus = eventBus;
validators = new ConcurrentHashMap<ClientId, MessageValidator>();
}
@Override
public boolean start() {
eventBus.addListener(this);
return true;
}
@Override
public boolean stop() {
eventBus.removeListener(this);
return true;
}
@Override
public void setMessageValidator(ClientId c, MessageValidator v) {
validators.put(c, v);

View File

@@ -9,7 +9,6 @@ import org.briarproject.api.db.DatabaseExecutor;
import org.briarproject.api.db.DbException;
import org.briarproject.api.event.ContactRemovedEvent;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.TransportAddedEvent;
import org.briarproject.api.event.TransportRemovedEvent;
@@ -38,19 +37,17 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
private final DatabaseComponent db;
private final CryptoComponent crypto;
private final ExecutorService dbExecutor;
private final EventBus eventBus;
private final Timer timer;
private final Clock clock;
private final ConcurrentHashMap<TransportId, TransportKeyManager> managers;
@Inject
KeyManagerImpl(DatabaseComponent db, CryptoComponent crypto,
@DatabaseExecutor ExecutorService dbExecutor, EventBus eventBus,
Timer timer, Clock clock) {
@DatabaseExecutor ExecutorService dbExecutor, Timer timer,
Clock clock) {
this.db = db;
this.crypto = crypto;
this.dbExecutor = dbExecutor;
this.eventBus = eventBus;
this.timer = timer;
this.clock = clock;
managers = new ConcurrentHashMap<TransportId, TransportKeyManager>();
@@ -58,7 +55,6 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
@Override
public boolean start() {
eventBus.addListener(this);
try {
Map<TransportId, Integer> latencies = db.getTransportLatencies();
for (Entry<TransportId, Integer> e : latencies.entrySet())
@@ -72,7 +68,6 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
@Override
public boolean stop() {
eventBus.removeListener(this);
return true;
}

View File

@@ -3,6 +3,7 @@ package org.briarproject.transport;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.transport.KeyManager;
import org.briarproject.api.transport.StreamReaderFactory;
@@ -20,8 +21,9 @@ public class TransportModule extends AbstractModule {
@Provides @Singleton
KeyManager getKeyManager(LifecycleManager lifecycleManager,
KeyManagerImpl keyManager) {
EventBus eventBus, KeyManagerImpl keyManager) {
lifecycleManager.register(keyManager);
eventBus.addListener(keyManager);
return keyManager;
}
}