From 9ddec991ed38a7e623fc787c55707738dadfd7d6 Mon Sep 17 00:00:00 2001 From: Ben <ben@unknown4cedfb3732c9.localdomain> Date: Wed, 4 Jul 2018 13:53:04 +0200 Subject: [PATCH] Refactor Mailbox Exchange task (merge into ContactExchangeTask to avoid redundancy) --- .../api/contact/ContactExchangeTask.java | 5 - .../api/contact/MailboxExchangeTask.java | 8 - .../contact/ContactExchangeTaskImpl.java | 81 ++++- .../bramble/contact/ContactModule.java | 7 - .../contact/MailboxExchangeTaskImpl.java | 332 ------------------ .../briar/android/AndroidComponent.java | 3 - .../keyagreement/MailboxExchangeActivity.java | 4 +- 7 files changed, 72 insertions(+), 368 deletions(-) delete mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/contact/MailboxExchangeTask.java delete mode 100644 bramble-core/src/main/java/org/briarproject/bramble/contact/MailboxExchangeTaskImpl.java diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeTask.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeTask.java index ab9daacc9..6e8dbd8cf 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeTask.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactExchangeTask.java @@ -16,11 +16,6 @@ import java.util.Map; @NotNullByDefault public interface ContactExchangeTask { - /** - * The current version of the contact exchange protocol. - */ - byte PROTOCOL_VERSION = 1; - /** * Label for deriving Alice's header key from the master secret. */ diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/MailboxExchangeTask.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/MailboxExchangeTask.java deleted file mode 100644 index 7d7f60b9b..000000000 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/MailboxExchangeTask.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.briarproject.bramble.api.contact; - -public interface MailboxExchangeTask extends ContactExchangeTask { - /** - * The current version of the contact exchange protocol. - */ - byte PROTOCOL_VERSION = 2; -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactExchangeTaskImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactExchangeTaskImpl.java index 16bdc9ec5..784e27968 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactExchangeTaskImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactExchangeTaskImpl.java @@ -43,8 +43,13 @@ import java.util.logging.Logger; import javax.inject.Inject; + import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.api.contact.ContactTypes.CONTACT; +import static org.briarproject.bramble.api.contact.ContactTypes.MAILBOX_OWNER; +import static org.briarproject.bramble.api.contact.ContactTypes.PRIVATE_MAILBOX; import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO; +import static org.briarproject.bramble.api.contact.RecordTypes.MAILBOX_INFO; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.ValidationUtils.checkLength; @@ -60,6 +65,14 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask { private static final String SIGNING_LABEL_EXCHANGE = "org.briarproject.briar.contact/EXCHANGE"; + /** + * The version of the contact exchange protocol. Note: For backwards compatibility, + * the normal contact exchange is version 1, and 2 for Mailbox related exchanges + * Version 2 introduces a new field to the record, which indicates the contact type + */ + byte PROTOCOL_VERSION; + byte RECORD_TYPE; + private final DatabaseComponent db; private final ClientHelper clientHelper; private final RecordReaderFactory recordReaderFactory; @@ -106,6 +119,15 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask { LocalAuthor localAuthor, SecretKey masterSecret, DuplexTransportConnection conn, TransportId transportId, boolean alice, int localType, int remoteType) { + + if (remoteType == CONTACT) { + PROTOCOL_VERSION = 1; + RECORD_TYPE = CONTACT_INFO; + } else { + PROTOCOL_VERSION = 2; + RECORD_TYPE = MAILBOX_INFO; + } + this.listener = listener; this.localAuthor = localAuthor; this.conn = conn; @@ -161,7 +183,8 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask { streamWriterFactory.createContactExchangeStreamWriter(out, alice ? aliceHeaderKey : bobHeaderKey); RecordWriter recordWriter = - recordWriterFactory.createRecordWriter(streamWriter.getOutputStream()); + recordWriterFactory + .createRecordWriter(streamWriter.getOutputStream()); // Derive the nonces to be signed byte[] aliceNonce = crypto.mac(ALICE_NONCE_LABEL, masterSecret, @@ -259,8 +282,13 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask { long timestamp) throws IOException { BdfList authorList = clientHelper.toList(author); BdfDictionary props = clientHelper.toDictionary(properties); - BdfList payload = BdfList.of(authorList, props, signature, timestamp); - recordWriter.writeRecord(new Record(PROTOCOL_VERSION, CONTACT_INFO, + BdfList payload; + if (PROTOCOL_VERSION >= 2){ + payload = BdfList.of(authorList, props, signature, timestamp, localType); + } else { + payload = BdfList.of(authorList, props, signature, timestamp); + } + recordWriter.writeRecord(new Record(PROTOCOL_VERSION, RECORD_TYPE, clientHelper.toByteArray(payload))); LOG.info("Sent contact info"); } @@ -272,10 +300,14 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask { record = recordReader.readRecord(); if (record.getProtocolVersion() != PROTOCOL_VERSION) throw new FormatException(); - } while (record.getRecordType() != CONTACT_INFO); + } while (record.getRecordType() != RECORD_TYPE); LOG.info("Received contact info"); BdfList payload = clientHelper.toList(record.getPayload()); - checkSize(payload, 4); + if (PROTOCOL_VERSION >= 2) { + checkSize(payload, 5); + } else { + checkSize(payload, 4); + } Author author = clientHelper.parseAndValidateAuthor(payload.getList(0)); BdfDictionary props = payload.getDictionary(1); Map<TransportId, TransportProperties> properties = @@ -284,7 +316,13 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask { checkLength(signature, 1, MAX_SIGNATURE_LENGTH); long timestamp = payload.getLong(3); if (timestamp < 0) throw new FormatException(); - return new ContactInfo(author, properties, signature, timestamp, remoteType); + if (PROTOCOL_VERSION >= 2){ + int type = payload.getLong(4).intValue(); + if(type != remoteType) + throw new AssertionError(); + } + return new ContactInfo(author, properties, signature, timestamp, + remoteType); } private ContactId addContact(Author remoteAuthor, long timestamp, @@ -293,11 +331,32 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask { ContactId contactId; Transaction txn = db.startTransaction(false); try { - contactId = contactManager.addContact(txn, remoteAuthor, - localAuthor.getId(), masterSecret, timestamp, alice, - true, true); - transportPropertyManager.addRemoteProperties(txn, contactId, - remoteProperties); + switch (remoteType) { + case CONTACT: + contactId = contactManager.addContact(txn, remoteAuthor, + localAuthor.getId(), masterSecret, timestamp, alice, + true, true); + transportPropertyManager.addRemoteProperties(txn, contactId, + remoteProperties); + break; + case MAILBOX_OWNER: + contactId = + contactManager.addMailboxOwner(txn, remoteAuthor, + localAuthor.getId(), masterSecret, + timestamp, alice); + break; + case PRIVATE_MAILBOX: + contactId = + contactManager.addPrivateMailbox(txn, remoteAuthor, + localAuthor.getId(), masterSecret, + timestamp, alice); + transportPropertyManager.addRemoteProperties(txn, contactId, + remoteProperties); + break; + default: + throw new RuntimeException("Invalid remote contact type"); + } + db.commitTransaction(txn); } finally { db.endTransaction(txn); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactModule.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactModule.java index 3599ade1c..2cb610972 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactModule.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactModule.java @@ -2,7 +2,6 @@ package org.briarproject.bramble.contact; import org.briarproject.bramble.api.contact.ContactExchangeTask; import org.briarproject.bramble.api.contact.ContactManager; -import org.briarproject.bramble.api.contact.MailboxExchangeTask; import javax.inject.Inject; import javax.inject.Singleton; @@ -29,10 +28,4 @@ public class ContactModule { ContactExchangeTaskImpl contactExchangeTask) { return contactExchangeTask; } - - @Provides - MailboxExchangeTask provideMailboxExchangeTask( - MailboxExchangeTaskImpl mailboxExchangeTask) { - return mailboxExchangeTask; - } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/MailboxExchangeTaskImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/MailboxExchangeTaskImpl.java deleted file mode 100644 index 7d09cb6e6..000000000 --- a/bramble-core/src/main/java/org/briarproject/bramble/contact/MailboxExchangeTaskImpl.java +++ /dev/null @@ -1,332 +0,0 @@ -package org.briarproject.bramble.contact; - -import org.briarproject.bramble.api.FormatException; -import org.briarproject.bramble.api.client.ClientHelper; -import org.briarproject.bramble.api.contact.ContactExchangeListener; -import org.briarproject.bramble.api.contact.ContactId; -import org.briarproject.bramble.api.contact.ContactManager; -import org.briarproject.bramble.api.contact.MailboxExchangeTask; -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.db.Transaction; -import org.briarproject.bramble.api.identity.Author; -import org.briarproject.bramble.api.identity.LocalAuthor; -import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; -import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; -import org.briarproject.bramble.api.plugin.ConnectionManager; -import org.briarproject.bramble.api.plugin.TransportId; -import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; -import org.briarproject.bramble.api.properties.TransportProperties; -import org.briarproject.bramble.api.properties.TransportPropertyManager; -import org.briarproject.bramble.api.record.Record; -import org.briarproject.bramble.api.record.RecordReader; -import org.briarproject.bramble.api.record.RecordReaderFactory; -import org.briarproject.bramble.api.record.RecordWriter; -import org.briarproject.bramble.api.record.RecordWriterFactory; -import org.briarproject.bramble.api.system.Clock; -import org.briarproject.bramble.api.transport.StreamReaderFactory; -import org.briarproject.bramble.api.transport.StreamWriter; -import org.briarproject.bramble.api.transport.StreamWriterFactory; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.util.Map; -import java.util.logging.Logger; - -import javax.inject.Inject; - -import static java.util.logging.Level.WARNING; -import static org.briarproject.bramble.api.contact.ContactTypes.MAILBOX_OWNER; -import static org.briarproject.bramble.api.contact.RecordTypes.MAILBOX_INFO; -import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; -import static org.briarproject.bramble.util.LogUtils.logException; -import static org.briarproject.bramble.util.ValidationUtils.checkLength; -import static org.briarproject.bramble.util.ValidationUtils.checkSize; - -@MethodsNotNullByDefault -@ParametersNotNullByDefault -class MailboxExchangeTaskImpl extends Thread implements MailboxExchangeTask { - private static final Logger LOG = - Logger.getLogger(MailboxExchangeTaskImpl.class.getName()); - - private static final String SIGNING_LABEL_EXCHANGE = - "org.briarproject.briar.contact/EXCHANGE"; - - private final DatabaseComponent db; - private final ClientHelper clientHelper; - private final RecordReaderFactory recordReaderFactory; - private final RecordWriterFactory recordWriterFactory; - private final Clock clock; - private final ConnectionManager connectionManager; - private final ContactManager contactManager; - private final TransportPropertyManager transportPropertyManager; - private final CryptoComponent crypto; - private final StreamReaderFactory streamReaderFactory; - private final StreamWriterFactory streamWriterFactory; - - private volatile ContactExchangeListener listener; - private volatile LocalAuthor localAuthor; - private volatile DuplexTransportConnection conn; - private volatile TransportId transportId; - private volatile SecretKey masterSecret; - private volatile boolean alice; - private volatile int localType, remoteType; - - @Inject - MailboxExchangeTaskImpl(DatabaseComponent db, ClientHelper clientHelper, - RecordReaderFactory recordReaderFactory, - RecordWriterFactory recordWriterFactory, Clock clock, - ConnectionManager connectionManager, ContactManager contactManager, - TransportPropertyManager transportPropertyManager, - CryptoComponent crypto, StreamReaderFactory streamReaderFactory, - StreamWriterFactory streamWriterFactory) { - this.db = db; - this.clientHelper = clientHelper; - this.recordReaderFactory = recordReaderFactory; - this.recordWriterFactory = recordWriterFactory; - this.clock = clock; - this.connectionManager = connectionManager; - this.contactManager = contactManager; - this.transportPropertyManager = transportPropertyManager; - this.crypto = crypto; - this.streamReaderFactory = streamReaderFactory; - this.streamWriterFactory = streamWriterFactory; - } - - @Override - public void startExchange(ContactExchangeListener listener, - LocalAuthor localAuthor, SecretKey masterSecret, - DuplexTransportConnection conn, TransportId transportId, - boolean alice, int localType, int remoteType) { - this.listener = listener; - this.localAuthor = localAuthor; - this.conn = conn; - this.transportId = transportId; - this.masterSecret = masterSecret; - this.alice = alice; - this.localType = localType; - this.remoteType = remoteType; - start(); - - } - - @Override - public void run() { - // 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); - listener.contactExchangeFailed(); - tryToClose(conn); - return; - } - - // Get the local transport properties - Map<TransportId, TransportProperties> localProperties; - try { - localProperties = transportPropertyManager.getLocalProperties(); - } catch (DbException e) { - logException(LOG, WARNING, e); - listener.contactExchangeFailed(); - tryToClose(conn); - return; - } - - // Derive the header keys for the transport streams - SecretKey aliceHeaderKey = crypto.deriveKey(ALICE_KEY_LABEL, - masterSecret, new byte[] {PROTOCOL_VERSION}); - SecretKey bobHeaderKey = crypto.deriveKey(BOB_KEY_LABEL, masterSecret, - new byte[] {PROTOCOL_VERSION}); - - // Create the readers - InputStream streamReader = - streamReaderFactory.createContactExchangeStreamReader(in, - alice ? bobHeaderKey : aliceHeaderKey); - RecordReader recordReader = - recordReaderFactory.createRecordReader(streamReader); - - // Create the writers - StreamWriter streamWriter = - streamWriterFactory.createContactExchangeStreamWriter(out, - alice ? aliceHeaderKey : bobHeaderKey); - RecordWriter recordWriter = - recordWriterFactory - .createRecordWriter(streamWriter.getOutputStream()); - - // Derive the nonces to be signed - byte[] aliceNonce = crypto.mac(ALICE_NONCE_LABEL, masterSecret, - new byte[] {PROTOCOL_VERSION}); - byte[] bobNonce = crypto.mac(BOB_NONCE_LABEL, masterSecret, - new byte[] {PROTOCOL_VERSION}); - byte[] localNonce = alice ? aliceNonce : bobNonce; - byte[] remoteNonce = alice ? bobNonce : aliceNonce; - - // Sign the nonce - byte[] localSignature = sign(localAuthor, localNonce); - - // Exchange contact info - long localTimestamp = clock.currentTimeMillis(); - ContactInfo remoteInfo; - try { - if (alice) { - sendContactInfo(recordWriter, localAuthor, localProperties, - localSignature, localTimestamp); - recordWriter.flush(); - remoteInfo = receiveContactInfo(recordReader); - } else { - remoteInfo = receiveContactInfo(recordReader); - sendContactInfo(recordWriter, localAuthor, localProperties, - localSignature, localTimestamp); - recordWriter.flush(); - } - // Send EOF on the outgoing stream - streamWriter.sendEndOfStream(); - // Skip any remaining records from the incoming stream - try { - while (true) recordReader.readRecord(); - } catch (EOFException expected) { - LOG.info("End of stream"); - } - } catch (IOException e) { - logException(LOG, WARNING, e); - listener.contactExchangeFailed(); - tryToClose(conn); - return; - } - - // Verify the contact's signature - if (!verify(remoteInfo.author, remoteNonce, remoteInfo.signature)) { - LOG.warning("Invalid signature"); - listener.contactExchangeFailed(); - tryToClose(conn); - return; - } - - // The agreed timestamp is the minimum of the peers' timestamps - long timestamp = Math.min(localTimestamp, remoteInfo.timestamp); - - try { - ContactId contactId; - // Add the Contact/Repeater - contactId = addContact(remoteInfo.author, timestamp, - remoteInfo.properties); - - // Reuse the connection as a transport connection - connectionManager.manageOutgoingConnection(contactId, transportId, - conn); - // Pseudonym exchange succeeded - LOG.info("Pseudonym exchange succeeded"); - listener.contactExchangeSucceeded(remoteInfo.author); - } catch (ContactExistsException e) { - logException(LOG, WARNING, e); - tryToClose(conn); - listener.duplicateContact(remoteInfo.author); - } catch (DbException e) { - logException(LOG, WARNING, e); - tryToClose(conn); - listener.contactExchangeFailed(); - } - } - - private byte[] sign(LocalAuthor author, byte[] nonce) { - try { - return crypto.sign(SIGNING_LABEL_EXCHANGE, nonce, - author.getPrivateKey()); - } catch (GeneralSecurityException e) { - throw new AssertionError(); - } - } - - private boolean verify(Author author, byte[] nonce, byte[] signature) { - try { - return crypto.verifySignature(signature, SIGNING_LABEL_EXCHANGE, - nonce, author.getPublicKey()); - } catch (GeneralSecurityException e) { - return false; - } - } - - private void sendContactInfo(RecordWriter recordWriter, Author author, - Map<TransportId, TransportProperties> properties, byte[] signature, - long timestamp) throws IOException { - BdfList authorList = clientHelper.toList(author); - BdfDictionary props = clientHelper.toDictionary(properties); - BdfList payload = BdfList.of(authorList, props, signature, timestamp, localType); - recordWriter.writeRecord(new Record(PROTOCOL_VERSION, MAILBOX_INFO, - clientHelper.toByteArray(payload))); - LOG.info("Sent repeater info"); - } - - private ContactInfo receiveContactInfo(RecordReader recordReader) - throws IOException { - Record record; - do { - record = recordReader.readRecord(); - if (record.getProtocolVersion() != PROTOCOL_VERSION) - throw new FormatException(); - } while (record.getRecordType() != MAILBOX_INFO); - LOG.info("Received contact info"); - BdfList payload = clientHelper.toList(record.getPayload()); - checkSize(payload, 5); - Author author = clientHelper.parseAndValidateAuthor(payload.getList(0)); - BdfDictionary props = payload.getDictionary(1); - Map<TransportId, TransportProperties> properties = - clientHelper.parseAndValidateTransportPropertiesMap(props); - byte[] signature = payload.getRaw(2); - checkLength(signature, 1, MAX_SIGNATURE_LENGTH); - long timestamp = payload.getLong(3); - if (timestamp < 0) throw new FormatException(); - int type = payload.getLong(4).intValue(); - if(type != remoteType) - throw new AssertionError(); - return new ContactInfo(author, properties, signature, timestamp, type); - } - - private ContactId addContact(Author remoteAuthor, long timestamp, - Map<TransportId, TransportProperties> remoteProperties) - throws DbException { - ContactId contactId; - Transaction txn = db.startTransaction(false); - try { - if (remoteType == MAILBOX_OWNER) { - contactId = contactManager.addMailboxOwner(txn, remoteAuthor, - localAuthor.getId(), masterSecret, timestamp, alice); - //TODO: Do we need transport properties here? (Repeater will not contact the Owner) - } else { - contactId = contactManager.addPrivateMailbox(txn, remoteAuthor, - localAuthor.getId(), masterSecret, timestamp, alice); - transportPropertyManager.addRemoteProperties(txn, contactId, - remoteProperties); - } - - db.commitTransaction(txn); - } finally { - db.endTransaction(txn); - } - return contactId; - } - - 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); - } - } - - -} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java index 9c140a021..778a6f2b9 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java @@ -7,7 +7,6 @@ import org.briarproject.bramble.BrambleCoreEagerSingletons; import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.api.contact.ContactExchangeTask; import org.briarproject.bramble.api.contact.ContactManager; -import org.briarproject.bramble.api.contact.MailboxExchangeTask; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoExecutor; import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator; @@ -130,8 +129,6 @@ public interface AndroidComponent ContactExchangeTask contactExchangeTask(); - MailboxExchangeTask mailboxExchangeTask(); - KeyAgreementTask keyAgreementTask(); PayloadEncoder payloadEncoder(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/MailboxExchangeActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/MailboxExchangeActivity.java index f2764266a..b3f39a560 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/MailboxExchangeActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/MailboxExchangeActivity.java @@ -5,7 +5,7 @@ import android.support.annotation.UiThread; import android.widget.Toast; import org.briarproject.bramble.api.contact.ContactExchangeListener; -import org.briarproject.bramble.api.contact.MailboxExchangeTask; +import org.briarproject.bramble.api.contact.ContactExchangeTask; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.IdentityManager; @@ -33,7 +33,7 @@ public class MailboxExchangeActivity extends KeyAgreementActivity implements Logger.getLogger(MailboxExchangeActivity.class.getName()); @Inject - volatile MailboxExchangeTask mailboxExchangeTask; + volatile ContactExchangeTask mailboxExchangeTask; @Inject volatile IdentityManager identityManager; -- GitLab