Refactor ContactExchangeTask into reusable manager.

This commit is contained in:
akwizgran
2019-05-09 17:03:50 +01:00
parent f459115b19
commit da54712ae1
6 changed files with 72 additions and 88 deletions

View File

@@ -0,0 +1,16 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
@NotNullByDefault
public interface ContactExchangeManager {
/**
* Exchanges contact information with a remote peer.
*/
void exchangeContacts(TransportId t, DuplexTransportConnection conn,
SecretKey masterKey, boolean alice);
}

View File

@@ -1,16 +1,6 @@
package org.briarproject.bramble.api.contact; package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.crypto.SecretKey; interface ContactExchangeConstants {
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
/**
* A task for conducting a contact information exchange with a remote peer.
*/
@NotNullByDefault
public interface ContactExchangeTask {
/** /**
* The current version of the contact exchange protocol. * The current version of the contact exchange protocol.
@@ -42,11 +32,4 @@ public interface ContactExchangeTask {
* Label for signing key binding nonces. * Label for signing key binding nonces.
*/ */
String SIGNING_LABEL = "org.briarproject.briar.contact/EXCHANGE"; String SIGNING_LABEL = "org.briarproject.briar.contact/EXCHANGE";
/**
* Exchanges contact information with a remote peer.
*/
void exchangeContacts(LocalAuthor localAuthor, SecretKey masterKey,
DuplexTransportConnection conn, TransportId transportId,
boolean alice);
} }

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Predicate; import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactExchangeTask; import org.briarproject.bramble.api.contact.ContactExchangeManager;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent; import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
@@ -17,6 +17,7 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
@@ -49,16 +50,22 @@ import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO; import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.contact.ContactExchangeConstants.ALICE_KEY_LABEL;
import static org.briarproject.bramble.contact.ContactExchangeConstants.ALICE_NONCE_LABEL;
import static org.briarproject.bramble.contact.ContactExchangeConstants.BOB_KEY_LABEL;
import static org.briarproject.bramble.contact.ContactExchangeConstants.BOB_NONCE_LABEL;
import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.contact.ContactExchangeConstants.SIGNING_LABEL;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
class ContactExchangeTaskImpl implements ContactExchangeTask { class ContactExchangeManagerImpl implements ContactExchangeManager {
private static final Logger LOG = private static final Logger LOG =
getLogger(ContactExchangeTaskImpl.class.getName()); getLogger(ContactExchangeManagerImpl.class.getName());
// Accept records with current protocol version, known record type // Accept records with current protocol version, known record type
private static final Predicate<Record> ACCEPT = r -> private static final Predicate<Record> ACCEPT = r ->
@@ -82,17 +89,18 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
private final Clock clock; private final Clock clock;
private final ConnectionManager connectionManager; private final ConnectionManager connectionManager;
private final ContactManager contactManager; private final ContactManager contactManager;
private final IdentityManager identityManager;
private final TransportPropertyManager transportPropertyManager; private final TransportPropertyManager transportPropertyManager;
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final StreamReaderFactory streamReaderFactory; private final StreamReaderFactory streamReaderFactory;
private final StreamWriterFactory streamWriterFactory; private final StreamWriterFactory streamWriterFactory;
@Inject @Inject
ContactExchangeTaskImpl(DatabaseComponent db, ClientHelper clientHelper, ContactExchangeManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
RecordReaderFactory recordReaderFactory, RecordReaderFactory recordReaderFactory,
RecordWriterFactory recordWriterFactory, EventBus eventBus, RecordWriterFactory recordWriterFactory, EventBus eventBus,
Clock clock, ConnectionManager connectionManager, Clock clock, ConnectionManager connectionManager,
ContactManager contactManager, ContactManager contactManager, IdentityManager identityManager,
TransportPropertyManager transportPropertyManager, TransportPropertyManager transportPropertyManager,
CryptoComponent crypto, StreamReaderFactory streamReaderFactory, CryptoComponent crypto, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory) { StreamWriterFactory streamWriterFactory) {
@@ -104,6 +112,7 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
this.clock = clock; this.clock = clock;
this.connectionManager = connectionManager; this.connectionManager = connectionManager;
this.contactManager = contactManager; this.contactManager = contactManager;
this.identityManager = identityManager;
this.transportPropertyManager = transportPropertyManager; this.transportPropertyManager = transportPropertyManager;
this.crypto = crypto; this.crypto = crypto;
this.streamReaderFactory = streamReaderFactory; this.streamReaderFactory = streamReaderFactory;
@@ -111,9 +120,8 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
} }
@Override @Override
public void exchangeContacts(LocalAuthor localAuthor, public void exchangeContacts(TransportId t, DuplexTransportConnection conn,
SecretKey masterKey, DuplexTransportConnection conn, SecretKey masterKey, boolean alice) {
TransportId transportId, boolean alice) {
// Get the transport connection's input and output streams // Get the transport connection's input and output streams
InputStream in; InputStream in;
OutputStream out; OutputStream out;
@@ -127,9 +135,11 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
return; return;
} }
// Get the local transport properties // Get the local author and transport properties
LocalAuthor localAuthor;
Map<TransportId, TransportProperties> localProperties; Map<TransportId, TransportProperties> localProperties;
try { try {
localAuthor = identityManager.getLocalAuthor();
localProperties = transportPropertyManager.getLocalProperties(); localProperties = transportPropertyManager.getLocalProperties();
} catch (DbException e) { } catch (DbException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
@@ -210,8 +220,7 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
ContactId contactId = addContact(remoteInfo.author, localAuthor, ContactId contactId = addContact(remoteInfo.author, localAuthor,
masterKey, timestamp, alice, remoteInfo.properties); masterKey, timestamp, alice, remoteInfo.properties);
// Reuse the connection as a transport connection // Reuse the connection as a transport connection
connectionManager.manageOutgoingConnection(contactId, transportId, connectionManager.manageOutgoingConnection(contactId, t, conn);
conn);
// Pseudonym exchange succeeded // Pseudonym exchange succeeded
LOG.info("Pseudonym exchange succeeded"); LOG.info("Pseudonym exchange succeeded");
eventBus.broadcast( eventBus.broadcast(

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.contact; package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.contact.ContactExchangeTask; import org.briarproject.bramble.api.contact.ContactExchangeManager;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import javax.inject.Inject; import javax.inject.Inject;
@@ -19,14 +19,14 @@ public class ContactModule {
@Provides @Provides
@Singleton @Singleton
ContactManager getContactManager(ContactManagerImpl contactManager) { ContactManager provideContactManager(ContactManagerImpl contactManager) {
return contactManager; return contactManager;
} }
@Provides @Provides
ContactExchangeTask provideContactExchangeTask( ContactExchangeManager provideContactExchangeManager(
ContactExchangeTaskImpl contactExchangeTask) { ContactExchangeManagerImpl contactExchangeManager) {
return contactExchangeTask; return contactExchangeManager;
} }
@Provides @Provides

View File

@@ -8,7 +8,7 @@ import org.briarproject.bramble.BrambleCoreEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.account.BriarAccountModule; import org.briarproject.bramble.account.BriarAccountModule;
import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.contact.ContactExchangeTask; import org.briarproject.bramble.api.contact.ContactExchangeManager;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.CryptoExecutor; import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator; import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
@@ -128,7 +128,7 @@ public interface AndroidComponent
SettingsManager settingsManager(); SettingsManager settingsManager();
ContactExchangeTask contactExchangeTask(); ContactExchangeManager contactExchangeManager();
KeyAgreementTask keyAgreementTask(); KeyAgreementTask keyAgreementTask();

View File

@@ -4,15 +4,12 @@ import android.os.Bundle;
import android.support.annotation.UiThread; import android.support.annotation.UiThread;
import android.widget.Toast; import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactExchangeTask; import org.briarproject.bramble.api.contact.ContactExchangeManager;
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent; import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent; import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.keyagreement.KeyAgreementResult; import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
@@ -21,32 +18,25 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import static android.widget.Toast.LENGTH_LONG; import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.WARNING; import static java.util.Objects.requireNonNull;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
public class ContactExchangeActivity extends KeyAgreementActivity implements public class ContactExchangeActivity extends KeyAgreementActivity implements
EventListener { EventListener {
private static final Logger LOG =
Logger.getLogger(ContactExchangeActivity.class.getName());
@Inject @Inject
@IoExecutor @IoExecutor
Executor ioExecutor; Executor ioExecutor;
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@Inject @Inject
volatile ContactExchangeTask contactExchangeTask; volatile ContactExchangeManager contactExchangeManager;
@Inject
volatile IdentityManager identityManager;
@Override @Override
public void injectActivity(ActivityComponent component) { public void injectActivity(ActivityComponent component) {
@@ -62,76 +52,62 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
// Listen to updates from contactExchangeTask // Listen to updates from ContactExchangeManager
eventBus.addListener(this); eventBus.addListener(this);
} }
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop(); super.onStop();
// Stop listening to updates from contactExchangeTask // Stop listening to updates from ContactExchangeManager
eventBus.addListener(this); eventBus.addListener(this);
} }
private void startContactExchange(KeyAgreementResult result) { private void startContactExchange(KeyAgreementResult result) {
ioExecutor.execute(() -> { ioExecutor.execute(() -> {
LocalAuthor localAuthor;
// Load the local pseudonym
try {
localAuthor = identityManager.getLocalAuthor();
} catch (DbException e) {
logException(LOG, WARNING, e);
contactExchangeFailed();
return;
}
// Exchange contact details // Exchange contact details
contactExchangeTask.exchangeContacts(localAuthor, contactExchangeManager.exchangeContacts(result.getTransportId(),
result.getMasterKey(), result.getConnection(), result.getConnection(), result.getMasterKey(),
result.getTransportId(), result.wasAlice()); result.wasAlice());
}); });
} }
@Override @Override
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (e instanceof ContactExchangeSucceededEvent) { if (e instanceof ContactExchangeSucceededEvent) {
contactExchangeSucceeded( ContactExchangeSucceededEvent c = (ContactExchangeSucceededEvent) e;
((ContactExchangeSucceededEvent) e).getRemoteAuthor()); contactExchangeSucceeded(c.getRemoteAuthor());
} else if (e instanceof ContactExchangeFailedEvent) { } else if (e instanceof ContactExchangeFailedEvent) {
ContactExchangeFailedEvent fe = (ContactExchangeFailedEvent) e; ContactExchangeFailedEvent c = (ContactExchangeFailedEvent) e;
if (fe.wasDuplicateContact()) { if (c.wasDuplicateContact()) {
duplicateContact(fe.getDuplicateRemoteAuthor()); duplicateContact(requireNonNull(c.getDuplicateRemoteAuthor()));
} else { } else {
contactExchangeFailed(); contactExchangeFailed();
} }
} }
} }
@UiThread
private void contactExchangeSucceeded(Author remoteAuthor) { private void contactExchangeSucceeded(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> { String contactName = remoteAuthor.getName();
String contactName = remoteAuthor.getName(); String format = getString(R.string.contact_added_toast);
String format = getString(R.string.contact_added_toast); String text = String.format(format, contactName);
String text = String.format(format, contactName); Toast.makeText(this, text, LENGTH_LONG).show();
Toast.makeText(ContactExchangeActivity.this, text, LENGTH_LONG) supportFinishAfterTransition();
.show();
supportFinishAfterTransition();
});
} }
@UiThread
private void duplicateContact(Author remoteAuthor) { private void duplicateContact(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> { String contactName = remoteAuthor.getName();
String contactName = remoteAuthor.getName(); String format = getString(R.string.contact_already_exists);
String format = getString(R.string.contact_already_exists); String text = String.format(format, contactName);
String text = String.format(format, contactName); Toast.makeText(this, text, LENGTH_LONG).show();
Toast.makeText(ContactExchangeActivity.this, text, LENGTH_LONG) finish();
.show();
finish();
});
} }
@UiThread
private void contactExchangeFailed() { private void contactExchangeFailed() {
runOnUiThreadUnlessDestroyed(() -> { showErrorFragment(R.string.connection_error_explanation);
showErrorFragment(R.string.connection_error_explanation);
});
} }
@UiThread @UiThread