From f2169b7d83e30234e073f479b93f1d87138fa351 Mon Sep 17 00:00:00 2001
From: Julian Dehm <goapunk@riseup.net>
Date: Thu, 4 Oct 2018 13:19:32 +0200
Subject: [PATCH] Mailbox introduction

---
 .../bramble/api/sync/MessageId.java           |   3 +-
 .../bramble/BrambleCoreEagerSingletons.java   |   3 +
 .../bramble/BrambleCoreModule.java            |   3 +
 .../AbstractIntroduceeSession.java            |   2 +-
 .../introduction/AbstractProtocolEngine.java  |  10 +-
 .../IntroduceeProtocolEngine.java             |  13 +--
 .../introduction/IntroduceeSession.java       |  11 +-
 .../introduction/MailboxAcceptMessage.java    |   5 +-
 .../introduction/MailboxAuthMessage.java      |   8 ++
 .../MailboxIntroductionManagerImpl.java       | 103 +++++++++++++-----
 .../MailboxIntroductionValidator.java         |  13 ++-
 .../introduction/MailboxMessageEncoder.java   |   2 +
 .../MailboxMessageEncoderImpl.java            |   5 +-
 .../introduction/MailboxMessageParser.java    |   1 -
 .../MailboxMessageParserImpl.java             |  10 +-
 .../introduction/MailboxProtocolEngine.java   |  18 +--
 .../mailbox/introduction/MailboxSession.java  |  11 +-
 .../MailboxSessionParserImpl.java             |   7 +-
 .../introduction/OwnerProtocolEngine.java     |  24 ++--
 .../mailbox/introduction/OwnerSession.java    |   8 +-
 .../mailbox/introduction/ProtocolEngine.java  |   8 +-
 .../BrambleIntegrationTestComponent.java      |   4 +-
 .../MailboxIntroductionIntegrationTest.java   |  48 +++++---
 ...xIntroductionIntegrationTestComponent.java |   2 +
 .../android/contact/ConversationActivity.java |   7 +-
 .../contact/ConversationRequestItem.java      |   2 +-
 .../reveal/RevealContactsControllerImpl.java  |   2 +-
 27 files changed, 211 insertions(+), 122 deletions(-)

diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java
index 907b6e2d0..d483eb71d 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageId.java
@@ -3,6 +3,7 @@ package org.briarproject.bramble.api.sync;
 import org.briarproject.bramble.api.UniqueId;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.ThreadSafe;
 
 /**
@@ -29,7 +30,7 @@ public class MessageId extends UniqueId {
 	}
 
 	@Override
-	public boolean equals(Object o) {
+	public boolean equals(@Nullable Object o) {
 		return o instanceof MessageId && super.equals(o);
 	}
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreEagerSingletons.java b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreEagerSingletons.java
index f5723ddf7..f73c9ce57 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreEagerSingletons.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreEagerSingletons.java
@@ -6,6 +6,7 @@ import org.briarproject.bramble.db.DatabaseExecutorModule;
 import org.briarproject.bramble.identity.IdentityModule;
 import org.briarproject.bramble.lifecycle.LifecycleModule;
 import org.briarproject.bramble.mailbox.MailboxModule;
+import org.briarproject.bramble.mailbox.introduction.MailboxIntroductionModule;
 import org.briarproject.bramble.plugin.PluginModule;
 import org.briarproject.bramble.properties.PropertiesModule;
 import org.briarproject.bramble.reporting.ReportingModule;
@@ -40,4 +41,6 @@ public interface BrambleCoreEagerSingletons {
 
 	void inject(VersioningModule.EagerSingletons init);
 
+	void inject(MailboxIntroductionModule.EagerSingletons init);
+
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java
index 3419aea43..62ceff1a6 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java
@@ -12,6 +12,7 @@ import org.briarproject.bramble.identity.IdentityModule;
 import org.briarproject.bramble.keyagreement.KeyAgreementModule;
 import org.briarproject.bramble.lifecycle.LifecycleModule;
 import org.briarproject.bramble.mailbox.MailboxModule;
+import org.briarproject.bramble.mailbox.introduction.MailboxIntroductionModule;
 import org.briarproject.bramble.plugin.PluginModule;
 import org.briarproject.bramble.properties.PropertiesModule;
 import org.briarproject.bramble.record.RecordModule;
@@ -39,6 +40,7 @@ import dagger.Module;
 		KeyAgreementModule.class,
 		LifecycleModule.class,
 		MailboxModule.class,
+		MailboxIntroductionModule.class,
 		PluginModule.class,
 		PropertiesModule.class,
 		RecordModule.class,
@@ -59,6 +61,7 @@ public class BrambleCoreModule {
 		c.inject(new DatabaseExecutorModule.EagerSingletons());
 		c.inject(new IdentityModule.EagerSingletons());
 		c.inject(new LifecycleModule.EagerSingletons());
+		c.inject(new MailboxIntroductionModule.EagerSingletons());
 		c.inject(new PluginModule.EagerSingletons());
 		c.inject(new PropertiesModule.EagerSingletons());
 		c.inject(new ReportingModule.EagerSingletons());
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/AbstractIntroduceeSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/AbstractIntroduceeSession.java
index 438bc62cb..dac48220c 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/AbstractIntroduceeSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/AbstractIntroduceeSession.java
@@ -99,7 +99,7 @@ abstract class AbstractIntroduceeSession<S extends State> extends Session<S>
 
 		private Common(boolean alice, @Nullable MessageId lastMessageId,
 				@Nullable byte[] ephemeralPublicKey,
-				@Nullable long acceptTimestamp, @Nullable byte[] macKey) {
+				long acceptTimestamp, @Nullable byte[] macKey) {
 			this.alice = alice;
 			this.lastMessageId = lastMessageId;
 			this.ephemeralPublicKey = ephemeralPublicKey;
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/AbstractProtocolEngine.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/AbstractProtocolEngine.java
index 8a998aa5e..2dcce8ffc 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/AbstractProtocolEngine.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/AbstractProtocolEngine.java
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.ClientHelper;
 import org.briarproject.bramble.api.client.ContactGroupFactory;
 import org.briarproject.bramble.api.client.SessionId;
+import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.contact.ContactManager;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.db.DatabaseComponent;
@@ -94,7 +95,7 @@ abstract class AbstractProtocolEngine<S extends Session>
 	}
 
 	Message sendIntroduceeResponseMessage(Transaction txn, PeerSession s,
-			MessageId previousMessage, long timestamp,
+			@Nullable MessageId previousMessage, long timestamp,
 			byte[] ephemeralPublicKey, byte[] mac, byte[] signature,
 			long acceptTimestamp) throws DbException {
 		Message m = messageEncoder
@@ -107,12 +108,12 @@ abstract class AbstractProtocolEngine<S extends Session>
 	}
 
 	Message sendMailboxAuthMessage(Transaction txn, PeerSession s,
-			long timestamp,
+			long timestamp, ContactId contactId,
 			Map<TransportId, TransportProperties> transportProperties,
 			byte[] mac, byte[] signature) throws DbException {
 		Message m = messageEncoder
 				.encodeMailboxAuthMessage(s.getContactGroupId(), timestamp,
-						s.getLastRemoteMessageId(), s.getSessionId(),
+						s.getLastRemoteMessageId(), s.getSessionId(), contactId,
 						transportProperties, mac, signature,
 						s.getAbortCounter());
 		sendMessage(txn, MAILBOX_AUTH, s.getSessionId(), m,
@@ -156,8 +157,7 @@ abstract class AbstractProtocolEngine<S extends Session>
 	boolean isInvalidDependency(@Nullable MessageId lastRemoteMessageId,
 			@Nullable MessageId dependency) {
 		if (dependency == null) return lastRemoteMessageId != null;
-		return lastRemoteMessageId == null ||
-				!dependency.equals(lastRemoteMessageId);
+		return !dependency.equals(lastRemoteMessageId);
 	}
 
 	long getLocalTimestamp(long localTimestamp, long requestTimestamp) {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/IntroduceeProtocolEngine.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/IntroduceeProtocolEngine.java
index 83fe29e7c..dde4ca21d 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/IntroduceeProtocolEngine.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/IntroduceeProtocolEngine.java
@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionAbortedEvent;
 import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionRequestReceivedEvent;
 import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionSucceededEvent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.plugin.TransportId;
 import org.briarproject.bramble.api.properties.TransportPropertyManager;
 import org.briarproject.bramble.api.sync.Message;
@@ -31,11 +32,11 @@ import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.bramble.mailbox.introduction.IntroduceeState.AWAIT_AUTH;
 import static org.briarproject.bramble.mailbox.introduction.IntroduceeState.MAILBOX_ADDED;
 import static org.briarproject.bramble.mailbox.introduction.IntroduceeState.START;
 import static org.briarproject.bramble.util.LogUtils.logException;
 
+@NotNullByDefault
 class IntroduceeProtocolEngine
 		extends AbstractProtocolEngine<IntroduceeSession> {
 
@@ -57,8 +58,7 @@ class IntroduceeProtocolEngine
 
 	@Override
 	public IntroduceeSession onRequestMessage(Transaction txn,
-			IntroduceeSession session, RequestMessage m)
-			throws DbException, FormatException {
+			IntroduceeSession session, RequestMessage m) {
 		throw new UnsupportedOperationException();
 	}
 
@@ -85,14 +85,13 @@ class IntroduceeProtocolEngine
 
 	@Override
 	public IntroduceeSession onDeclineMessage(Transaction txn,
-			IntroduceeSession s, DeclineMessage m)
-			throws DbException, FormatException {
+			IntroduceeSession s, DeclineMessage m) {
 		throw new UnsupportedOperationException();
 	}
 
 	@Override
 	public IntroduceeSession onAuthMessage(Transaction txn, IntroduceeSession s,
-			MailboxAuthMessage m) throws DbException, FormatException {
+			MailboxAuthMessage m) throws DbException {
 		switch (s.getState()) {
 			case AWAIT_AUTH:
 				return handleAuthMessage(txn, s, m);
@@ -216,7 +215,7 @@ class IntroduceeProtocolEngine
 							localTimestamp);
 			//TODO: Check for reasons to decline and if any, move to LOCAL_DECLINE
 			// Move to the AWAIT_REMOTE_RESPONSE state
-			return IntroduceeSession.addLocalAuth(s, AWAIT_AUTH, reply);
+			return IntroduceeSession.addLocalAuth(s, reply);
 		} catch (GeneralSecurityException e) {
 			logException(LOG, WARNING, e);
 			return abort(txn, s);
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/IntroduceeSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/IntroduceeSession.java
index 9ffd984ed..3a529ab23 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/IntroduceeSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/IntroduceeSession.java
@@ -33,11 +33,11 @@ class IntroduceeSession extends AbstractIntroduceeSession<IntroduceeState> {
 	}
 
 	static IntroduceeSession getInitial(GroupId contactGroupId,
-			SessionId sessionId, Author introducer, boolean localIsAlice,
+			SessionId sessionId, Author introducer,
 			Author remoteAuthor) {
-		Local local = new Local(localIsAlice, null, -1, null, null, -1, null);
+		Local local = new Local(false, null, -1, null, null, -1, null);
 		Remote remote =
-				new Remote(!localIsAlice, remoteAuthor, null, null, null, -1,
+				new Remote(true, remoteAuthor, null, null, null, -1,
 						null);
 		return new IntroduceeSession(sessionId, START, -1, contactGroupId,
 				introducer, local, remote, null, null, 0);
@@ -60,13 +60,14 @@ class IntroduceeSession extends AbstractIntroduceeSession<IntroduceeState> {
 	}
 
 	static IntroduceeSession addLocalAuth(IntroduceeSession s,
-			IntroduceeState state, Message m) {
+			Message m) {
 		// add mac key and sent message
 		Local local = new Local(false, m.getId(), m.getTimestamp(),
 				s.local.ephemeralPublicKey, s.local.ephemeralPrivateKey,
 				s.local.acceptTimestamp, s.local.macKey);
 
-		return new IntroduceeSession(s.getSessionId(), state,
+		return new IntroduceeSession(s.getSessionId(),
+				IntroduceeState.AWAIT_AUTH,
 				s.getRequestTimestamp(), s.contactGroupId, s.introducer, local,
 				s.remote, s.masterKey, s.transportKeys, s.getAbortCounter());
 	}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxAcceptMessage.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxAcceptMessage.java
index bec6267bd..b97a04682 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxAcceptMessage.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxAcceptMessage.java
@@ -14,13 +14,15 @@ import javax.annotation.concurrent.Immutable;
 class MailboxAcceptMessage extends AbstractMailboxIntroductionMessage {
 
 	private final SessionId sessionId;
+	@Nullable
 	private final Author author;
 	private final byte[] ephemeralPublicKey;
 	private final long acceptTimestamp;
 
 	protected MailboxAcceptMessage(MessageId messageId, GroupId groupId,
 			long timestamp, @Nullable MessageId previousMessageId,
-			SessionId sessionId, Author author, byte[] ephemeralPublicKey,
+			SessionId sessionId, @Nullable Author author,
+			byte[] ephemeralPublicKey,
 			long acceptTimestamp) {
 		super(messageId, groupId, timestamp, previousMessageId);
 		this.sessionId = sessionId;
@@ -33,6 +35,7 @@ class MailboxAcceptMessage extends AbstractMailboxIntroductionMessage {
 		return sessionId;
 	}
 
+	@Nullable
 	public Author getAuthor() {
 		return author;
 	}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxAuthMessage.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxAuthMessage.java
index 8f7871be9..26254e265 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxAuthMessage.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxAuthMessage.java
@@ -1,6 +1,7 @@
 package org.briarproject.bramble.mailbox.introduction;
 
 import org.briarproject.bramble.api.client.SessionId;
+import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.plugin.TransportId;
 import org.briarproject.bramble.api.properties.TransportProperties;
@@ -17,6 +18,7 @@ import javax.annotation.concurrent.Immutable;
 class MailboxAuthMessage extends AbstractMailboxIntroductionMessage {
 
 	private final SessionId sessionId;
+	private final ContactId contactId;
 	private final Map<TransportId, TransportProperties> transportProperties;
 	private final byte[] mac;
 	private final byte[] signature;
@@ -24,10 +26,12 @@ class MailboxAuthMessage extends AbstractMailboxIntroductionMessage {
 	protected MailboxAuthMessage(MessageId messageId, GroupId groupId,
 			long timestamp, @Nullable MessageId previousMessageId,
 			SessionId sessionId,
+			ContactId contactId,
 			Map<TransportId, TransportProperties> transportProperties,
 			byte[] mac, byte[] signature) {
 		super(messageId, groupId, timestamp, previousMessageId);
 		this.sessionId = sessionId;
+		this.contactId = contactId;
 		this.transportProperties = transportProperties;
 		this.mac = mac;
 		this.signature = signature;
@@ -48,4 +52,8 @@ class MailboxAuthMessage extends AbstractMailboxIntroductionMessage {
 	public Map<TransportId, TransportProperties> getTransportProperties() {
 		return transportProperties;
 	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionManagerImpl.java
index c10a7bfce..ccca7b691 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionManagerImpl.java
@@ -1,5 +1,6 @@
 package org.briarproject.bramble.mailbox.introduction;
 
+import org.briarproject.bramble.api.BrambleConfig;
 import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.BdfIncomingMessageHook;
 import org.briarproject.bramble.api.client.ClientHelper;
@@ -23,6 +24,7 @@ import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.lifecycle.IoExecutor;
 import org.briarproject.bramble.api.mailbox.MailboxIntroductionManager;
 import org.briarproject.bramble.api.mailbox.Role;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.Client;
 import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.GroupId;
@@ -50,6 +52,7 @@ import static org.briarproject.bramble.mailbox.introduction.IntroductionConstant
 import static org.briarproject.bramble.mailbox.introduction.MessageType.MAILBOX_ACCEPT;
 import static org.briarproject.bramble.mailbox.introduction.MessageType.MAILBOX_REQUEST;
 
+@NotNullByDefault
 class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 		implements MailboxIntroductionManager, Client, ClientVersioningHook,
 		ContactHook {
@@ -57,6 +60,7 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 	private static final Logger LOG =
 			Logger.getLogger(MailboxIntroductionManagerImpl.class.getName());
 	private final Executor ioExecutor;
+	private final BrambleConfig brambleConfig;
 	private final ClientVersioningManager clientVersioningManager;
 	private final ContactGroupFactory contactGroupFactory;
 	private final ContactManager contactManager;
@@ -73,6 +77,7 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 
 	@Inject
 	MailboxIntroductionManagerImpl(@IoExecutor Executor ioExecutor,
+			BrambleConfig brambleConfig,
 			DatabaseComponent db, ClientHelper clientHelper,
 			ClientVersioningManager clientVersioningManager,
 			MetadataParser metadataParser,
@@ -87,6 +92,7 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 			IdentityManager identityManager, Clock clock) {
 		super(db, clientHelper, metadataParser);
 		this.ioExecutor = ioExecutor;
+		this.brambleConfig = brambleConfig;
 		this.clientVersioningManager = clientVersioningManager;
 		this.contactGroupFactory = contactGroupFactory;
 		this.contactManager = contactManager;
@@ -170,42 +176,50 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 		setupNewContact(txn, privateMailbox);
 		ioExecutor.execute(() -> {
 			try {
-				for (Contact c : db.getContacts(txn)) {
-					makeIntroduction(privateMailbox, c,
-							clock.currentTimeMillis());
-				}
+				startIntroductionMailboxAdded(privateMailbox);
 			} catch (DbException e) {
-				LOG.warning("Mailbox introduction failed: " + e.toString());
+				LOG.warning("Starting mailbox introductions failed:" + e);
 			}
 		});
 	}
 
+	private void startIntroductionMailboxAdded(PrivateMailbox privateMailbox)
+			throws DbException {
+		Transaction txn = null;
+		Collection<Contact> contacts;
+		try {
+			txn = db.startTransaction(true);
+			contacts = db.getContacts(txn);
+			db.commitTransaction(txn);
+		} finally {
+			db.endTransaction(txn);
+		}
+		for (Contact c : contacts) {
+			makeIntroduction(privateMailbox, c,
+					clock.currentTimeMillis());
+		}
+	}
+
 	@Override
 	protected boolean incomingMessage(Transaction txn, Message m, BdfList body,
 			BdfDictionary bdfMeta) throws DbException, FormatException {
+		if (brambleConfig.isMailbox())
+			return mailboxIncomingMessage(txn, m, body, bdfMeta);
 		MessageMetadata meta = messageParser.parseMetadata(bdfMeta);
 		// Look up the session, if there is one
 		SessionId sessionId = meta.getSessionId();
-		Session session = null;
-		if (sessionId == null) {
-			if (meta.getMessageType() != MAILBOX_REQUEST)
-				throw new AssertionError();
-			session = createMailboxSession(txn, m, body);
-			sessionId = session.getSessionId();
-		}
+		if (sessionId == null) throw new FormatException();
 		StoredSession ss = getSession(txn, sessionId);
+		Session session;
 		// Handle the message
 		MessageId storageId;
 		if (ss == null) {
-			ProtocolEngine engine;
-			if (meta.getMessageType() == MAILBOX_REQUEST)
-				engine = mailboxProtocolEngine;
-			else if (meta.getMessageType() == MAILBOX_ACCEPT) {
-				session = createIntroduceeSession(txn, m, body);
-				engine = introduceeProtocolEngine;
-			} else throw new FormatException();
-			if (session == null) throw new AssertionError();
-			session = handleMessage(txn, m, body, meta, session, engine);
+			if (meta.getMessageType() != MAILBOX_ACCEPT)
+				throw new FormatException();
+			IntroduceeSession introduceeSession =
+					createIntroduceeSession(txn, m, body);
+			session = handleMessage(txn, m, body, meta, introduceeSession,
+					introduceeProtocolEngine);
 			storageId = createStorageId(txn);
 		} else {
 			storageId = ss.storageId;
@@ -216,11 +230,6 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 							sessionParser.parseOwnerSession(ss.bdfSession),
 							ownerProtocolEngine);
 					break;
-				case MAILBOX:
-					session = handleMessage(txn, m, body, meta, sessionParser
-									.parseMailboxSession(m.getGroupId(), ss.bdfSession),
-							mailboxProtocolEngine);
-					break;
 				case INTRODUCEE:
 					session = handleMessage(txn, m, body, meta, sessionParser
 							.parseIntroduceeSession(m.getGroupId(),
@@ -235,6 +244,40 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 		return false;
 	}
 
+	private boolean mailboxIncomingMessage(Transaction txn, Message m,
+			BdfList body, BdfDictionary bdfMeta)
+			throws DbException, FormatException {
+		MessageMetadata meta = messageParser.parseMetadata(bdfMeta);
+		// Look up the session, if there is one
+		SessionId sessionId = meta.getSessionId();
+		MailboxSession mailboxSession = null;
+		if (sessionId == null) {
+			if (meta.getMessageType() != MAILBOX_REQUEST)
+				throw new AssertionError();
+			mailboxSession = createMailboxSession(txn, m, body);
+			sessionId = mailboxSession.getSessionId();
+		}
+		StoredSession ss = getSession(txn, sessionId);
+		Session session;
+		// Handle the message
+		MessageId storageId;
+		if (ss == null) {
+			if (meta.getMessageType() != MAILBOX_REQUEST)
+				throw new FormatException();
+			session = handleMessage(txn, m, body, meta, mailboxSession,
+					mailboxProtocolEngine);
+			storageId = createStorageId(txn);
+		} else {
+			storageId = ss.storageId;
+			session = handleMessage(txn, m, body, meta, sessionParser
+							.parseMailboxSession(m.getGroupId(), ss.bdfSession),
+					mailboxProtocolEngine);
+		}
+		// Store the updated session
+		storeSession(txn, storageId, session);
+		return false;
+	}
+
 	private MailboxSession createMailboxSession(Transaction txn, Message m,
 			BdfList body) throws DbException, FormatException {
 		ContactId ownerId = getContactId(txn, m.getGroupId());
@@ -244,7 +287,7 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 		if (local.equals(remote)) throw new FormatException();
 		SessionId sessionId = crypto.getSessionId(owner, local, remote, true);
 		return MailboxSession
-				.getInitial(m.getGroupId(), sessionId, owner, true, remote);
+				.getInitial(m.getGroupId(), sessionId, owner, remote);
 	}
 
 	private IntroduceeSession createIntroduceeSession(Transaction txn,
@@ -257,7 +300,7 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 		if (local.equals(remote)) throw new FormatException();
 		SessionId sessionId = crypto.getSessionId(owner, local, remote, false);
 		return IntroduceeSession
-				.getInitial(m.getGroupId(), sessionId, owner, false, remote);
+				.getInitial(m.getGroupId(), sessionId, owner, remote);
 	}
 
 	private <S extends Session> S handleMessage(Transaction txn, Message m,
@@ -336,7 +379,7 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 				// use fixed deterministic roles for the introducees
 				session = new OwnerSession(sessionId, groupId1,
 						privateMailbox.getAuthor(), groupId2,
-						contact.getAuthor(), 0);
+						contact.getAuthor());
 				storageId = createStorageId(txn);
 			} else {
 				// An earlier request exists, so we already have a session
@@ -345,7 +388,7 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook
 			}
 			// Handle the request action
 			session = ownerProtocolEngine
-					.onStartStartIntroduction(txn, session, timestamp);
+					.onStartIntroduction(txn, session, timestamp);
 			// Store the updated session
 			storeSession(txn, storageId, session);
 			db.commitTransaction(txn);
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionValidator.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionValidator.java
index f6a2e2362..0cddc9d66 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionValidator.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionValidator.java
@@ -158,7 +158,7 @@ class MailboxIntroductionValidator extends BdfMessageValidator {
 
 	private BdfMessageContext validateAuthMessage(Message m, BdfList body)
 			throws FormatException {
-		checkSize(body, 7);
+		checkSize(body, 8);
 
 		byte[] sessionIdBytes = body.getRaw(1);
 		checkLength(sessionIdBytes, UniqueId.LENGTH);
@@ -166,18 +166,21 @@ class MailboxIntroductionValidator extends BdfMessageValidator {
 		byte[] previousMessageId = body.getRaw(2);
 		checkLength(previousMessageId, UniqueId.LENGTH);
 
-		BdfDictionary transportProperties = body.getDictionary(3);
+		int contactId = body.getLong(3).intValue();
+		if (contactId <= 0) throw new FormatException();
+
+		BdfDictionary transportProperties = body.getDictionary(4);
 		if (transportProperties.size() < 1) throw new FormatException();
 		clientHelper
 				.parseAndValidateTransportPropertiesMap(transportProperties);
 
-		byte[] mac = body.getRaw(4);
+		byte[] mac = body.getRaw(5);
 		checkLength(mac, MAC_BYTES);
 
-		byte[] signature = body.getRaw(5);
+		byte[] signature = body.getRaw(6);
 		checkLength(signature, 1, MAX_SIGNATURE_BYTES);
 
-		long messageCounter = body.getLong(6);
+		long messageCounter = body.getLong(7);
 
 		SessionId sessionId = new SessionId(sessionIdBytes);
 		BdfDictionary meta = messageEncoder
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageEncoder.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageEncoder.java
index f1ead80fa..3ad10818f 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageEncoder.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageEncoder.java
@@ -1,6 +1,7 @@
 package org.briarproject.bramble.mailbox.introduction;
 
 import org.briarproject.bramble.api.client.SessionId;
+import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.identity.Author;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -43,6 +44,7 @@ public interface MailboxMessageEncoder {
 
 	Message encodeMailboxAuthMessage(GroupId contactGroupId, long timestamp,
 			@Nullable MessageId previousMessageId, SessionId sessionId,
+			ContactId contactId,
 			Map<TransportId, TransportProperties> transportProperties,
 			byte[] mac, byte[] signature, long messageCounter);
 
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageEncoderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageEncoderImpl.java
index 8e438ada9..a7ea53da4 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageEncoderImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageEncoderImpl.java
@@ -3,6 +3,7 @@ package org.briarproject.bramble.mailbox.introduction;
 import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.ClientHelper;
 import org.briarproject.bramble.api.client.SessionId;
+import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.data.BdfList;
 import org.briarproject.bramble.api.identity.Author;
@@ -113,11 +114,11 @@ class MailboxMessageEncoderImpl implements MailboxMessageEncoder {
 	@Override
 	public Message encodeMailboxAuthMessage(GroupId contactGroupId,
 			long timestamp, @Nullable MessageId previousMessageId,
-			SessionId sessionId,
+			SessionId sessionId, ContactId contactId,
 			Map<TransportId, TransportProperties> transportProperties,
 			byte[] mac, byte[] signature, long messageCounter) {
 		BdfList body = BdfList.of(MAILBOX_AUTH.getValue(), sessionId,
-				previousMessageId,
+				previousMessageId, contactId.getInt(),
 				clientHelper.toDictionary(transportProperties), mac, signature,
 				messageCounter);
 		return createMessage(contactGroupId, timestamp, body);
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageParser.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageParser.java
index 8ca36bda9..afe6a0d02 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageParser.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageParser.java
@@ -1,7 +1,6 @@
 package org.briarproject.bramble.mailbox.introduction;
 
 import org.briarproject.bramble.api.FormatException;
-import org.briarproject.bramble.api.client.SessionId;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.data.BdfList;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageParserImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageParserImpl.java
index 778e76e82..5585701ae 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageParserImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxMessageParserImpl.java
@@ -3,6 +3,7 @@ package org.briarproject.bramble.mailbox.introduction;
 import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.ClientHelper;
 import org.briarproject.bramble.api.client.SessionId;
+import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.data.BdfList;
 import org.briarproject.bramble.api.identity.Author;
@@ -111,13 +112,14 @@ class MailboxMessageParserImpl implements MailboxMessageParser {
 		SessionId sessionId = new SessionId(body.getRaw(1));
 		byte[] previousMsgBytes = body.getRaw(2);
 		MessageId previousMessageId = new MessageId(previousMsgBytes);
+		ContactId contactId = new ContactId(body.getLong(3).intValue());
 		Map<TransportId, TransportProperties> transportProperties = clientHelper
-				.parseAndValidateTransportPropertiesMap(body.getDictionary(3));
-		byte[] mac = body.getRaw(4);
-		byte[] signature = body.getRaw(5);
+				.parseAndValidateTransportPropertiesMap(body.getDictionary(4));
+		byte[] mac = body.getRaw(5);
+		byte[] signature = body.getRaw(6);
 		return new MailboxAuthMessage(m.getId(), m.getGroupId(),
 				m.getTimestamp(), previousMessageId, sessionId,
-				transportProperties, mac, signature);
+				contactId, transportProperties, mac, signature);
 	}
 
 	@Override
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxProtocolEngine.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxProtocolEngine.java
index 9f19e23ac..942d12fad 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxProtocolEngine.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxProtocolEngine.java
@@ -17,6 +17,7 @@ import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionAbortedEvent;
 import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionRequestReceivedEvent;
 import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionSucceededEvent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.plugin.TransportId;
 import org.briarproject.bramble.api.properties.TransportProperties;
 import org.briarproject.bramble.api.properties.TransportPropertyManager;
@@ -34,12 +35,12 @@ import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.bramble.mailbox.introduction.MailboxState.AWAIT_INTRODUCEE_RESPONSE;
 import static org.briarproject.bramble.mailbox.introduction.MailboxState.CONTACT_ADDED;
 import static org.briarproject.bramble.mailbox.introduction.MailboxState.INTRODUCEE_DECLINED;
 import static org.briarproject.bramble.mailbox.introduction.MailboxState.START;
 import static org.briarproject.bramble.util.LogUtils.logException;
 
+@NotNullByDefault
 class MailboxProtocolEngine extends AbstractProtocolEngine<MailboxSession> {
 
 	private final static Logger LOG =
@@ -60,7 +61,7 @@ class MailboxProtocolEngine extends AbstractProtocolEngine<MailboxSession> {
 
 	@Override
 	public MailboxSession onRequestMessage(Transaction txn, MailboxSession s,
-			RequestMessage m) throws DbException, FormatException {
+			RequestMessage m) throws DbException {
 		switch (s.getState()) {
 			case START:
 				return onRemoteRequest(txn, s, m);
@@ -76,8 +77,7 @@ class MailboxProtocolEngine extends AbstractProtocolEngine<MailboxSession> {
 
 	@Override
 	public MailboxSession onMailboxAcceptMessage(Transaction txn,
-			MailboxSession session, MailboxAcceptMessage m)
-			throws DbException, FormatException {
+			MailboxSession session, MailboxAcceptMessage m) {
 		throw new UnsupportedOperationException();
 	}
 
@@ -149,7 +149,7 @@ class MailboxProtocolEngine extends AbstractProtocolEngine<MailboxSession> {
 					transportPropertyManager.getLocalProperties(txn);
 			Message reply =
 					sendMailboxAuthMessage(txn, s, clock.currentTimeMillis(),
-							transportProperties, mac, signature);
+							c.getId(), transportProperties, mac, signature);
 			LOG.info("Contact from owner added");
 			//TODO: Check for reasons to decline and if any, move to LOCAL_DECLINE
 			return MailboxSession.clear(s, CONTACT_ADDED, reply.getId(),
@@ -181,7 +181,7 @@ class MailboxProtocolEngine extends AbstractProtocolEngine<MailboxSession> {
 	@Override
 	public MailboxSession onDeclineMessage(Transaction txn,
 			MailboxSession session, DeclineMessage m)
-			throws DbException, FormatException {
+			throws DbException {
 		switch (session.getState()) {
 			case AWAIT_INTRODUCEE_RESPONSE:
 				break;
@@ -200,13 +200,13 @@ class MailboxProtocolEngine extends AbstractProtocolEngine<MailboxSession> {
 
 	@Override
 	public MailboxSession onAuthMessage(Transaction txn, MailboxSession session,
-			MailboxAuthMessage m) throws DbException, FormatException {
+			MailboxAuthMessage m) {
 		throw new UnsupportedOperationException();
 	}
 
 	@Override
 	public MailboxSession onAbortMessage(Transaction txn, MailboxSession s,
-			AbortMessage m) throws DbException, FormatException {
+			AbortMessage m) {
 		// Broadcast abort event for testing
 		txn.attach(new MailboxIntroductionAbortedEvent(s.getSessionId()));
 		// Reset the session back to initial state
@@ -241,7 +241,7 @@ class MailboxProtocolEngine extends AbstractProtocolEngine<MailboxSession> {
 		//TODO: Check for reasons to decline and if any, move to LOCAL_DECLINE
 		// Move to the AWAIT_REMOTE_RESPONSE state
 		return MailboxSession
-				.addLocalAccept(s, AWAIT_INTRODUCEE_RESPONSE, reply, publicKey,
+				.addLocalAccept(s, reply, publicKey,
 						privateKey, localTimestamp);
 	}
 
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxSession.java
index e9b7fe6e8..5c6b67fb2 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxSession.java
@@ -34,22 +34,23 @@ class MailboxSession extends AbstractIntroduceeSession<MailboxState> {
 	}
 
 	static MailboxSession getInitial(GroupId contactGroupId,
-			SessionId sessionId, Author introducer, boolean localIsAlice,
+			SessionId sessionId, Author introducer,
 			Author remoteAuthor) {
-		Local local = new Local(localIsAlice, null, -1, null, null, -1, null);
+		Local local = new Local(true, null, -1, null, null, -1, null);
 		Remote remote =
-				new Remote(!localIsAlice, remoteAuthor, null, null, null, -1,
+				new Remote(false, remoteAuthor, null, null, null, -1,
 						null);
 		return new MailboxSession(sessionId, START, -1, contactGroupId,
 				introducer, local, remote, null, null, 0);
 	}
 
-	static MailboxSession addLocalAccept(MailboxSession s, MailboxState state,
+	static MailboxSession addLocalAccept(MailboxSession s,
 			Message m, byte[] ephemeralPublicKey, byte[] ephemeralPrivateKey,
 			long acceptTimestamp) {
 		Local local = new Local(s.local.alice, m.getId(), m.getTimestamp(),
 				ephemeralPublicKey, ephemeralPrivateKey, acceptTimestamp, null);
-		return new MailboxSession(s.getSessionId(), state, m.getTimestamp(),
+		return new MailboxSession(s.getSessionId(),
+				MailboxState.AWAIT_INTRODUCEE_RESPONSE, m.getTimestamp(),
 				s.contactGroupId, s.introducer, local, s.remote, s.masterKey,
 				s.transportKeys, s.getAbortCounter());
 	}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxSessionParserImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxSessionParserImpl.java
index a714fe929..ed1cb7390 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxSessionParserImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/MailboxSessionParserImpl.java
@@ -33,7 +33,6 @@ import static org.briarproject.bramble.mailbox.introduction.IntroductionConstant
 import static org.briarproject.bramble.mailbox.introduction.IntroductionConstants.SESSION_KEY_COUNTER;
 import static org.briarproject.bramble.mailbox.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PRIVATE_KEY;
 import static org.briarproject.bramble.mailbox.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PUBLIC_KEY;
-import static org.briarproject.bramble.mailbox.introduction.IntroductionConstants.SESSION_KEY_GROUP_ID;
 import static org.briarproject.bramble.mailbox.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_A;
 import static org.briarproject.bramble.mailbox.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_B;
 import static org.briarproject.bramble.mailbox.introduction.IntroductionConstants.SESSION_KEY_INTRODUCER;
@@ -101,7 +100,7 @@ class MailboxSessionParserImpl implements MailboxSessionParser {
 		MessageId lastRemoteMessageId =
 				getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID);
 		long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP);
-		GroupId groupId = getGroupId(d, SESSION_KEY_GROUP_ID);
+		GroupId groupId = getGroupId(d);
 		Author author = getAuthor(d, SESSION_KEY_AUTHOR);
 		long abortCounter = d.getLong(SESSION_KEY_COUNTER);
 		return new Introducee(sessionId, groupId, author, localTimestamp,
@@ -206,9 +205,9 @@ class MailboxSessionParserImpl implements MailboxSessionParser {
 		return b == null ? null : new MessageId(b);
 	}
 
-	private GroupId getGroupId(BdfDictionary d, String key)
+	private GroupId getGroupId(BdfDictionary d)
 			throws FormatException {
-		return new GroupId(d.getRaw(key));
+		return new GroupId(d.getRaw(IntroductionConstants.SESSION_KEY_GROUP_ID));
 	}
 
 	private Author getAuthor(BdfDictionary d, String key)
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/OwnerProtocolEngine.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/OwnerProtocolEngine.java
index 50be2b64b..92ea004e5 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/OwnerProtocolEngine.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/OwnerProtocolEngine.java
@@ -1,6 +1,5 @@
 package org.briarproject.bramble.mailbox.introduction;
 
-import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.ClientHelper;
 import org.briarproject.bramble.api.client.ContactGroupFactory;
 import org.briarproject.bramble.api.client.ProtocolStateException;
@@ -14,6 +13,7 @@ import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionAbortedEvent;
 import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionResponseReceivedEvent;
 import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionSucceededEvent;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.properties.TransportPropertyManager;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.Message;
@@ -30,6 +30,7 @@ import static org.briarproject.bramble.mailbox.introduction.OwnerState.AWAIT_RES
 import static org.briarproject.bramble.mailbox.introduction.OwnerState.AWAIT_RESPONSE_M;
 import static org.briarproject.bramble.mailbox.introduction.OwnerState.START;
 
+@NotNullByDefault
 class OwnerProtocolEngine extends AbstractProtocolEngine<OwnerSession> {
 
 	private static final Logger LOG =
@@ -48,7 +49,7 @@ class OwnerProtocolEngine extends AbstractProtocolEngine<OwnerSession> {
 				keyManager, transportPropertyManager);
 	}
 
-	OwnerSession onStartStartIntroduction(Transaction txn, OwnerSession s,
+	OwnerSession onStartIntroduction(Transaction txn, OwnerSession s,
 			long timestamp) throws DbException {
 		switch (s.getState()) {
 			case START:
@@ -67,14 +68,13 @@ class OwnerProtocolEngine extends AbstractProtocolEngine<OwnerSession> {
 
 	@Override
 	public OwnerSession onRequestMessage(Transaction txn, OwnerSession session,
-			RequestMessage m) throws DbException, FormatException {
-		//		return abort(txn, session);
+			RequestMessage m) {
 		throw new UnsupportedOperationException();
 	}
 
 	@Override
 	public OwnerSession onMailboxAcceptMessage(Transaction txn, OwnerSession s,
-			MailboxAcceptMessage m) throws DbException, FormatException {
+			MailboxAcceptMessage m) throws DbException {
 		switch (s.getState()) {
 			case START:
 			case AWAIT_RESPONSE_M:
@@ -110,24 +110,27 @@ class OwnerProtocolEngine extends AbstractProtocolEngine<OwnerSession> {
 
 	@Override
 	public OwnerSession onDeclineMessage(Transaction txn, OwnerSession session,
-			DeclineMessage m) throws DbException, FormatException {
+			DeclineMessage m) {
+		// TODO
 		return null;
 	}
 
 	@Override
 	public OwnerSession onAuthMessage(Transaction txn, OwnerSession s,
-			MailboxAuthMessage m) throws DbException, FormatException {
+			MailboxAuthMessage m) throws DbException {
 		// The dependency, if any, must be the last remote message
 		if (isInvalidDependency(s.getMailbox().getLastLocalMessageId(),
 				m.getPreviousMessageId())) return abort(txn, s);
 		Message forward = sendMailboxAuthMessage(txn, s.getIntroducee(),
-				clock.currentTimeMillis(), m.getTransportProperties(),
+				clock.currentTimeMillis(), m.getContactId(),
+				m.getTransportProperties(),
 				m.getMac(), m.getSignature());
 		Contact c = contactManager
 				.getContact(txn, s.getIntroducee().author.getId(),
 						identityManager.getLocalAuthor().getId());
-		db.setMailboxForContact(txn, c.getId(), null, c.getId());
+		db.setMailboxForContact(txn, c.getId(), null, m.getContactId());
 		txn.attach(new MailboxIntroductionSucceededEvent(c));
+		LOG.info("MI succ");
 		return new OwnerSession(s.getSessionId(), ADDED,
 				s.getRequestTimestamp(),
 				new Introducee(s.getMailbox(), m.getMessageId(),
@@ -182,6 +185,7 @@ class OwnerProtocolEngine extends AbstractProtocolEngine<OwnerSession> {
 
 	private OwnerSession onLocalRequest(Transaction txn, OwnerSession s,
 			long timestamp) throws DbException {
+		LOG.info("LOCAL REQUEST");
 		// Send REQUEST messages
 		long maxIntroduceeTimestamp =
 				Math.max(getLocalTimestamp(s, s.getMailbox()),
@@ -253,7 +257,7 @@ class OwnerProtocolEngine extends AbstractProtocolEngine<OwnerSession> {
 		else throw new AssertionError();
 	}
 
-	void broadcastMailboxIntroductionResponseReceived(Transaction txn,
+	private void broadcastMailboxIntroductionResponseReceived(Transaction txn,
 			Author from, Author to) {
 		MailboxIntroductionResponseReceivedEvent e =
 				new MailboxIntroductionResponseReceivedEvent(from, to);
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/OwnerSession.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/OwnerSession.java
index e88389215..f47dfe4e5 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/OwnerSession.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/OwnerSession.java
@@ -24,11 +24,11 @@ class OwnerSession extends Session<OwnerState> {
 	}
 
 	OwnerSession(SessionId sessionId, GroupId groupIdA, Author authorA,
-			GroupId groupIdB, Author authorB, long abortCounter) {
+			GroupId groupIdB, Author authorB) {
 		this(sessionId, OwnerState.START, -1,
-				new Introducee(sessionId, groupIdA, authorA, abortCounter),
-				new Introducee(sessionId, groupIdB, authorB, abortCounter),
-				abortCounter);
+				new Introducee(sessionId, groupIdA, authorA, (long) 0),
+				new Introducee(sessionId, groupIdB, authorB, (long) 0),
+				(long) 0);
 	}
 
 	public static OwnerSession finished(OwnerSession s) {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/ProtocolEngine.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/ProtocolEngine.java
index c0b18de6b..1929f2f4c 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/ProtocolEngine.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/introduction/ProtocolEngine.java
@@ -9,7 +9,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 interface ProtocolEngine<S extends Session> {
 
 	S onRequestMessage(Transaction txn, S session, RequestMessage m)
-			throws DbException, FormatException;
+			throws DbException;
 
 	S onMailboxAcceptMessage(Transaction txn, S session, MailboxAcceptMessage m)
 			throws DbException, FormatException;
@@ -18,13 +18,13 @@ interface ProtocolEngine<S extends Session> {
 			IntroduceeAcceptMessage acceptMessage) throws DbException;
 
 	S onDeclineMessage(Transaction txn, S session, DeclineMessage m)
-			throws DbException, FormatException;
+			throws DbException;
 
 	S onAuthMessage(Transaction txn, S session, MailboxAuthMessage m)
-			throws DbException, FormatException;
+			throws DbException;
 
 	S onAbortMessage(Transaction txn, S session, AbortMessage m)
-			throws DbException, FormatException;
+			throws DbException;
 
 
 }
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/integration/BrambleIntegrationTestComponent.java b/bramble-core/src/test/java/org/briarproject/bramble/integration/BrambleIntegrationTestComponent.java
index 2a0e20334..f1b33e55a 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/integration/BrambleIntegrationTestComponent.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/integration/BrambleIntegrationTestComponent.java
@@ -7,6 +7,7 @@ import org.briarproject.bramble.api.event.EventBus;
 import org.briarproject.bramble.api.identity.AuthorFactory;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.mailbox.MailboxIntroductionManager;
 import org.briarproject.bramble.api.properties.TransportPropertyManager;
 import org.briarproject.bramble.api.sync.SyncSessionFactory;
 import org.briarproject.bramble.client.ClientModule;
@@ -18,12 +19,12 @@ import org.briarproject.bramble.db.DatabaseModule;
 import org.briarproject.bramble.event.EventModule;
 import org.briarproject.bramble.identity.IdentityModule;
 import org.briarproject.bramble.lifecycle.LifecycleModule;
-import org.briarproject.bramble.api.mailbox.MailboxIntroductionManager;
 import org.briarproject.bramble.mailbox.introduction.MailboxIntroductionModule;
 import org.briarproject.bramble.properties.PropertiesModule;
 import org.briarproject.bramble.record.RecordModule;
 import org.briarproject.bramble.sync.SyncModule;
 import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.test.TestBrambleConfigModule;
 import org.briarproject.bramble.test.TestDatabaseModule;
 import org.briarproject.bramble.test.TestPluginConfigModule;
 import org.briarproject.bramble.test.TestSecureRandomModule;
@@ -37,6 +38,7 @@ import dagger.Component;
 @Singleton
 @Component(modules = {
 		TestDatabaseModule.class,
+		TestBrambleConfigModule.class,
 		TestPluginConfigModule.class,
 		TestSecureRandomModule.class,
 		ClientModule.class,
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionIntegrationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionIntegrationTest.java
index d69b67fc5..ec1323bef 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionIntegrationTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionIntegrationTest.java
@@ -2,25 +2,26 @@ package org.briarproject.bramble.mailbox.introduction;
 
 import net.jodah.concurrentunit.Waiter;
 
+import org.briarproject.bramble.api.client.SessionId;
 import org.briarproject.bramble.api.contact.Contact;
 import org.briarproject.bramble.api.contact.PrivateMailbox;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.event.Event;
 import org.briarproject.bramble.api.event.EventListener;
 import org.briarproject.bramble.api.identity.AuthorId;
+import org.briarproject.bramble.api.mailbox.MailboxIntroductionManager;
+import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionAbortedEvent;
+import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionRequestReceivedEvent;
+import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionResponseReceivedEvent;
+import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionSucceededEvent;
 import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
 import org.briarproject.bramble.api.properties.TransportPropertyManager;
 import org.briarproject.bramble.api.sync.Group;
-import org.briarproject.bramble.api.client.SessionId;
 import org.briarproject.bramble.integration.BrambleIntegrationTest;
 import org.briarproject.bramble.integration.BrambleIntegrationTestComponent;
-import org.briarproject.bramble.api.mailbox.MailboxIntroductionManager;
-import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionAbortedEvent;
-import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionRequestReceivedEvent;
-import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionResponseReceivedEvent;
-import org.briarproject.bramble.api.mailbox.event.MailboxIntroductionSucceededEvent;
+import org.briarproject.bramble.test.TestBrambleConfigModule;
 import org.briarproject.bramble.test.TestDatabaseModule;
 import org.junit.Before;
 import org.junit.Test;
@@ -74,24 +75,28 @@ public class MailboxIntroductionIntegrationTest extends
 	@Override
 	protected void createComponents() {
 		MailboxIntroductionIntegrationTestComponent component =
-				DaggerMailboxIntroductionIntegrationTestComponent.builder()
+				DaggerMailboxIntroductionIntegrationTestComponent.builder().testBrambleConfigModule(new TestBrambleConfigModule(false))
 						.build();
 		component.inject(this);
 
 		c0 = DaggerMailboxIntroductionIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
+				.testDatabaseModule(new TestDatabaseModule(t0Dir))
+				.testBrambleConfigModule(new TestBrambleConfigModule(false)).build();
 		injectEagerSingletons(c0);
 
 		c1 = DaggerMailboxIntroductionIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
+				.testDatabaseModule(new TestDatabaseModule(t1Dir))
+				.testBrambleConfigModule(new TestBrambleConfigModule(false)).build();
 		injectEagerSingletons(c1);
 
 		c2 = DaggerMailboxIntroductionIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
+				.testDatabaseModule(new TestDatabaseModule(t2Dir))
+				.testBrambleConfigModule(new TestBrambleConfigModule(false)).build();
 		injectEagerSingletons(c2);
 
 		cMailbox = DaggerMailboxIntroductionIntegrationTestComponent.builder()
-				.testDatabaseModule(new TestDatabaseModule(t3Dir)).build();
+				.testDatabaseModule(new TestDatabaseModule(t3Dir))
+				.testBrambleConfigModule(new TestBrambleConfigModule(true)).build();
 		injectEagerSingletons(cMailbox);
 	}
 
@@ -105,13 +110,19 @@ public class MailboxIntroductionIntegrationTest extends
 	@Test
 	public void testIntroductionSession() throws Exception {
 		addListeners(true, true, true);
-
-		// make introduction
-		long time = clock.currentTimeMillis();
-		Contact introducee = contact1From0;
-		PrivateMailbox mailbox = privateMailboxFrom0;
-		introductionManager0.makeIntroduction(mailbox, introducee, time);
-
+		sync0To1(1, true);
+		sync1To0(1, true);
+		sync0ToMailbox(1, true);
+		syncMailboxTo0(1, true);
+		sync0To1(1, true);
+/*
+		sync0ToMailbox(1, true);
+		sync0ToMailbox(1, true);
+		syncMailboxTo0(1, true);
+		sync0To1(1, true);
+		sync1To0(1,true);
+		*/
+/*
 		// sync first REQUEST message
 		sync0ToMailbox(1, true);
 		eventWaiter.await(TIMEOUT, 1);
@@ -140,6 +151,7 @@ public class MailboxIntroductionIntegrationTest extends
 		assertTrue(listener1.succeeded);
 		assertEquals(privateMailboxFrom0.getAuthor(),
 				listener1.introduceeContact.getAuthor());
+				*/
 	}
 
 
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionIntegrationTestComponent.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionIntegrationTestComponent.java
index 706b951ea..2f4d80b40 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionIntegrationTestComponent.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/introduction/MailboxIntroductionIntegrationTestComponent.java
@@ -14,6 +14,7 @@ import org.briarproject.bramble.properties.PropertiesModule;
 import org.briarproject.bramble.record.RecordModule;
 import org.briarproject.bramble.sync.SyncModule;
 import org.briarproject.bramble.system.SystemModule;
+import org.briarproject.bramble.test.TestBrambleConfigModule;
 import org.briarproject.bramble.test.TestDatabaseModule;
 import org.briarproject.bramble.test.TestPluginConfigModule;
 import org.briarproject.bramble.test.TestSecureRandomModule;
@@ -27,6 +28,7 @@ import dagger.Component;
 @Singleton
 @Component(modules = {
 		TestDatabaseModule.class,
+		TestBrambleConfigModule.class,
 		TestPluginConfigModule.class,
 		TestSecureRandomModule.class,
 		ClientModule.class,
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java
index ce2e6f9b2..d63b80a4c 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationActivity.java
@@ -20,6 +20,8 @@ import android.widget.TextView;
 import android.widget.Toast;
 
 import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ProtocolStateException;
+import org.briarproject.bramble.api.client.SessionId;
 import org.briarproject.bramble.api.contact.Contact;
 import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.contact.ContactManager;
@@ -58,8 +60,6 @@ import org.briarproject.briar.android.view.TextInputView;
 import org.briarproject.briar.android.view.TextInputView.TextInputListener;
 import org.briarproject.briar.api.android.AndroidNotificationManager;
 import org.briarproject.briar.api.blog.BlogSharingManager;
-import org.briarproject.briar.api.client.ProtocolStateException;
-import org.briarproject.briar.api.client.SessionId;
 import org.briarproject.briar.api.forum.ForumSharingManager;
 import org.briarproject.briar.api.introduction.IntroductionManager;
 import org.briarproject.briar.api.introduction.IntroductionMessage;
@@ -678,7 +678,8 @@ public class ConversationActivity extends BriarActivity
 				//noinspection ConstantConditions init in loadGroupId()
 				storeMessage(privateMessageFactory.createPrivateMessage(
 						messagingGroupId, timestamp, body), body);
-			} catch (FormatException e) {throw new RuntimeException(e);
+			} catch (FormatException e) {
+				throw new RuntimeException(e);
 			}
 		});
 	}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestItem.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestItem.java
index b11a00c60..b49b86d90 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestItem.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ConversationRequestItem.java
@@ -2,11 +2,11 @@ package org.briarproject.briar.android.contact;
 
 import android.support.annotation.LayoutRes;
 
+import org.briarproject.bramble.api.client.SessionId;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.briar.R;
-import org.briarproject.briar.api.client.SessionId;
 
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java
index 3b257c2f0..34635b3af 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/reveal/RevealContactsControllerImpl.java
@@ -1,5 +1,6 @@
 package org.briarproject.briar.android.privategroup.reveal;
 
+import org.briarproject.bramble.api.client.ProtocolStateException;
 import org.briarproject.bramble.api.contact.Contact;
 import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.contact.ContactManager;
@@ -13,7 +14,6 @@ import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.briar.android.controller.DbControllerImpl;
 import org.briarproject.briar.android.controller.handler.ExceptionHandler;
 import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
-import org.briarproject.briar.api.client.ProtocolStateException;
 import org.briarproject.briar.api.privategroup.GroupMember;
 import org.briarproject.briar.api.privategroup.PrivateGroupManager;
 import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
-- 
GitLab