mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Replace events with return value and exceptions.
This commit is contained in:
@@ -1,16 +1,24 @@
|
||||
package org.briarproject.bramble.api.contact;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface ContactExchangeManager {
|
||||
|
||||
/**
|
||||
* Exchanges contact information with a remote peer.
|
||||
*
|
||||
* @return The contact's pseudonym
|
||||
* @throws ContactExistsException If the contact already exists
|
||||
*/
|
||||
void exchangeContacts(TransportId t, DuplexTransportConnection conn,
|
||||
SecretKey masterKey, boolean alice);
|
||||
Author exchangeContacts(TransportId t, DuplexTransportConnection conn,
|
||||
SecretKey masterKey, boolean alice) throws IOException, DbException;
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package org.briarproject.bramble.api.contact.event;
|
||||
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@NotNullByDefault
|
||||
public class ContactExchangeFailedEvent extends Event {
|
||||
|
||||
@Nullable
|
||||
private final Author duplicateRemoteAuthor;
|
||||
|
||||
public ContactExchangeFailedEvent(@Nullable Author duplicateRemoteAuthor) {
|
||||
this.duplicateRemoteAuthor = duplicateRemoteAuthor;
|
||||
}
|
||||
|
||||
public ContactExchangeFailedEvent() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Author getDuplicateRemoteAuthor() {
|
||||
return duplicateRemoteAuthor;
|
||||
}
|
||||
|
||||
public boolean wasDuplicateContact() {
|
||||
return duplicateRemoteAuthor != null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.briarproject.bramble.api.contact.event;
|
||||
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public class ContactExchangeSucceededEvent extends Event {
|
||||
|
||||
private final Author remoteAuthor;
|
||||
|
||||
public ContactExchangeSucceededEvent(Author remoteAuthor) {
|
||||
this.remoteAuthor = remoteAuthor;
|
||||
}
|
||||
|
||||
public Author getRemoteAuthor() {
|
||||
return remoteAuthor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,16 +6,12 @@ import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.contact.ContactExchangeManager;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
|
||||
import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent;
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
@@ -46,7 +42,6 @@ import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO;
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||
@@ -56,7 +51,6 @@ import static org.briarproject.bramble.contact.ContactExchangeConstants.BOB_KEY_
|
||||
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.ValidationUtils.checkLength;
|
||||
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
||||
|
||||
@@ -85,7 +79,6 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
|
||||
private final ClientHelper clientHelper;
|
||||
private final RecordReaderFactory recordReaderFactory;
|
||||
private final RecordWriterFactory recordWriterFactory;
|
||||
private final EventBus eventBus;
|
||||
private final Clock clock;
|
||||
private final ConnectionManager connectionManager;
|
||||
private final ContactManager contactManager;
|
||||
@@ -98,7 +91,7 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
|
||||
@Inject
|
||||
ContactExchangeManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
|
||||
RecordReaderFactory recordReaderFactory,
|
||||
RecordWriterFactory recordWriterFactory, EventBus eventBus,
|
||||
RecordWriterFactory recordWriterFactory,
|
||||
Clock clock, ConnectionManager connectionManager,
|
||||
ContactManager contactManager, IdentityManager identityManager,
|
||||
TransportPropertyManager transportPropertyManager,
|
||||
@@ -108,7 +101,6 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
|
||||
this.clientHelper = clientHelper;
|
||||
this.recordReaderFactory = recordReaderFactory;
|
||||
this.recordWriterFactory = recordWriterFactory;
|
||||
this.eventBus = eventBus;
|
||||
this.clock = clock;
|
||||
this.connectionManager = connectionManager;
|
||||
this.contactManager = contactManager;
|
||||
@@ -120,33 +112,17 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exchangeContacts(TransportId t, DuplexTransportConnection conn,
|
||||
SecretKey masterKey, boolean alice) {
|
||||
public Author exchangeContacts(TransportId t,
|
||||
DuplexTransportConnection conn, SecretKey masterKey, boolean alice)
|
||||
throws IOException, DbException {
|
||||
// Get the transport connection's input and output streams
|
||||
InputStream in;
|
||||
OutputStream out;
|
||||
try {
|
||||
in = conn.getReader().getInputStream();
|
||||
out = conn.getWriter().getOutputStream();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
tryToClose(conn);
|
||||
eventBus.broadcast(new ContactExchangeFailedEvent());
|
||||
return;
|
||||
}
|
||||
InputStream in = conn.getReader().getInputStream();
|
||||
OutputStream out = conn.getWriter().getOutputStream();
|
||||
|
||||
// Get the local author and transport properties
|
||||
LocalAuthor localAuthor;
|
||||
Map<TransportId, TransportProperties> localProperties;
|
||||
try {
|
||||
localAuthor = identityManager.getLocalAuthor();
|
||||
localProperties = transportPropertyManager.getLocalProperties();
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
eventBus.broadcast(new ContactExchangeFailedEvent());
|
||||
tryToClose(conn);
|
||||
return;
|
||||
}
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
||||
Map<TransportId, TransportProperties> localProperties =
|
||||
transportPropertyManager.getLocalProperties();
|
||||
|
||||
// Derive the header keys for the transport streams
|
||||
SecretKey aliceHeaderKey = crypto.deriveKey(ALICE_KEY_LABEL, masterKey,
|
||||
@@ -183,58 +159,37 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
|
||||
// Exchange contact info
|
||||
long localTimestamp = clock.currentTimeMillis();
|
||||
ContactInfo remoteInfo;
|
||||
try {
|
||||
if (alice) {
|
||||
sendContactInfo(recordWriter, localAuthor, localProperties,
|
||||
localSignature, localTimestamp);
|
||||
remoteInfo = receiveContactInfo(recordReader);
|
||||
} else {
|
||||
remoteInfo = receiveContactInfo(recordReader);
|
||||
sendContactInfo(recordWriter, localAuthor, localProperties,
|
||||
localSignature, localTimestamp);
|
||||
}
|
||||
// Send EOF on the outgoing stream
|
||||
streamWriter.sendEndOfStream();
|
||||
// Skip any remaining records from the incoming stream
|
||||
recordReader.readRecord(r -> false, IGNORE);
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
eventBus.broadcast(new ContactExchangeFailedEvent());
|
||||
tryToClose(conn);
|
||||
return;
|
||||
if (alice) {
|
||||
sendContactInfo(recordWriter, localAuthor, localProperties,
|
||||
localSignature, localTimestamp);
|
||||
remoteInfo = receiveContactInfo(recordReader);
|
||||
} else {
|
||||
remoteInfo = receiveContactInfo(recordReader);
|
||||
sendContactInfo(recordWriter, localAuthor, localProperties,
|
||||
localSignature, localTimestamp);
|
||||
}
|
||||
// Send EOF on the outgoing stream
|
||||
streamWriter.sendEndOfStream();
|
||||
// Skip any remaining records from the incoming stream
|
||||
recordReader.readRecord(r -> false, IGNORE);
|
||||
|
||||
// Verify the contact's signature
|
||||
if (!verify(remoteInfo.author, remoteNonce, remoteInfo.signature)) {
|
||||
LOG.warning("Invalid signature");
|
||||
eventBus.broadcast(new ContactExchangeFailedEvent());
|
||||
tryToClose(conn);
|
||||
return;
|
||||
throw new FormatException();
|
||||
}
|
||||
|
||||
// The agreed timestamp is the minimum of the peers' timestamps
|
||||
long timestamp = Math.min(localTimestamp, remoteInfo.timestamp);
|
||||
|
||||
try {
|
||||
// Add the contact
|
||||
ContactId contactId = addContact(remoteInfo.author, localAuthor,
|
||||
masterKey, timestamp, alice, remoteInfo.properties);
|
||||
// Reuse the connection as a transport connection
|
||||
connectionManager.manageOutgoingConnection(contactId, t, conn);
|
||||
// Pseudonym exchange succeeded
|
||||
LOG.info("Pseudonym exchange succeeded");
|
||||
eventBus.broadcast(
|
||||
new ContactExchangeSucceededEvent(remoteInfo.author));
|
||||
} catch (ContactExistsException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
tryToClose(conn);
|
||||
eventBus.broadcast(
|
||||
new ContactExchangeFailedEvent(e.getRemoteAuthor()));
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
tryToClose(conn);
|
||||
eventBus.broadcast(new ContactExchangeFailedEvent());
|
||||
}
|
||||
// Add the contact
|
||||
ContactId contactId = addContact(remoteInfo.author, localAuthor,
|
||||
masterKey, timestamp, alice, remoteInfo.properties);
|
||||
// Reuse the connection as a transport connection
|
||||
connectionManager.manageOutgoingConnection(contactId, t, conn);
|
||||
// Pseudonym exchange succeeded
|
||||
LOG.info("Pseudonym exchange succeeded");
|
||||
return remoteInfo.author;
|
||||
}
|
||||
|
||||
private byte[] sign(LocalAuthor author, byte[] nonce) {
|
||||
@@ -298,16 +253,6 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
|
||||
});
|
||||
}
|
||||
|
||||
private void tryToClose(DuplexTransportConnection conn) {
|
||||
try {
|
||||
LOG.info("Closing connection");
|
||||
conn.getReader().dispose(true, true);
|
||||
conn.getWriter().dispose(true);
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ContactInfo {
|
||||
|
||||
private final Author author;
|
||||
|
||||
@@ -7,58 +7,63 @@ import android.arch.lifecycle.MutableLiveData;
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactExchangeManager;
|
||||
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
|
||||
import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@NotNullByDefault
|
||||
class ContactExchangeViewModel extends AndroidViewModel
|
||||
implements EventListener {
|
||||
class ContactExchangeViewModel extends AndroidViewModel {
|
||||
|
||||
private static final Logger LOG =
|
||||
getLogger(ContactExchangeViewModel.class.getName());
|
||||
|
||||
private final Executor ioExecutor;
|
||||
private final ContactExchangeManager contactExchangeManager;
|
||||
private final EventBus eventBus;
|
||||
private final MutableLiveData<Boolean> succeeded = new MutableLiveData<>();
|
||||
|
||||
@Nullable
|
||||
private Author remoteAuthor, duplicateAuthor;
|
||||
private volatile Author remoteAuthor, duplicateAuthor;
|
||||
|
||||
@Inject
|
||||
ContactExchangeViewModel(Application app, @IoExecutor Executor ioExecutor,
|
||||
ContactExchangeManager contactExchangeManager, EventBus eventBus) {
|
||||
ContactExchangeManager contactExchangeManager) {
|
||||
super(app);
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.contactExchangeManager = contactExchangeManager;
|
||||
this.eventBus = eventBus;
|
||||
eventBus.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
super.onCleared();
|
||||
eventBus.removeListener(this);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void startContactExchange(TransportId t, DuplexTransportConnection conn,
|
||||
SecretKey masterKey, boolean alice) {
|
||||
ioExecutor.execute(() -> contactExchangeManager.exchangeContacts(t,
|
||||
conn, masterKey, alice));
|
||||
ioExecutor.execute(() -> {
|
||||
try {
|
||||
remoteAuthor = contactExchangeManager.exchangeContacts(t, conn,
|
||||
masterKey, alice);
|
||||
succeeded.postValue(true);
|
||||
} catch (ContactExistsException e) {
|
||||
duplicateAuthor = e.getRemoteAuthor();
|
||||
succeeded.postValue(false);
|
||||
} catch (DbException | IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
succeeded.postValue(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@@ -76,18 +81,4 @@ class ContactExchangeViewModel extends AndroidViewModel
|
||||
LiveData<Boolean> getSucceeded() {
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventOccurred(Event e) {
|
||||
if (e instanceof ContactExchangeSucceededEvent) {
|
||||
ContactExchangeSucceededEvent c = (ContactExchangeSucceededEvent) e;
|
||||
remoteAuthor = c.getRemoteAuthor();
|
||||
succeeded.setValue(true);
|
||||
} else if (e instanceof ContactExchangeFailedEvent) {
|
||||
ContactExchangeFailedEvent c = (ContactExchangeFailedEvent) e;
|
||||
if (c.wasDuplicateContact())
|
||||
duplicateAuthor = requireNonNull(c.getDuplicateRemoteAuthor());
|
||||
succeeded.setValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user