Merge branch '2261-include-mailbox-api-version-in-mailbox-properties' into 'master'

Include mailbox API version in local and remote mailbox properties

Closes #2261

See merge request briar/briar!1621
This commit is contained in:
akwizgran
2022-05-16 09:58:30 +00:00
23 changed files with 673 additions and 423 deletions

View File

@@ -9,7 +9,7 @@ import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate; import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
@@ -21,8 +21,6 @@ import java.security.GeneralSecurityException;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface ClientHelper { public interface ClientHelper {
@@ -127,16 +125,14 @@ public interface ClientHelper {
BdfDictionary properties) throws FormatException; BdfDictionary properties) throws FormatException;
/** /**
* Parse and validate the property dictionary of a Mailbox property update * Parse and validate the elements of a Mailbox update message.
* message.
* *
* @return the properties for using the Mailbox, or null if there is no * @return the parsed update message
* Mailbox available * @throws FormatException if the message elements are invalid
* @throws FormatException if the properties are not valid
*/ */
@Nullable MailboxUpdate parseAndValidateMailboxUpdate(BdfList clientSupports,
MailboxPropertiesUpdate parseAndValidateMailboxPropertiesUpdate( BdfList serverSupports, BdfDictionary properties)
BdfDictionary properties) throws FormatException; throws FormatException;
/** /**
* Retrieves the contact ID from the group metadata of the given contact * Retrieves the contact ID from the group metadata of the given contact

View File

@@ -7,6 +7,8 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
@@ -49,7 +51,8 @@ public interface MailboxSettingsManager {
* @param txn A read-write transaction * @param txn A read-write transaction
* @param ownOnion Our new mailbox's onion (56 base32 chars) * @param ownOnion Our new mailbox's onion (56 base32 chars)
*/ */
void mailboxPaired(Transaction txn, String ownOnion) void mailboxPaired(Transaction txn, String ownOnion,
List<MailboxVersion> serverSupports)
throws DbException; throws DbException;
/** /**

View File

@@ -0,0 +1,28 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.List;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class MailboxUpdate {
boolean hasMailbox;
private final List<MailboxVersion> clientSupports;
public MailboxUpdate(List<MailboxVersion> clientSupports) {
this.hasMailbox = false;
this.clientSupports = clientSupports;
}
public List<MailboxVersion> getClientSupports() {
return clientSupports;
}
public boolean hasMailbox() {
return hasMailbox;
}
}

View File

@@ -9,31 +9,31 @@ import org.briarproject.bramble.api.sync.ClientId;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface MailboxPropertyManager { public interface MailboxUpdateManager {
/** /**
* The unique ID of the mailbox property client. * The unique ID of the mailbox update (properties) client.
*/ */
ClientId CLIENT_ID = ClientId CLIENT_ID =
new ClientId("org.briarproject.bramble.mailbox.properties"); new ClientId("org.briarproject.bramble.mailbox.properties");
/** /**
* The current major version of the mailbox property client. * The current major version of the mailbox update (properties) client.
*/ */
int MAJOR_VERSION = 0; int MAJOR_VERSION = 1;
/** /**
* The current minor version of the mailbox property client. * The current minor version of the mailbox update (properties) client.
*/ */
int MINOR_VERSION = 0; int MINOR_VERSION = 0;
/** /**
* The number of properties required for a (non-empty) update message. * The number of properties required for an update message with a mailbox.
*/ */
int PROP_COUNT = 4; int PROP_COUNT = 4;
/** /**
* The required properties of a non-empty update message. * The required properties of an update message with a mailbox.
*/ */
String PROP_KEY_ONION = "onion"; String PROP_KEY_ONION = "onion";
String PROP_KEY_AUTHTOKEN = "authToken"; String PROP_KEY_AUTHTOKEN = "authToken";
@@ -57,11 +57,10 @@ public interface MailboxPropertyManager {
*/ */
String MSG_KEY_LOCAL = "local"; String MSG_KEY_LOCAL = "local";
@Nullable MailboxUpdate getLocalUpdate(Transaction txn, ContactId c)
MailboxPropertiesUpdate getLocalProperties(Transaction txn, ContactId c)
throws DbException; throws DbException;
@Nullable @Nullable
MailboxPropertiesUpdate getRemoteProperties(Transaction txn, ContactId c) MailboxUpdate getRemoteUpdate(Transaction txn, ContactId c)
throws DbException; throws DbException;
} }

View File

@@ -2,20 +2,27 @@ package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.List;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class MailboxPropertiesUpdate { public class MailboxUpdateWithMailbox extends MailboxUpdate {
private final List<MailboxVersion> serverSupports;
private final String onion; private final String onion;
private final MailboxAuthToken authToken; private final MailboxAuthToken authToken;
private final MailboxFolderId inboxId; private final MailboxFolderId inboxId;
private final MailboxFolderId outboxId; private final MailboxFolderId outboxId;
public MailboxPropertiesUpdate(String onion, public MailboxUpdateWithMailbox(List<MailboxVersion> clientSupports,
List<MailboxVersion> serverSupports, String onion,
MailboxAuthToken authToken, MailboxFolderId inboxId, MailboxAuthToken authToken, MailboxFolderId inboxId,
MailboxFolderId outboxId) { MailboxFolderId outboxId
) {
super(clientSupports);
this.hasMailbox = true;
this.serverSupports = serverSupports;
this.onion = onion; this.onion = onion;
this.authToken = authToken; this.authToken = authToken;
this.inboxId = inboxId; this.inboxId = inboxId;
@@ -38,4 +45,7 @@ public class MailboxPropertiesUpdate {
return outboxId; return outboxId;
} }
public List<MailboxVersion> getServerSupports() {
return serverSupports;
}
} }

View File

@@ -1,36 +0,0 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when {@link MailboxPropertiesUpdate} are received
* from a contact.
*/
@Immutable
@NotNullByDefault
public class RemoteMailboxPropertiesUpdateEvent extends Event {
private final ContactId contactId;
@Nullable
private final MailboxPropertiesUpdate mailboxPropertiesUpdate;
public RemoteMailboxPropertiesUpdateEvent(ContactId contactId,
@Nullable MailboxPropertiesUpdate mailboxPropertiesUpdate) {
this.contactId = contactId;
this.mailboxPropertiesUpdate = mailboxPropertiesUpdate;
}
public ContactId getContact() {
return contactId;
}
@Nullable
public MailboxPropertiesUpdate getMailboxPropertiesUpdate() {
return mailboxPropertiesUpdate;
}
}

View File

@@ -0,0 +1,33 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when {@link MailboxUpdate} are received
* from a contact.
*/
@Immutable
@NotNullByDefault
public class RemoteMailboxUpdateEvent extends Event {
private final ContactId contactId;
private final MailboxUpdate mailboxUpdate;
public RemoteMailboxUpdateEvent(ContactId contactId,
MailboxUpdate mailboxUpdate) {
this.contactId = contactId;
this.mailboxUpdate = mailboxUpdate;
}
public ContactId getContact() {
return contactId;
}
public MailboxUpdate getMailboxUpdate() {
return mailboxUpdate;
}
}

View File

@@ -21,7 +21,8 @@ import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Identity; import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.mailbox.MailboxProperties; import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate; import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.sync.ClientId; import org.briarproject.bramble.api.sync.ClientId;
@@ -280,20 +281,27 @@ public class TestUtils {
asList(optionalTests.split(",")).contains(testClass.getName()); asList(optionalTests.split(",")).contains(testClass.getName());
} }
public static boolean mailboxPropertiesUpdateEqual( public static boolean mailboxUpdateEqual(@Nullable MailboxUpdate a,
@Nullable MailboxPropertiesUpdate a, @Nullable MailboxUpdate b) {
@Nullable MailboxPropertiesUpdate b) {
if (a == null || b == null) { if (a == null || b == null) {
return a == b; return a == b;
} }
return a.getOnion().equals(b.getOnion()) && if (!a.hasMailbox() && !b.hasMailbox()) {
a.getAuthToken().equals(b.getAuthToken()) && return a.getClientSupports().equals(b.getClientSupports());
a.getInboxId().equals(b.getInboxId()) && } else if (a.hasMailbox() && b.hasMailbox()) {
a.getOutboxId().equals(b.getOutboxId()); MailboxUpdateWithMailbox am = (MailboxUpdateWithMailbox) a;
MailboxUpdateWithMailbox bm = (MailboxUpdateWithMailbox) b;
return am.getClientSupports().equals(bm.getClientSupports()) &&
am.getServerSupports().equals(bm.getServerSupports()) &&
am.getOnion().equals(bm.getOnion()) &&
am.getAuthToken().equals(bm.getAuthToken()) &&
am.getInboxId().equals(bm.getInboxId()) &&
am.getOutboxId().equals(bm.getOutboxId());
}
return false;
} }
public static boolean mailboxPropertiesEqual( public static boolean mailboxPropertiesEqual(@Nullable MailboxProperties a,
@Nullable MailboxProperties a,
@Nullable MailboxProperties b) { @Nullable MailboxProperties b) {
if (a == null || b == null) { if (a == null || b == null) {
return a == b; return a == b;

View File

@@ -25,7 +25,9 @@ import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken; import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxFolderId; import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate; import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
@@ -39,12 +41,13 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
@@ -52,12 +55,12 @@ import static org.briarproject.bramble.api.client.ContactGroupConstants.GROUP_KE
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION; import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_COUNT; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_COUNT;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_AUTHTOKEN; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_AUTHTOKEN;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_INBOXID; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_INBOXID;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_ONION; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_ONION;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_OUTBOXID; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_OUTBOXID;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_ONION_LENGTH; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_ONION_LENGTH;
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT; import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH; import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
@@ -412,11 +415,28 @@ class ClientHelperImpl implements ClientHelper {
} }
@Override @Override
@Nullable public MailboxUpdate parseAndValidateMailboxUpdate(BdfList clientSupports,
public MailboxPropertiesUpdate parseAndValidateMailboxPropertiesUpdate( BdfList serverSupports, BdfDictionary properties)
BdfDictionary properties) throws FormatException { throws FormatException {
List<MailboxVersion> clientSupportsList =
getMailboxVersionList(clientSupports);
List<MailboxVersion> serverSupportsList =
getMailboxVersionList(serverSupports);
// We must always learn what Mailbox API version(s) the client supports
if (clientSupports.isEmpty()) {
throw new FormatException();
}
if (properties.isEmpty()) { if (properties.isEmpty()) {
return null; // No mailbox -- cannot claim to support any API versions!
if (!serverSupports.isEmpty()) {
throw new FormatException();
}
return new MailboxUpdate(clientSupportsList);
}
// Mailbox must be accompanied by the Mailbox API version(s) it supports
if (serverSupports.isEmpty()) {
throw new FormatException();
} }
// Accepting more props than we need, for forward compatibility // Accepting more props than we need, for forward compatibility
if (properties.size() < PROP_COUNT) { if (properties.size() < PROP_COUNT) {
@@ -435,9 +455,23 @@ class ClientHelperImpl implements ClientHelper {
checkLength(inboxId, UniqueId.LENGTH); checkLength(inboxId, UniqueId.LENGTH);
byte[] outboxId = properties.getRaw(PROP_KEY_OUTBOXID); byte[] outboxId = properties.getRaw(PROP_KEY_OUTBOXID);
checkLength(outboxId, UniqueId.LENGTH); checkLength(outboxId, UniqueId.LENGTH);
return new MailboxPropertiesUpdate(onion, return new MailboxUpdateWithMailbox(clientSupportsList,
new MailboxAuthToken(authToken), new MailboxFolderId(inboxId), serverSupportsList, onion, new MailboxAuthToken(authToken),
new MailboxFolderId(outboxId)); new MailboxFolderId(inboxId), new MailboxFolderId(outboxId));
}
private List<MailboxVersion> getMailboxVersionList(BdfList bdfList)
throws FormatException {
List<MailboxVersion> list = new ArrayList<>();
for (int i = 0; i < bdfList.size(); i++) {
BdfList element = bdfList.getList(i);
if (element.size() != 2) {
throw new FormatException();
}
list.add(new MailboxVersion(element.getLong(0).intValue(),
element.getLong(1).intValue()));
}
return list;
} }
@Override @Override

View File

@@ -7,6 +7,8 @@ import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxFileId; import org.briarproject.bramble.api.mailbox.MailboxFileId;
import org.briarproject.bramble.api.mailbox.MailboxFolderId; import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxProperties; import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.File; import java.io.File;
@@ -17,9 +19,18 @@ import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static java.util.Collections.singletonList;
@NotNullByDefault @NotNullByDefault
interface MailboxApi { interface MailboxApi {
/**
* Mailbox API versions that we support as a client. This is reported to our
* contacts by {@link MailboxUpdateManager}.
*/
List<MailboxVersion> CLIENT_SUPPORTS = singletonList(
new MailboxVersion(1, 0));
/** /**
* Sets up the mailbox with the setup token. * Sets up the mailbox with the setup token.
* *

View File

@@ -5,8 +5,8 @@ import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.mailbox.MailboxManager; import org.briarproject.bramble.api.mailbox.MailboxManager;
import org.briarproject.bramble.api.mailbox.MailboxPropertyManager;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager; import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.sync.validation.ValidationManager; import org.briarproject.bramble.api.sync.validation.ValidationManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.versioning.ClientVersioningManager; import org.briarproject.bramble.api.versioning.ClientVersioningManager;
@@ -17,18 +17,18 @@ import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.CLIENT_ID; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.CLIENT_ID;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MAJOR_VERSION; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MAJOR_VERSION;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MINOR_VERSION; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MINOR_VERSION;
@Module @Module
public class MailboxModule { public class MailboxModule {
public static class EagerSingletons { public static class EagerSingletons {
@Inject @Inject
MailboxPropertyValidator mailboxPropertyValidator; MailboxUpdateValidator mailboxUpdateValidator;
@Inject @Inject
MailboxPropertyManager mailboxPropertyManager; MailboxUpdateManager mailboxUpdateManager;
} }
@Provides @Provides
@@ -56,10 +56,10 @@ public class MailboxModule {
@Provides @Provides
@Singleton @Singleton
MailboxPropertyValidator provideMailboxPropertyValidator( MailboxUpdateValidator provideMailboxUpdateValidator(
ValidationManager validationManager, ClientHelper clientHelper, ValidationManager validationManager, ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) { MetadataEncoder metadataEncoder, Clock clock) {
MailboxPropertyValidator validator = new MailboxPropertyValidator( MailboxUpdateValidator validator = new MailboxUpdateValidator(
clientHelper, metadataEncoder, clock); clientHelper, metadataEncoder, clock);
validationManager.registerMessageValidator(CLIENT_ID, MAJOR_VERSION, validationManager.registerMessageValidator(CLIENT_ID, MAJOR_VERSION,
validator); validator);
@@ -68,19 +68,19 @@ public class MailboxModule {
@Provides @Provides
@Singleton @Singleton
MailboxPropertyManager provideMailboxPropertyManager( MailboxUpdateManager provideMailboxUpdateManager(
LifecycleManager lifecycleManager, LifecycleManager lifecycleManager,
ValidationManager validationManager, ContactManager contactManager, ValidationManager validationManager, ContactManager contactManager,
ClientVersioningManager clientVersioningManager, ClientVersioningManager clientVersioningManager,
MailboxSettingsManager mailboxSettingsManager, MailboxSettingsManager mailboxSettingsManager,
MailboxPropertyManagerImpl mailboxPropertyManager) { MailboxUpdateManagerImpl mailboxUpdateManager) {
lifecycleManager.registerOpenDatabaseHook(mailboxPropertyManager); lifecycleManager.registerOpenDatabaseHook(mailboxUpdateManager);
validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION, validationManager.registerIncomingMessageHook(CLIENT_ID, MAJOR_VERSION,
mailboxPropertyManager); mailboxUpdateManager);
contactManager.registerContactHook(mailboxPropertyManager); contactManager.registerContactHook(mailboxUpdateManager);
clientVersioningManager.registerClient(CLIENT_ID, MAJOR_VERSION, clientVersioningManager.registerClient(CLIENT_ID, MAJOR_VERSION,
MINOR_VERSION, mailboxPropertyManager); MINOR_VERSION, mailboxUpdateManager);
mailboxSettingsManager.registerMailboxHook(mailboxPropertyManager); mailboxSettingsManager.registerMailboxHook(mailboxUpdateManager);
return mailboxPropertyManager; return mailboxUpdateManager;
} }
} }

View File

@@ -4,8 +4,8 @@ import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.event.EventExecutor; import org.briarproject.bramble.api.event.EventExecutor;
import org.briarproject.bramble.api.mailbox.MailboxPairingTask; import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
import org.briarproject.bramble.api.mailbox.MailboxPropertyManager;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager; import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
@@ -24,7 +24,7 @@ class MailboxPairingTaskFactoryImpl implements MailboxPairingTaskFactory {
private final Clock clock; private final Clock clock;
private final MailboxApi api; private final MailboxApi api;
private final MailboxSettingsManager mailboxSettingsManager; private final MailboxSettingsManager mailboxSettingsManager;
private final MailboxPropertyManager mailboxPropertyManager; private final MailboxUpdateManager mailboxUpdateManager;
@Inject @Inject
MailboxPairingTaskFactoryImpl( MailboxPairingTaskFactoryImpl(
@@ -34,20 +34,20 @@ class MailboxPairingTaskFactoryImpl implements MailboxPairingTaskFactory {
Clock clock, Clock clock,
MailboxApi api, MailboxApi api,
MailboxSettingsManager mailboxSettingsManager, MailboxSettingsManager mailboxSettingsManager,
MailboxPropertyManager mailboxPropertyManager) { MailboxUpdateManager mailboxUpdateManager) {
this.eventExecutor = eventExecutor; this.eventExecutor = eventExecutor;
this.db = db; this.db = db;
this.crypto = crypto; this.crypto = crypto;
this.clock = clock; this.clock = clock;
this.api = api; this.api = api;
this.mailboxSettingsManager = mailboxSettingsManager; this.mailboxSettingsManager = mailboxSettingsManager;
this.mailboxPropertyManager = mailboxPropertyManager; this.mailboxUpdateManager = mailboxUpdateManager;
} }
@Override @Override
public MailboxPairingTask createPairingTask(String qrCodePayload) { public MailboxPairingTask createPairingTask(String qrCodePayload) {
return new MailboxPairingTaskImpl(qrCodePayload, eventExecutor, db, return new MailboxPairingTaskImpl(qrCodePayload, eventExecutor, db,
crypto, clock, api, mailboxSettingsManager, crypto, clock, api, mailboxSettingsManager,
mailboxPropertyManager); mailboxUpdateManager);
} }
} }

View File

@@ -11,9 +11,9 @@ import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxPairingState; import org.briarproject.bramble.api.mailbox.MailboxPairingState;
import org.briarproject.bramble.api.mailbox.MailboxPairingTask; import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
import org.briarproject.bramble.api.mailbox.MailboxProperties; import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate;
import org.briarproject.bramble.api.mailbox.MailboxPropertyManager;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager; import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.mailbox.MailboxApi.ApiException; import org.briarproject.bramble.mailbox.MailboxApi.ApiException;
@@ -51,7 +51,7 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
private final Clock clock; private final Clock clock;
private final MailboxApi api; private final MailboxApi api;
private final MailboxSettingsManager mailboxSettingsManager; private final MailboxSettingsManager mailboxSettingsManager;
private final MailboxPropertyManager mailboxPropertyManager; private final MailboxUpdateManager mailboxUpdateManager;
private final Object lock = new Object(); private final Object lock = new Object();
@GuardedBy("lock") @GuardedBy("lock")
@@ -68,7 +68,7 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
Clock clock, Clock clock,
MailboxApi api, MailboxApi api,
MailboxSettingsManager mailboxSettingsManager, MailboxSettingsManager mailboxSettingsManager,
MailboxPropertyManager mailboxPropertyManager) { MailboxUpdateManager mailboxUpdateManager) {
this.payload = payload; this.payload = payload;
this.eventExecutor = eventExecutor; this.eventExecutor = eventExecutor;
this.db = db; this.db = db;
@@ -76,7 +76,7 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
this.clock = clock; this.clock = clock;
this.api = api; this.api = api;
this.mailboxSettingsManager = mailboxSettingsManager; this.mailboxSettingsManager = mailboxSettingsManager;
this.mailboxPropertyManager = mailboxPropertyManager; this.mailboxUpdateManager = mailboxUpdateManager;
state = new MailboxPairingState.QrCodeReceived(); state = new MailboxPairingState.QrCodeReceived();
} }
@@ -125,9 +125,9 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
// timers for contacts who doesn't have their own mailbox. This way, // timers for contacts who doesn't have their own mailbox. This way,
// data stranded on our old mailbox will be re-uploaded to our new. // data stranded on our old mailbox will be re-uploaded to our new.
for (Contact c : db.getContacts(txn)) { for (Contact c : db.getContacts(txn)) {
MailboxPropertiesUpdate remoteProps = mailboxPropertyManager MailboxUpdate update = mailboxUpdateManager.getRemoteUpdate(
.getRemoteProperties(txn, c.getId()); txn, c.getId());
if (remoteProps == null) { if (update == null || !update.hasMailbox()) {
db.resetUnackedMessagesToSend(txn, c.getId()); db.resetUnackedMessagesToSend(txn, c.getId());
} }
} }

View File

@@ -91,7 +91,7 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager {
s.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS, ints); s.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS, ints);
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE); settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
for (MailboxHook hook : hooks) { for (MailboxHook hook : hooks) {
hook.mailboxPaired(txn, p.getOnion()); hook.mailboxPaired(txn, p.getOnion(), p.getServerSupports());
} }
} }

View File

@@ -18,11 +18,13 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken; import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxFolderId; import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxProperties; import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate;
import org.briarproject.bramble.api.mailbox.MailboxPropertyManager;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager; import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager.MailboxHook; import org.briarproject.bramble.api.mailbox.MailboxSettingsManager.MailboxHook;
import org.briarproject.bramble.api.mailbox.RemoteMailboxPropertiesUpdateEvent; import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.mailbox.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility; import org.briarproject.bramble.api.sync.Group.Visibility;
@@ -35,6 +37,7 @@ import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.versioning.ClientVersioningManager; import org.briarproject.bramble.api.versioning.ClientVersioningManager;
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook; import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -42,9 +45,10 @@ import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction.ACCEPT_DO_NOT_SHARE; import static org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction.ACCEPT_DO_NOT_SHARE;
import static org.briarproject.bramble.mailbox.MailboxApi.CLIENT_SUPPORTS;
@NotNullByDefault @NotNullByDefault
class MailboxPropertyManagerImpl implements MailboxPropertyManager, class MailboxUpdateManagerImpl implements MailboxUpdateManager,
OpenDatabaseHook, ContactHook, ClientVersioningHook, OpenDatabaseHook, ContactHook, ClientVersioningHook,
IncomingMessageHook, MailboxHook { IncomingMessageHook, MailboxHook {
@@ -59,7 +63,7 @@ class MailboxPropertyManagerImpl implements MailboxPropertyManager,
private final Group localGroup; private final Group localGroup;
@Inject @Inject
MailboxPropertyManagerImpl(DatabaseComponent db, ClientHelper clientHelper, MailboxUpdateManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
ClientVersioningManager clientVersioningManager, ClientVersioningManager clientVersioningManager,
MetadataParser metadataParser, MetadataParser metadataParser,
ContactGroupFactory contactGroupFactory, Clock clock, ContactGroupFactory contactGroupFactory, Clock clock,
@@ -100,11 +104,15 @@ class MailboxPropertyManagerImpl implements MailboxPropertyManager,
db.setGroupVisibility(txn, c.getId(), g.getId(), client); db.setGroupVisibility(txn, c.getId(), g.getId(), client);
// Attach the contact ID to the group // Attach the contact ID to the group
clientHelper.setContactId(txn, g.getId(), c.getId()); clientHelper.setContactId(txn, g.getId(), c.getId());
// If we are paired, create and send props to the newly added contact
MailboxProperties ownProps = MailboxProperties ownProps =
mailboxSettingsManager.getOwnMailboxProperties(txn); mailboxSettingsManager.getOwnMailboxProperties(txn);
if (ownProps != null) { if (ownProps != null) {
createAndSendProperties(txn, c, ownProps.getOnion()); // We are paired, create and send props to the newly added contact
createAndSendUpdateWithMailbox(txn, c, ownProps.getServerSupports(),
ownProps.getOnion());
} else {
// Not paired, but we still want to get our clientSupports sent
sendUpdateNoMailbox(txn, c);
} }
} }
@@ -114,17 +122,18 @@ class MailboxPropertyManagerImpl implements MailboxPropertyManager,
} }
@Override @Override
public void mailboxPaired(Transaction txn, String ownOnion) public void mailboxPaired(Transaction txn, String ownOnion,
List<MailboxVersion> serverSupports)
throws DbException { throws DbException {
for (Contact c : db.getContacts(txn)) { for (Contact c : db.getContacts(txn)) {
createAndSendProperties(txn, c, ownOnion); createAndSendUpdateWithMailbox(txn, c, serverSupports, ownOnion);
} }
} }
@Override @Override
public void mailboxUnpaired(Transaction txn) throws DbException { public void mailboxUnpaired(Transaction txn) throws DbException {
for (Contact c : db.getContacts(txn)) { for (Contact c : db.getContacts(txn)) {
sendEmptyProperties(txn, c); sendUpdateNoMailbox(txn, c);
} }
} }
@@ -156,8 +165,8 @@ class MailboxPropertyManagerImpl implements MailboxPropertyManager,
} }
ContactId c = clientHelper.getContactId(txn, m.getGroupId()); ContactId c = clientHelper.getContactId(txn, m.getGroupId());
BdfList body = clientHelper.getMessageAsList(txn, m.getId()); BdfList body = clientHelper.getMessageAsList(txn, m.getId());
MailboxPropertiesUpdate p = parseProperties(body); MailboxUpdate u = parseUpdate(body);
txn.attach(new RemoteMailboxPropertiesUpdateEvent(c, p)); txn.attach(new RemoteMailboxUpdateEvent(c, u));
// Reset message retransmission timers for the contact. Avoiding // Reset message retransmission timers for the contact. Avoiding
// messages getting stranded: // messages getting stranded:
// - on our mailbox, if they now have a mailbox but didn't before // - on our mailbox, if they now have a mailbox but didn't before
@@ -171,70 +180,79 @@ class MailboxPropertyManagerImpl implements MailboxPropertyManager,
} }
@Override @Override
@Nullable public MailboxUpdate getLocalUpdate(Transaction txn, ContactId c)
public MailboxPropertiesUpdate getLocalProperties(Transaction txn, throws DbException {
ContactId c) throws DbException { MailboxUpdate local = getUpdate(txn, db.getContact(txn, c), true);
return getProperties(txn, db.getContact(txn, c), true); // An update (with or without mailbox) is created when contact is added
if (local == null) {
throw new DbException();
}
return local;
} }
@Override @Override
@Nullable @Nullable
public MailboxPropertiesUpdate getRemoteProperties(Transaction txn, public MailboxUpdate getRemoteUpdate(Transaction txn, ContactId c) throws
ContactId c) throws DbException { DbException {
return getProperties(txn, db.getContact(txn, c), false); return getUpdate(txn, db.getContact(txn, c), false);
} }
/** /**
* Creates and sends an update message to the given contact. The message * Creates and sends an update message to the given contact. The message
* holds our own mailbox's onion, and generated unique properties. All of * holds our own mailbox's onion, generated unique properties, and lists of
* which the contact needs to communicate with our Mailbox. * supported Mailbox API version(s). All of which the contact needs to
* communicate with our Mailbox.
*/ */
private void createAndSendProperties(Transaction txn, private void createAndSendUpdateWithMailbox(Transaction txn, Contact c,
Contact c, String ownOnion) throws DbException { List<MailboxVersion> serverSupports, String ownOnion)
MailboxPropertiesUpdate p = new MailboxPropertiesUpdate(ownOnion, throws DbException {
MailboxUpdate u = new MailboxUpdateWithMailbox(
CLIENT_SUPPORTS, serverSupports, ownOnion,
new MailboxAuthToken(crypto.generateUniqueId().getBytes()), new MailboxAuthToken(crypto.generateUniqueId().getBytes()),
new MailboxFolderId(crypto.generateUniqueId().getBytes()), new MailboxFolderId(crypto.generateUniqueId().getBytes()),
new MailboxFolderId(crypto.generateUniqueId().getBytes())); new MailboxFolderId(crypto.generateUniqueId().getBytes()));
Group g = getContactGroup(c); Group g = getContactGroup(c);
storeMessageReplaceLatest(txn, g.getId(), p); storeMessageReplaceLatest(txn, g.getId(), u);
} }
/** /**
* Sends an empty update message to the given contact. The empty update * Sends an update message with empty properties to the given contact. The
* indicates for the receiving contact that we no longer have a Mailbox that * empty update indicates for the receiving contact that we don't have any
* they can use. * Mailbox that they can use. It still includes the list of Mailbox API
* version(s) that we support as a client.
*/ */
private void sendEmptyProperties(Transaction txn, Contact c) private void sendUpdateNoMailbox(Transaction txn, Contact c)
throws DbException { throws DbException {
Group g = getContactGroup(c); Group g = getContactGroup(c);
storeMessageReplaceLatest(txn, g.getId(), null); MailboxUpdate u = new MailboxUpdate(CLIENT_SUPPORTS);
storeMessageReplaceLatest(txn, g.getId(), u);
} }
@Nullable @Nullable
private MailboxPropertiesUpdate getProperties(Transaction txn, private MailboxUpdate getUpdate(Transaction txn, Contact c, boolean local)
Contact c, boolean local) throws DbException { throws DbException {
MailboxPropertiesUpdate p = null; MailboxUpdate u = null;
Group g = getContactGroup(c); Group g = getContactGroup(c);
try { try {
LatestUpdate latest = findLatest(txn, g.getId(), local); LatestUpdate latest = findLatest(txn, g.getId(), local);
if (latest != null) { if (latest != null) {
BdfList body = BdfList body =
clientHelper.getMessageAsList(txn, latest.messageId); clientHelper.getMessageAsList(txn, latest.messageId);
p = parseProperties(body); u = parseUpdate(body);
} }
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }
return p; return u;
} }
private void storeMessageReplaceLatest(Transaction txn, GroupId g, private void storeMessageReplaceLatest(Transaction txn, GroupId g,
@Nullable MailboxPropertiesUpdate p) throws DbException { MailboxUpdate u) throws DbException {
try { try {
LatestUpdate latest = findLatest(txn, g, true); LatestUpdate latest = findLatest(txn, g, true);
long version = latest == null ? 1 : latest.version + 1; long version = latest == null ? 1 : latest.version + 1;
Message m = clientHelper.createMessage(g, clock.currentTimeMillis(), Message m = clientHelper.createMessage(g, clock.currentTimeMillis(),
encodeProperties(version, p)); encodeProperties(version, u));
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(MSG_KEY_VERSION, version); meta.put(MSG_KEY_VERSION, version);
meta.put(MSG_KEY_LOCAL, true); meta.put(MSG_KEY_LOCAL, true);
@@ -266,23 +284,36 @@ class MailboxPropertyManagerImpl implements MailboxPropertyManager,
return null; return null;
} }
private BdfList encodeProperties(long version, private BdfList encodeProperties(long version, MailboxUpdate u) {
@Nullable MailboxPropertiesUpdate p) {
BdfDictionary dict = new BdfDictionary(); BdfDictionary dict = new BdfDictionary();
if (p != null) { BdfList serverSupports = new BdfList();
dict.put(PROP_KEY_ONION, p.getOnion()); if (u.hasMailbox()) {
dict.put(PROP_KEY_AUTHTOKEN, p.getAuthToken().getBytes()); MailboxUpdateWithMailbox um = (MailboxUpdateWithMailbox) u;
dict.put(PROP_KEY_INBOXID, p.getInboxId().getBytes()); serverSupports = encodeSupportsList(um.getServerSupports());
dict.put(PROP_KEY_OUTBOXID, p.getOutboxId().getBytes()); dict.put(PROP_KEY_ONION, um.getOnion());
dict.put(PROP_KEY_AUTHTOKEN, um.getAuthToken().getBytes());
dict.put(PROP_KEY_INBOXID, um.getInboxId().getBytes());
dict.put(PROP_KEY_OUTBOXID, um.getOutboxId().getBytes());
} }
return BdfList.of(version, dict); return BdfList.of(version, encodeSupportsList(u.getClientSupports()),
serverSupports, dict);
} }
@Nullable private BdfList encodeSupportsList(List<MailboxVersion> supportsList) {
private MailboxPropertiesUpdate parseProperties(BdfList body) BdfList supports = new BdfList();
for (MailboxVersion version : supportsList) {
supports.add(BdfList.of(version.getMajor(), version.getMinor()));
}
return supports;
}
private MailboxUpdate parseUpdate(BdfList body)
throws FormatException { throws FormatException {
BdfDictionary dict = body.getDictionary(1); BdfList clientSupports = body.getList(1);
return clientHelper.parseAndValidateMailboxPropertiesUpdate(dict); BdfList serverSupports = body.getList(2);
BdfDictionary dict = body.getDictionary(3);
return clientHelper.parseAndValidateMailboxUpdate(clientSupports,
serverSupports, dict);
} }
private Group getContactGroup(Contact c) { private Group getContactGroup(Contact c) {

View File

@@ -15,15 +15,15 @@ import org.briarproject.bramble.api.system.Clock;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MSG_KEY_LOCAL; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MSG_KEY_LOCAL;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MSG_KEY_VERSION; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MSG_KEY_VERSION;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class MailboxPropertyValidator extends BdfMessageValidator { class MailboxUpdateValidator extends BdfMessageValidator {
MailboxPropertyValidator(ClientHelper clientHelper, MailboxUpdateValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) { MetadataEncoder metadataEncoder, Clock clock) {
super(clientHelper, metadataEncoder, clock); super(clientHelper, metadataEncoder, clock);
} }
@@ -31,14 +31,19 @@ class MailboxPropertyValidator extends BdfMessageValidator {
@Override @Override
protected BdfMessageContext validateMessage(Message m, Group g, protected BdfMessageContext validateMessage(Message m, Group g,
BdfList body) throws InvalidMessageException, FormatException { BdfList body) throws InvalidMessageException, FormatException {
// Version, properties // Version, Properties, clientSupports, serverSupports
checkSize(body, 2); checkSize(body, 4);
// Version // Version
long version = body.getLong(0); long version = body.getLong(0);
if (version < 0) throw new FormatException(); if (version < 0) throw new FormatException();
// clientSupports
BdfList clientSupports = body.getList(1);
// serverSupports
BdfList serverSupports = body.getList(2);
// Properties // Properties
BdfDictionary dictionary = body.getDictionary(1); BdfDictionary dictionary = body.getDictionary(3);
clientHelper.parseAndValidateMailboxPropertiesUpdate(dictionary); clientHelper.parseAndValidateMailboxUpdate(clientSupports,
serverSupports, dictionary);
// Return the metadata // Return the metadata
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(MSG_KEY_VERSION, version); meta.put(MSG_KEY_VERSION, version);

View File

@@ -23,7 +23,9 @@ import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken; import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxFolderId; import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate; import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageFactory; import org.briarproject.bramble.api.sync.MessageFactory;
@@ -41,24 +43,25 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_AUTHTOKEN; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_AUTHTOKEN;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_INBOXID; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_INBOXID;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_ONION; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_ONION;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_OUTBOXID; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_OUTBOXID;
import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getMessage; import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSignaturePrivateKey; import static org.briarproject.bramble.test.TestUtils.getSignaturePrivateKey;
import static org.briarproject.bramble.test.TestUtils.getSignaturePublicKey; import static org.briarproject.bramble.test.TestUtils.getSignaturePublicKey;
import static org.briarproject.bramble.test.TestUtils.mailboxPropertiesUpdateEqual; import static org.briarproject.bramble.test.TestUtils.mailboxUpdateEqual;
import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@@ -95,24 +98,34 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
messageFactory, bdfReaderFactory, bdfWriterFactory, metadataParser, messageFactory, bdfReaderFactory, bdfWriterFactory, metadataParser,
metadataEncoder, cryptoComponent, authorFactory); metadataEncoder, cryptoComponent, authorFactory);
private final MailboxPropertiesUpdate validMailboxPropsUpdate; private final MailboxUpdateWithMailbox validMailboxUpdateWithMailbox;
private final BdfList emptyClientSupports;
private final BdfList someClientSupports;
private final BdfList emptyServerSupports;
private final BdfList someServerSupports;
public ClientHelperImplTest() { public ClientHelperImplTest() {
validMailboxPropsUpdate = new MailboxPropertiesUpdate( emptyClientSupports = new BdfList();
someClientSupports = BdfList.of(BdfList.of(1, 0));
emptyServerSupports = new BdfList();
someServerSupports = BdfList.of(BdfList.of(1, 0));
validMailboxUpdateWithMailbox = new MailboxUpdateWithMailbox(
singletonList(new MailboxVersion(1, 0)),
singletonList(new MailboxVersion(1, 0)),
"pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd", "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd",
new MailboxAuthToken(getRandomId()), new MailboxAuthToken(getRandomId()),
new MailboxFolderId(getRandomId()), new MailboxFolderId(getRandomId()),
new MailboxFolderId(getRandomId())); new MailboxFolderId(getRandomId()));
} }
private BdfDictionary getValidMailboxPropsUpdateDict() { private BdfDictionary getValidMailboxUpdateWithMailboxDict() {
BdfDictionary dict = new BdfDictionary(); BdfDictionary dict = new BdfDictionary();
dict.put(PROP_KEY_ONION, validMailboxPropsUpdate.getOnion()); dict.put(PROP_KEY_ONION, validMailboxUpdateWithMailbox.getOnion());
dict.put(PROP_KEY_AUTHTOKEN, validMailboxPropsUpdate.getAuthToken() dict.put(PROP_KEY_AUTHTOKEN, validMailboxUpdateWithMailbox
.getAuthToken().getBytes());
dict.put(PROP_KEY_INBOXID, validMailboxUpdateWithMailbox.getInboxId()
.getBytes()); .getBytes());
dict.put(PROP_KEY_INBOXID, validMailboxPropsUpdate.getInboxId() dict.put(PROP_KEY_OUTBOXID, validMailboxUpdateWithMailbox.getOutboxId()
.getBytes());
dict.put(PROP_KEY_OUTBOXID, validMailboxPropsUpdate.getOutboxId()
.getBytes()); .getBytes());
return dict; return dict;
} }
@@ -546,94 +559,151 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}}); }});
} }
@Test @Test(expected = FormatException.class)
public void testParseEmptyMailboxPropsUpdate() throws Exception { public void testRejectsMailboxUpdateWithEmptyClientSupports()
throws Exception {
BdfDictionary emptyPropsDict = new BdfDictionary(); BdfDictionary emptyPropsDict = new BdfDictionary();
MailboxPropertiesUpdate parsedProps = clientHelper clientHelper.parseAndValidateMailboxUpdate(emptyClientSupports,
.parseAndValidateMailboxPropertiesUpdate(emptyPropsDict); emptyServerSupports, emptyPropsDict
assertNull(parsedProps); );
} }
@Test @Test
public void testParseValidMailboxPropsUpdate() throws Exception { public void testParseMailboxUpdateNoMailbox() throws Exception {
MailboxPropertiesUpdate parsedProps = clientHelper BdfDictionary emptyPropsDict = new BdfDictionary();
.parseAndValidateMailboxPropertiesUpdate( MailboxUpdate parsedUpdate = clientHelper.parseAndValidateMailboxUpdate(
getValidMailboxPropsUpdateDict()); someClientSupports, emptyServerSupports, emptyPropsDict);
assertTrue(mailboxPropertiesUpdateEqual(validMailboxPropsUpdate, assertFalse(parsedUpdate.hasMailbox());
parsedProps));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMailboxPropsUpdateOnionNotDecodable() public void testRejectsMailboxUpdateNoMailboxWithSomeServerSupports()
throws Exception { throws Exception {
BdfDictionary propsDict = getValidMailboxPropsUpdateDict(); BdfDictionary emptyPropsDict = new BdfDictionary();
clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
someServerSupports, emptyPropsDict);
}
@Test(expected = FormatException.class)
public void testRejectsMailboxUpdateShortSupports() throws Exception {
clientHelper.parseAndValidateMailboxUpdate(BdfList.of(BdfList.of(1)),
emptyServerSupports, new BdfDictionary());
}
@Test(expected = FormatException.class)
public void testRejectsMailboxUpdateLongSupports() throws Exception {
clientHelper.parseAndValidateMailboxUpdate(
BdfList.of(BdfList.of(1, 0, 0)), emptyServerSupports,
new BdfDictionary());
}
@Test(expected = FormatException.class)
public void testRejectsMailboxUpdateNonIntSupports() throws Exception {
clientHelper.parseAndValidateMailboxUpdate(
BdfList.of(BdfList.of(1, "0")), emptyServerSupports,
new BdfDictionary()
);
}
@Test(expected = FormatException.class)
public void testRejectsMailboxUpdateNonListSupports() throws Exception {
clientHelper.parseAndValidateMailboxUpdate(
BdfList.of("non-list"), emptyServerSupports,
new BdfDictionary());
}
@Test
public void testParseValidMailboxUpdateWithMailbox() throws Exception {
MailboxUpdate parsedUpdate = clientHelper.parseAndValidateMailboxUpdate(
someClientSupports, someServerSupports,
getValidMailboxUpdateWithMailboxDict());
assertTrue(
mailboxUpdateEqual(validMailboxUpdateWithMailbox,
parsedUpdate));
}
@Test(expected = FormatException.class)
public void rejectsMailboxUpdateWithEmptyServerSupports() throws Exception {
clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
emptyServerSupports, getValidMailboxUpdateWithMailboxDict());
}
@Test(expected = FormatException.class)
public void testRejectsMailboxUpdateOnionNotDecodable() throws Exception {
BdfDictionary propsDict = getValidMailboxUpdateWithMailboxDict();
String badOnion = "!" + propsDict.getString(PROP_KEY_ONION) String badOnion = "!" + propsDict.getString(PROP_KEY_ONION)
.substring(1); .substring(1);
propsDict.put(PROP_KEY_ONION, badOnion); propsDict.put(PROP_KEY_ONION, badOnion);
clientHelper.parseAndValidateMailboxPropertiesUpdate(propsDict); clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
emptyServerSupports, propsDict);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMailboxPropsUpdateOnionWrongLength() public void testRejectsMailboxUpdateOnionWrongLength() throws Exception {
throws Exception { BdfDictionary propsDict = getValidMailboxUpdateWithMailboxDict();
BdfDictionary propsDict = getValidMailboxPropsUpdateDict();
String tooLongOnion = propsDict.getString(PROP_KEY_ONION) + "!"; String tooLongOnion = propsDict.getString(PROP_KEY_ONION) + "!";
propsDict.put(PROP_KEY_ONION, tooLongOnion); propsDict.put(PROP_KEY_ONION, tooLongOnion);
clientHelper.parseAndValidateMailboxPropertiesUpdate(propsDict); clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
emptyServerSupports, propsDict
);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMailboxPropsUpdateInboxIdWrongLength() public void testRejectsMailboxUpdateInboxIdWrongLength() throws Exception {
throws Exception { BdfDictionary propsDict = getValidMailboxUpdateWithMailboxDict();
BdfDictionary propsDict = getValidMailboxPropsUpdateDict();
propsDict.put(PROP_KEY_INBOXID, getRandomBytes(UniqueId.LENGTH + 1)); propsDict.put(PROP_KEY_INBOXID, getRandomBytes(UniqueId.LENGTH + 1));
clientHelper.parseAndValidateMailboxPropertiesUpdate(propsDict); clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
someServerSupports, propsDict);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMailboxPropsUpdateOutboxIdWrongLength() public void testRejectsMailboxUpdateOutboxIdWrongLength() throws Exception {
throws Exception { BdfDictionary propsDict = getValidMailboxUpdateWithMailboxDict();
BdfDictionary propsDict = getValidMailboxPropsUpdateDict();
propsDict.put(PROP_KEY_OUTBOXID, getRandomBytes(UniqueId.LENGTH + 1)); propsDict.put(PROP_KEY_OUTBOXID, getRandomBytes(UniqueId.LENGTH + 1));
clientHelper.parseAndValidateMailboxPropertiesUpdate(propsDict); clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
someServerSupports, propsDict);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMailboxPropsUpdateAuthTokenWrongLength() public void testRejectsMailboxUpdateAuthTokenWrongLength()
throws Exception { throws Exception {
BdfDictionary propsDict = getValidMailboxPropsUpdateDict(); BdfDictionary propsDict = getValidMailboxUpdateWithMailboxDict();
propsDict.put(PROP_KEY_AUTHTOKEN, getRandomBytes(UniqueId.LENGTH + 1)); propsDict.put(PROP_KEY_AUTHTOKEN, getRandomBytes(UniqueId.LENGTH + 1));
clientHelper.parseAndValidateMailboxPropertiesUpdate(propsDict); clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
someServerSupports, propsDict);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMailboxPropsUpdateMissingOnion() throws Exception { public void testRejectsMailboxUpdateMissingOnion() throws Exception {
BdfDictionary propsDict = getValidMailboxPropsUpdateDict(); BdfDictionary propsDict = getValidMailboxUpdateWithMailboxDict();
propsDict.remove(PROP_KEY_ONION); propsDict.remove(PROP_KEY_ONION);
clientHelper.parseAndValidateMailboxPropertiesUpdate(propsDict); clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
someServerSupports, propsDict
);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMailboxPropsUpdateMissingAuthToken() public void testRejectsMailboxUpdateMissingAuthToken() throws Exception {
throws Exception { BdfDictionary propsDict = getValidMailboxUpdateWithMailboxDict();
BdfDictionary propsDict = getValidMailboxPropsUpdateDict();
propsDict.remove(PROP_KEY_AUTHTOKEN); propsDict.remove(PROP_KEY_AUTHTOKEN);
clientHelper.parseAndValidateMailboxPropertiesUpdate(propsDict); clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
someServerSupports, propsDict);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMailboxPropsUpdateMissingInboxId() throws Exception { public void testRejectsMailboxUpdateMissingInboxId() throws Exception {
BdfDictionary propsDict = getValidMailboxPropsUpdateDict(); BdfDictionary propsDict = getValidMailboxUpdateWithMailboxDict();
propsDict.remove(PROP_KEY_INBOXID); propsDict.remove(PROP_KEY_INBOXID);
clientHelper.parseAndValidateMailboxPropertiesUpdate(propsDict); clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
someServerSupports, propsDict);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMailboxPropsUpdateMissingOutboxId() public void testRejectsMailboxUpdateMissingOutboxId() throws Exception {
throws Exception { BdfDictionary propsDict = getValidMailboxUpdateWithMailboxDict();
BdfDictionary propsDict = getValidMailboxPropsUpdateDict();
propsDict.remove(PROP_KEY_OUTBOXID); propsDict.remove(PROP_KEY_OUTBOXID);
clientHelper.parseAndValidateMailboxPropertiesUpdate(propsDict); clientHelper.parseAndValidateMailboxUpdate(someClientSupports,
someServerSupports, propsDict);
} }
} }

View File

@@ -9,8 +9,9 @@ import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxPairingState; import org.briarproject.bramble.api.mailbox.MailboxPairingState;
import org.briarproject.bramble.api.mailbox.MailboxPairingTask; import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
import org.briarproject.bramble.api.mailbox.MailboxProperties; import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxPropertyManager;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager; import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.mailbox.OwnMailboxConnectionStatusEvent; import org.briarproject.bramble.api.mailbox.OwnMailboxConnectionStatusEvent;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
@@ -24,10 +25,11 @@ import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.mailbox.MailboxApi.CLIENT_SUPPORTS;
import static org.briarproject.bramble.test.TestUtils.getContact; import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
@@ -47,11 +49,11 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
private final MailboxApi api = context.mock(MailboxApi.class); private final MailboxApi api = context.mock(MailboxApi.class);
private final MailboxSettingsManager mailboxSettingsManager = private final MailboxSettingsManager mailboxSettingsManager =
context.mock(MailboxSettingsManager.class); context.mock(MailboxSettingsManager.class);
private final MailboxPropertyManager mailboxPropertyManager = private final MailboxUpdateManager mailboxUpdateManager =
context.mock(MailboxPropertyManager.class); context.mock(MailboxUpdateManager.class);
private final MailboxPairingTaskFactory factory = private final MailboxPairingTaskFactory factory =
new MailboxPairingTaskFactoryImpl(executor, db, crypto, clock, api, new MailboxPairingTaskFactoryImpl(executor, db, crypto, clock, api,
mailboxSettingsManager, mailboxPropertyManager); mailboxSettingsManager, mailboxUpdateManager);
private final String onion = getRandomString(56); private final String onion = getRandomString(56);
private final byte[] onionBytes = getRandomBytes(32); private final byte[] onionBytes = getRandomBytes(32);
@@ -105,16 +107,17 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
}}); }});
Contact contact1 = getContact(); Contact contact1 = getContact();
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
MailboxUpdate updateNoMailbox = new MailboxUpdate(CLIENT_SUPPORTS);
context.checking(new DbExpectations() {{ context.checking(new DbExpectations() {{
oneOf(db).transaction(with(false), withDbRunnable(txn)); oneOf(db).transaction(with(false), withDbRunnable(txn));
oneOf(mailboxSettingsManager).setOwnMailboxProperties( oneOf(mailboxSettingsManager).setOwnMailboxProperties(
with(txn), with(matches(ownerProperties))); with(txn), with(matches(ownerProperties)));
oneOf(mailboxSettingsManager).recordSuccessfulConnection(txn, time); oneOf(mailboxSettingsManager).recordSuccessfulConnection(txn, time);
oneOf(db).getContacts(txn); oneOf(db).getContacts(txn);
will(returnValue(Collections.singletonList(contact1))); will(returnValue(singletonList(contact1)));
oneOf(mailboxPropertyManager).getRemoteProperties(txn, oneOf(mailboxUpdateManager).getRemoteUpdate(txn,
contact1.getId()); contact1.getId());
will(returnValue(null)); will(returnValue(updateNoMailbox));
oneOf(db).resetUnackedMessagesToSend(txn, contact1.getId()); oneOf(db).resetUnackedMessagesToSend(txn, contact1.getId());
}}); }});

View File

@@ -14,9 +14,11 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken; import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxFolderId; import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxProperties; import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager; import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.RemoteMailboxPropertiesUpdateEvent; import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.mailbox.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
@@ -27,34 +29,34 @@ import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.CLIENT_ID; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.CLIENT_ID;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MAJOR_VERSION; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MAJOR_VERSION;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MSG_KEY_LOCAL; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MSG_KEY_LOCAL;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.MSG_KEY_VERSION; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MSG_KEY_VERSION;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_AUTHTOKEN; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_AUTHTOKEN;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_INBOXID; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_INBOXID;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_ONION; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_ONION;
import static org.briarproject.bramble.api.mailbox.MailboxPropertyManager.PROP_KEY_OUTBOXID; import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY_OUTBOXID;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction.ACCEPT_DO_NOT_SHARE; import static org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction.ACCEPT_DO_NOT_SHARE;
import static org.briarproject.bramble.mailbox.MailboxApi.CLIENT_SUPPORTS;
import static org.briarproject.bramble.test.TestUtils.getContact; import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getMessage; import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.hasEvent; import static org.briarproject.bramble.test.TestUtils.hasEvent;
import static org.briarproject.bramble.test.TestUtils.mailboxPropertiesUpdateEqual; import static org.briarproject.bramble.test.TestUtils.mailboxUpdateEqual;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
public class MailboxPropertyManagerImplTest extends BrambleMockTestCase { public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class); private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final ClientHelper clientHelper = context.mock(ClientHelper.class); private final ClientHelper clientHelper = context.mock(ClientHelper.class);
@@ -72,30 +74,54 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION); private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
private final BdfDictionary propsDict; private final BdfDictionary propsDict;
private final BdfDictionary emptyPropsDict = new BdfDictionary(); private final BdfDictionary emptyPropsDict = new BdfDictionary();
private final MailboxPropertiesUpdate props; private final BdfList realClientSupports;
private final BdfList someClientSupports;
private final List<MailboxVersion> someClientSupportsList;
private final BdfList emptyServerSupports;
private final BdfList someServerSupports;
private final List<MailboxVersion> someServerSupportsList;
private final MailboxUpdateWithMailbox updateWithMailbox;
private final MailboxUpdate updateNoMailbox;
private final MailboxProperties ownProps; private final MailboxProperties ownProps;
public MailboxPropertyManagerImplTest() { public MailboxUpdateManagerImplTest() {
someClientSupports = BdfList.of(BdfList.of(1, 0));
someClientSupportsList = singletonList(new MailboxVersion(1, 0));
emptyServerSupports = new BdfList();
someServerSupports = BdfList.of(BdfList.of(1, 0));
someServerSupportsList = singletonList(new MailboxVersion(1, 0));
realClientSupports = new BdfList();
for (MailboxVersion v : CLIENT_SUPPORTS) {
realClientSupports.add(BdfList.of(v.getMajor(), v.getMinor()));
}
ownProps = new MailboxProperties("http://bar.onion", ownProps = new MailboxProperties("http://bar.onion",
new MailboxAuthToken(getRandomId()), true, new ArrayList<>()); new MailboxAuthToken(getRandomId()), true,
props = new MailboxPropertiesUpdate(ownProps.getOnion(), someServerSupportsList);
updateWithMailbox = new MailboxUpdateWithMailbox(
singletonList(new MailboxVersion(1, 0)),
singletonList(new MailboxVersion(1, 0)),
ownProps.getOnion(),
new MailboxAuthToken(getRandomId()), new MailboxAuthToken(getRandomId()),
new MailboxFolderId(getRandomId()), new MailboxFolderId(getRandomId()),
new MailboxFolderId(getRandomId())); new MailboxFolderId(getRandomId()));
propsDict = new BdfDictionary(); propsDict = new BdfDictionary();
propsDict.put(PROP_KEY_ONION, props.getOnion()); propsDict.put(PROP_KEY_ONION, updateWithMailbox.getOnion());
propsDict.put(PROP_KEY_AUTHTOKEN, props.getAuthToken().getBytes()); propsDict.put(PROP_KEY_AUTHTOKEN, updateWithMailbox.getAuthToken()
propsDict.put(PROP_KEY_INBOXID, props.getInboxId().getBytes()); .getBytes());
propsDict.put(PROP_KEY_OUTBOXID, props.getOutboxId().getBytes()); propsDict.put(PROP_KEY_INBOXID, updateWithMailbox.getInboxId()
.getBytes());
propsDict.put(PROP_KEY_OUTBOXID, updateWithMailbox.getOutboxId()
.getBytes());
updateNoMailbox = new MailboxUpdate(someClientSupportsList);
} }
private MailboxPropertyManagerImpl createInstance() { private MailboxUpdateManagerImpl createInstance() {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID, oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID,
MAJOR_VERSION); MAJOR_VERSION);
will(returnValue(localGroup)); will(returnValue(localGroup));
}}); }});
return new MailboxPropertyManagerImpl(db, clientHelper, return new MailboxUpdateManagerImpl(db, clientHelper,
clientVersioningManager, metadataParser, contactGroupFactory, clientVersioningManager, metadataParser, contactGroupFactory,
clock, mailboxSettingsManager, crypto); clock, mailboxSettingsManager, crypto);
} }
@@ -105,6 +131,7 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
Contact contact = getContact(); Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION); Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).containsGroup(txn, localGroup.getId()); oneOf(db).containsGroup(txn, localGroup.getId());
@@ -125,9 +152,17 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
contact.getId()); contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn); oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(null)); will(returnValue(null));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroup.getId(), 1, realClientSupports,
emptyServerSupports, emptyPropsDict, true);
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
t.onDatabaseOpened(txn); t.onDatabaseOpened(txn);
} }
@@ -159,21 +194,22 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn); oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(ownProps)); will(returnValue(ownProps));
oneOf(crypto).generateUniqueId(); oneOf(crypto).generateUniqueId();
will(returnValue(props.getAuthToken())); will(returnValue(updateWithMailbox.getAuthToken()));
oneOf(crypto).generateUniqueId(); oneOf(crypto).generateUniqueId();
will(returnValue(props.getInboxId())); will(returnValue(updateWithMailbox.getInboxId()));
oneOf(crypto).generateUniqueId(); oneOf(crypto).generateUniqueId();
will(returnValue(props.getOutboxId())); will(returnValue(updateWithMailbox.getOutboxId()));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact); MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroup.getId(), propsDict, 1, true); expectStoreMessage(txn, contactGroup.getId(), 1, realClientSupports,
someServerSupports, propsDict, true);
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
t.onDatabaseOpened(txn); t.onDatabaseOpened(txn);
} }
@@ -187,7 +223,7 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
will(returnValue(true)); will(returnValue(true));
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
t.onDatabaseOpened(txn); t.onDatabaseOpened(txn);
} }
@@ -197,6 +233,7 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
Contact contact = getContact(); Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION); Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Create the group and share it with the contact // Create the group and share it with the contact
@@ -213,9 +250,17 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
contact.getId()); contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn); oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(null)); will(returnValue(null));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroup.getId(), 1, realClientSupports,
emptyServerSupports, emptyPropsDict, true);
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
t.addingContact(txn, contact); t.addingContact(txn, contact);
} }
@@ -243,21 +288,22 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn); oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(ownProps)); will(returnValue(ownProps));
oneOf(crypto).generateUniqueId(); oneOf(crypto).generateUniqueId();
will(returnValue(props.getAuthToken())); will(returnValue(updateWithMailbox.getAuthToken()));
oneOf(crypto).generateUniqueId(); oneOf(crypto).generateUniqueId();
will(returnValue(props.getInboxId())); will(returnValue(updateWithMailbox.getInboxId()));
oneOf(crypto).generateUniqueId(); oneOf(crypto).generateUniqueId();
will(returnValue(props.getOutboxId())); will(returnValue(updateWithMailbox.getOutboxId()));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact); MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroup.getId(), propsDict, 1, true); expectStoreMessage(txn, contactGroup.getId(), 1, someClientSupports,
someServerSupports, propsDict, true);
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
t.addingContact(txn, contact); t.addingContact(txn, contact);
} }
@@ -274,7 +320,7 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(db).removeGroup(txn, contactGroup); oneOf(db).removeGroup(txn, contactGroup);
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
t.removingContact(txn, contact); t.removingContact(txn, contact);
} }
@@ -285,7 +331,8 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
Contact contact = getContact(); Contact contact = getContact();
GroupId contactGroupId = new GroupId(getRandomId()); GroupId contactGroupId = new GroupId(getRandomId());
Message message = getMessage(contactGroupId); Message message = getMessage(contactGroupId);
BdfList body = BdfList.of(1, propsDict); BdfList body = BdfList.of(1, someClientSupports, someServerSupports,
propsDict);
Metadata meta = new Metadata(); Metadata meta = new Metadata();
BdfDictionary metaDictionary = BdfDictionary.of( BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 1), new BdfEntry(MSG_KEY_VERSION, 1),
@@ -309,16 +356,16 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
will(returnValue(contact.getId())); will(returnValue(contact.getId()));
oneOf(clientHelper).getMessageAsList(txn, message.getId()); oneOf(clientHelper).getMessageAsList(txn, message.getId());
will(returnValue(body)); will(returnValue(body));
oneOf(clientHelper).parseAndValidateMailboxPropertiesUpdate( oneOf(clientHelper).parseAndValidateMailboxUpdate(
propsDict); someClientSupports, someServerSupports, propsDict);
will(returnValue(props)); will(returnValue(updateWithMailbox));
oneOf(db).resetUnackedMessagesToSend(txn, contact.getId()); oneOf(db).resetUnackedMessagesToSend(txn, contact.getId());
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
assertEquals(ACCEPT_DO_NOT_SHARE, assertEquals(ACCEPT_DO_NOT_SHARE,
t.incomingMessage(txn, message, meta)); t.incomingMessage(txn, message, meta));
assertTrue(hasEvent(txn, RemoteMailboxPropertiesUpdateEvent.class)); assertTrue(hasEvent(txn, RemoteMailboxUpdateEvent.class));
} }
@Test @Test
@@ -328,7 +375,8 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
Contact contact = getContact(); Contact contact = getContact();
GroupId contactGroupId = new GroupId(getRandomId()); GroupId contactGroupId = new GroupId(getRandomId());
Message message = getMessage(contactGroupId); Message message = getMessage(contactGroupId);
BdfList body = BdfList.of(1, propsDict); BdfList body = BdfList.of(1, someClientSupports, someServerSupports,
propsDict);
Metadata meta = new Metadata(); Metadata meta = new Metadata();
BdfDictionary metaDictionary = BdfDictionary.of( BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 2), new BdfEntry(MSG_KEY_VERSION, 2),
@@ -360,16 +408,16 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
will(returnValue(contact.getId())); will(returnValue(contact.getId()));
oneOf(clientHelper).getMessageAsList(txn, message.getId()); oneOf(clientHelper).getMessageAsList(txn, message.getId());
will(returnValue(body)); will(returnValue(body));
oneOf(clientHelper).parseAndValidateMailboxPropertiesUpdate( oneOf(clientHelper).parseAndValidateMailboxUpdate(
propsDict); someClientSupports, someServerSupports, propsDict);
will(returnValue(props)); will(returnValue(updateWithMailbox));
oneOf(db).resetUnackedMessagesToSend(txn, contact.getId()); oneOf(db).resetUnackedMessagesToSend(txn, contact.getId());
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
assertEquals(ACCEPT_DO_NOT_SHARE, assertEquals(ACCEPT_DO_NOT_SHARE,
t.incomingMessage(txn, message, meta)); t.incomingMessage(txn, message, meta));
assertTrue(hasEvent(txn, RemoteMailboxPropertiesUpdateEvent.class)); assertTrue(hasEvent(txn, RemoteMailboxUpdateEvent.class));
} }
@Test @Test
@@ -400,14 +448,14 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(db).deleteMessageMetadata(txn, message.getId()); oneOf(db).deleteMessageMetadata(txn, message.getId());
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
assertEquals(ACCEPT_DO_NOT_SHARE, assertEquals(ACCEPT_DO_NOT_SHARE,
t.incomingMessage(txn, message, meta)); t.incomingMessage(txn, message, meta));
assertFalse(hasEvent(txn, RemoteMailboxPropertiesUpdateEvent.class)); assertFalse(hasEvent(txn, RemoteMailboxUpdateEvent.class));
} }
@Test @Test
public void testCreatesAndStoresLocalPropertiesWithNewVersionOnPairing() public void testCreatesAndStoresLocalUpdateWithNewVersionOnPairing()
throws Exception { throws Exception {
Contact contact = getContact(); Contact contact = getContact();
List<Contact> contacts = singletonList(contact); List<Contact> contacts = singletonList(contact);
@@ -430,27 +478,28 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(db).getContacts(txn); oneOf(db).getContacts(txn);
will(returnValue(contacts)); will(returnValue(contacts));
oneOf(crypto).generateUniqueId(); oneOf(crypto).generateUniqueId();
will(returnValue(props.getAuthToken())); will(returnValue(updateWithMailbox.getAuthToken()));
oneOf(crypto).generateUniqueId(); oneOf(crypto).generateUniqueId();
will(returnValue(props.getInboxId())); will(returnValue(updateWithMailbox.getInboxId()));
oneOf(crypto).generateUniqueId(); oneOf(crypto).generateUniqueId();
will(returnValue(props.getOutboxId())); will(returnValue(updateWithMailbox.getOutboxId()));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact); MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroup.getId(), propsDict, 2, true); expectStoreMessage(txn, contactGroup.getId(), 2, someClientSupports,
someServerSupports, propsDict, true);
oneOf(db).removeMessage(txn, latestId); oneOf(db).removeMessage(txn, latestId);
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
t.mailboxPaired(txn, ownProps.getOnion()); t.mailboxPaired(txn, ownProps.getOnion(), someServerSupportsList);
} }
@Test @Test
public void testStoresEmptyLocalPropertiesWithNewVersionOnUnpairing() public void testStoresLocalUpdateNoMailboxWithNewVersionOnUnpairing()
throws Exception { throws Exception {
Contact contact = getContact(); Contact contact = getContact();
List<Contact> contacts = singletonList(contact); List<Contact> contacts = singletonList(contact);
@@ -478,18 +527,17 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroup.getId(), emptyPropsDict, expectStoreMessage(txn, contactGroup.getId(), 2, someClientSupports,
2, true); emptyServerSupports, emptyPropsDict, true);
oneOf(db).removeMessage(txn, latestId); oneOf(db).removeMessage(txn, latestId);
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
t.mailboxUnpaired(txn); t.mailboxUnpaired(txn);
} }
@Test @Test
public void testGetRemoteProperties() public void testGetRemoteUpdate() throws Exception {
throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
Contact contact = getContact(); Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION); Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
@@ -498,34 +546,34 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
new BdfEntry(MSG_KEY_LOCAL, false) new BdfEntry(MSG_KEY_LOCAL, false)
); );
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>(); Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
MessageId fooUpdateId = new MessageId(getRandomId()); MessageId messageId = new MessageId(getRandomId());
messageMetadata.put(fooUpdateId, metaDictionary); messageMetadata.put(messageId, metaDictionary);
BdfList fooUpdate = BdfList.of(1, propsDict); BdfList body = BdfList.of(1, someClientSupports, someServerSupports,
propsDict);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).getContact(txn, contact.getId()); oneOf(db).getContact(txn, contact.getId());
will(returnValue(contact)); will(returnValue(contact));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory)
MAJOR_VERSION, contact); .createContactGroup(CLIENT_ID, MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId); oneOf(clientHelper).getMessageAsList(txn, messageId);
will(returnValue(fooUpdate)); will(returnValue(body));
oneOf(clientHelper).parseAndValidateMailboxPropertiesUpdate( oneOf(clientHelper).parseAndValidateMailboxUpdate(
propsDict); someClientSupports, someServerSupports, propsDict);
will(returnValue(props)); will(returnValue(updateWithMailbox));
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
MailboxPropertiesUpdate remote = MailboxUpdate remote = t.getRemoteUpdate(txn, contact.getId());
t.getRemoteProperties(txn, contact.getId()); assertTrue(mailboxUpdateEqual(remote, updateWithMailbox));
assertTrue(mailboxPropertiesUpdateEqual(remote, props));
} }
@Test @Test
public void testGetRemotePropertiesReturnsNullBecauseNoUpdate() public void testGetRemoteUpdateReturnsNullBecauseNoUpdate()
throws Exception { throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
Contact contact = getContact(); Contact contact = getContact();
@@ -544,13 +592,12 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
will(returnValue(emptyMessageMetadata)); will(returnValue(emptyMessageMetadata));
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
assertNull(t.getRemoteProperties(txn, contact.getId())); assertNull(t.getRemoteUpdate(txn, contact.getId()));
} }
@Test @Test
public void testGetRemotePropertiesReturnsNullBecauseEmptyUpdate() public void testGetRemoteUpdateNoMailbox() throws Exception {
throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
Contact contact = getContact(); Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION); Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
@@ -559,9 +606,10 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
new BdfEntry(MSG_KEY_LOCAL, false) new BdfEntry(MSG_KEY_LOCAL, false)
); );
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>(); Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
MessageId fooUpdateId = new MessageId(getRandomId()); MessageId messageId = new MessageId(getRandomId());
messageMetadata.put(fooUpdateId, metaDictionary); messageMetadata.put(messageId, metaDictionary);
BdfList fooUpdate = BdfList.of(1, emptyPropsDict); BdfList body = BdfList.of(1, someClientSupports, emptyServerSupports,
emptyPropsDict);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).getContact(txn, contact.getId()); oneOf(db).getContact(txn, contact.getId());
@@ -572,20 +620,20 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId); oneOf(clientHelper).getMessageAsList(txn, messageId);
will(returnValue(fooUpdate)); will(returnValue(body));
oneOf(clientHelper).parseAndValidateMailboxPropertiesUpdate( oneOf(clientHelper).parseAndValidateMailboxUpdate(
emptyPropsDict); someClientSupports, emptyServerSupports, emptyPropsDict);
will(returnValue(null)); will(returnValue(updateNoMailbox));
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
assertNull(t.getRemoteProperties(txn, contact.getId())); MailboxUpdate remote = t.getRemoteUpdate(txn, contact.getId());
assertTrue(mailboxUpdateEqual(remote, updateNoMailbox));
} }
@Test @Test
public void testGetLocalProperties() public void testGetLocalUpdate() throws Exception {
throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
Contact contact = getContact(); Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION); Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
@@ -594,9 +642,10 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
new BdfEntry(MSG_KEY_LOCAL, true) new BdfEntry(MSG_KEY_LOCAL, true)
); );
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>(); Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
MessageId fooUpdateId = new MessageId(getRandomId()); MessageId messageId = new MessageId(getRandomId());
messageMetadata.put(fooUpdateId, metaDictionary); messageMetadata.put(messageId, metaDictionary);
BdfList fooUpdate = BdfList.of(1, propsDict); BdfList body = BdfList.of(1, someClientSupports, someServerSupports,
propsDict);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).getContact(txn, contact.getId()); oneOf(db).getContact(txn, contact.getId());
@@ -607,46 +656,20 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId); oneOf(clientHelper).getMessageAsList(txn, messageId);
will(returnValue(fooUpdate)); will(returnValue(body));
oneOf(clientHelper).parseAndValidateMailboxPropertiesUpdate( oneOf(clientHelper).parseAndValidateMailboxUpdate(
propsDict); someClientSupports, someServerSupports, propsDict);
will(returnValue(props)); will(returnValue(updateWithMailbox));
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
MailboxPropertiesUpdate local = MailboxUpdate local = t.getLocalUpdate(txn, contact.getId());
t.getLocalProperties(txn, contact.getId()); assertTrue(mailboxUpdateEqual(local, updateWithMailbox));
assertTrue(mailboxPropertiesUpdateEqual(local, props));
} }
@Test @Test
public void testGetLocalPropertiesReturnsNullBecauseNoUpdate() public void testGetLocalUpdateNoMailbox() throws Exception {
throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> emptyMessageMetadata =
new LinkedHashMap<>();
context.checking(new Expectations() {{
oneOf(db).getContact(txn, contact.getId());
will(returnValue(contact));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(emptyMessageMetadata));
}});
MailboxPropertyManagerImpl t = createInstance();
assertNull(t.getLocalProperties(txn, contact.getId()));
}
@Test
public void testGetLocalPropertiesReturnsNullBecauseEmptyUpdate()
throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
Contact contact = getContact(); Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION); Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
@@ -655,9 +678,10 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
new BdfEntry(MSG_KEY_LOCAL, true) new BdfEntry(MSG_KEY_LOCAL, true)
); );
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>(); Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
MessageId fooUpdateId = new MessageId(getRandomId()); MessageId messageId = new MessageId(getRandomId());
messageMetadata.put(fooUpdateId, metaDictionary); messageMetadata.put(messageId, metaDictionary);
BdfList fooUpdate = BdfList.of(1, emptyPropsDict); BdfList body = BdfList.of(1, someClientSupports, emptyServerSupports,
emptyPropsDict);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).getContact(txn, contact.getId()); oneOf(db).getContact(txn, contact.getId());
@@ -668,21 +692,24 @@ public class MailboxPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId()); contactGroup.getId());
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId); oneOf(clientHelper).getMessageAsList(txn, messageId);
will(returnValue(fooUpdate)); will(returnValue(body));
oneOf(clientHelper).parseAndValidateMailboxPropertiesUpdate( oneOf(clientHelper).parseAndValidateMailboxUpdate(
emptyPropsDict); someClientSupports, emptyServerSupports, emptyPropsDict);
will(returnValue(null)); will(returnValue(updateNoMailbox));
}}); }});
MailboxPropertyManagerImpl t = createInstance(); MailboxUpdateManagerImpl t = createInstance();
assertNull(t.getLocalProperties(txn, contact.getId())); MailboxUpdate local = t.getLocalUpdate(txn, contact.getId());
assertTrue(mailboxUpdateEqual(local, updateNoMailbox));
} }
private void expectStoreMessage(Transaction txn, GroupId g, private void expectStoreMessage(Transaction txn, GroupId g,
BdfDictionary properties, long version, boolean local) long version, BdfList clientSupports, BdfList serverSupports,
BdfDictionary properties, boolean local)
throws Exception { throws Exception {
BdfList body = BdfList.of(version, properties); BdfList body = BdfList.of(version, clientSupports, serverSupports,
properties);
Message message = getMessage(g); Message message = getMessage(g);
long timestamp = message.getTimestamp(); long timestamp = message.getTimestamp();
BdfDictionary meta = BdfDictionary.of( BdfDictionary meta = BdfDictionary.of(

View File

@@ -8,8 +8,10 @@ import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken; import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxFolderId; import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxPropertiesUpdate; import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxPropertyManager; import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
@@ -18,82 +20,101 @@ import org.jmock.Expectations;
import org.junit.Test; import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getMessage; import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
public class MailboxPropertyValidatorTest extends BrambleMockTestCase { public class MailboxUpdateValidatorTest extends BrambleMockTestCase {
private final ClientHelper clientHelper = context.mock(ClientHelper.class); private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final BdfDictionary bdfDict; private final BdfDictionary bdfDict;
private final MailboxPropertiesUpdate mailboxProps; private final BdfList emptyServerSupports;
private final BdfList someClientSupports;
private final List<MailboxVersion> someClientSupportsList;
private final BdfList someServerSupports;
private final MailboxUpdateWithMailbox updateMailbox;
private final MailboxUpdate updateNoMailbox;
private final Group group; private final Group group;
private final Message message; private final Message message;
private final MailboxPropertyValidator mpv; private final MailboxUpdateValidator muv;
public MailboxPropertyValidatorTest() { public MailboxUpdateValidatorTest() {
// Just dummies, clientHelper is mocked so our test is a bit shallow; // Just dummies, clientHelper is mocked so our test is a bit shallow;
// not testing // not testing
// {@link ClientHelper#parseAndValidateMailboxPropertiesUpdate(BdfDictionary)} // {@link ClientHelper#parseAndValidateMailboxUpdate(BdfList, BdfList, BdfDictionary)}
emptyServerSupports = new BdfList();
someClientSupports = BdfList.of(BdfList.of(1, 0));
someClientSupportsList = singletonList(new MailboxVersion(1, 0));
someServerSupports = BdfList.of(BdfList.of(1, 0));
bdfDict = BdfDictionary.of(new BdfEntry("foo", "bar")); bdfDict = BdfDictionary.of(new BdfEntry("foo", "bar"));
mailboxProps = new MailboxPropertiesUpdate("baz",
updateMailbox = new MailboxUpdateWithMailbox(
singletonList(new MailboxVersion(1, 0)),
singletonList(new MailboxVersion(1, 0)),
"baz",
new MailboxAuthToken(getRandomId()), new MailboxAuthToken(getRandomId()),
new MailboxFolderId(getRandomId()), new MailboxFolderId(getRandomId()),
new MailboxFolderId(getRandomId())); new MailboxFolderId(getRandomId()));
updateNoMailbox = new MailboxUpdate(someClientSupportsList);
group = getGroup(MailboxPropertyManager.CLIENT_ID,
MailboxPropertyManager.MAJOR_VERSION); group = getGroup(MailboxUpdateManager.CLIENT_ID,
MailboxUpdateManager.MAJOR_VERSION);
message = getMessage(group.getId()); message = getMessage(group.getId());
MetadataEncoder metadataEncoder = context.mock(MetadataEncoder.class); MetadataEncoder metadataEncoder = context.mock(MetadataEncoder.class);
Clock clock = context.mock(Clock.class); Clock clock = context.mock(Clock.class);
mpv = new MailboxPropertyValidator(clientHelper, metadataEncoder, muv = new MailboxUpdateValidator(clientHelper, metadataEncoder,
clock); clock);
} }
@Test @Test
public void testValidateMessageBody() throws IOException { public void testValidateMessageBody() throws IOException {
BdfList body = BdfList.of(4, bdfDict); BdfList body =
BdfList.of(4, someClientSupports, someServerSupports, bdfDict);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientHelper).parseAndValidateMailboxPropertiesUpdate( oneOf(clientHelper).parseAndValidateMailboxUpdate(
bdfDict); someClientSupports, someServerSupports, bdfDict);
will(returnValue(mailboxProps)); will(returnValue(updateMailbox));
}}); }});
BdfDictionary result = BdfDictionary result =
mpv.validateMessage(message, group, body).getDictionary(); muv.validateMessage(message, group, body).getDictionary();
assertEquals(4, result.getLong("version").longValue()); assertEquals(4, result.getLong("version").longValue());
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateWrongVersionValue() throws IOException { public void testValidateWrongVersionValue() throws IOException {
BdfList body = BdfList.of(-1, bdfDict); BdfList body = BdfList.of(-1, bdfDict);
mpv.validateMessage(message, group, body); muv.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateWrongVersionType() throws IOException { public void testValidateWrongVersionType() throws IOException {
BdfList body = BdfList.of(bdfDict, bdfDict); BdfList body = BdfList.of(bdfDict, bdfDict);
mpv.validateMessage(message, group, body); muv.validateMessage(message, group, body);
} }
@Test @Test
public void testEmptyPropertiesReturnsNull() throws IOException { public void testEmptyProperties() throws IOException {
BdfDictionary emptyBdfDict = new BdfDictionary(); BdfDictionary emptyBdfDict = new BdfDictionary();
BdfList body = BdfList.of(42, emptyBdfDict); BdfList body = BdfList.of(42, someClientSupports, emptyServerSupports,
emptyBdfDict);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientHelper).parseAndValidateMailboxPropertiesUpdate( oneOf(clientHelper).parseAndValidateMailboxUpdate(
emptyBdfDict); someClientSupports, emptyServerSupports, emptyBdfDict);
will(returnValue(null)); will(returnValue(updateNoMailbox));
}}); }});
BdfDictionary result = BdfDictionary result =
mpv.validateMessage(message, group, body).getDictionary(); muv.validateMessage(message, group, body).getDictionary();
assertEquals(42, result.getLong("version").longValue()); assertEquals(42, result.getLong("version").longValue());
} }
} }

View File

@@ -345,11 +345,12 @@ public class TransportKeyAgreementIntegrationTest
.canSendOutgoingStreams(aliceId, DUPLEX_TRANSPORT_ID)); .canSendOutgoingStreams(aliceId, DUPLEX_TRANSPORT_ID));
} }
// Sync initial client versioning updates // Sync initial client versioning updates and mailbox updates
syncMessage(alice, bob, bobId, 1, true); syncMessage(alice, bob, bobId, 1, true);
syncMessage(bob, alice, aliceId, 1, true); syncMessage(bob, alice, aliceId, 1, true);
syncMessage(alice, bob, bobId, 1, true); syncMessage(alice, bob, bobId, 2, true);
sendAcks(bob, alice, aliceId, 1); syncMessage(bob, alice, aliceId, 1, true);
sendAcks(alice, bob, bobId, 1);
return new Pair<>(aliceId, bobId); return new Pair<>(aliceId, bobId);
} }

View File

@@ -1051,11 +1051,12 @@ public class IntroductionIntegrationTest
true); true);
contact0From1 = contactManager1.getContact(contactId0From1); contact0From1 = contactManager1.getContact(contactId0From1);
// Sync initial client versioning updates and transport properties // Sync initial client versioning updates, mailbox updates, and
// transport properties
sync0To1(1, true); sync0To1(1, true);
sync1To0(1, true); sync1To0(1, true);
sync0To1(2, true); sync0To1(3, true);
sync1To0(1, true); sync1To0(2, true);
// a new introduction should be possible // a new introduction should be possible
assertTrue(introductionManager0 assertTrue(introductionManager0

View File

@@ -172,16 +172,18 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
true); true);
contact0From2 = contactManager2.getContact(contactId0From2); contact0From2 = contactManager2.getContact(contactId0From2);
// Sync initial client versioning updates // Sync initial client versioning updates and mailbox updates
sync0To1(1, true); sync0To1(1, true);
sync1To0(1, true); sync1To0(1, true);
sync0To1(1, true); sync0To1(2, true);
ack1To0(1); sync1To0(1, true);
ack0To1(1);
sync0To2(1, true); sync0To2(1, true);
sync2To0(1, true); sync2To0(1, true);
sync0To2(1, true); sync0To2(2, true);
ack2To0(1); sync2To0(1, true);
ack0To2(1);
} }
protected void addContacts1And2() throws Exception { protected void addContacts1And2() throws Exception {
@@ -200,13 +202,16 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
// Sync initial client versioning updates // Sync initial client versioning updates
sync1To2(1, true); sync1To2(1, true);
sync2To1(1, true); sync2To1(1, true);
// Sync 2nd client versioning msg from 1to2, mailbox updates, and
// transport properties if we should
if (haveTransportProperties) { if (haveTransportProperties) {
sync1To2(3, true);
sync2To1(2, true);
ack1To2(2);
} else {
sync1To2(2, true); sync1To2(2, true);
sync2To1(1, true); sync2To1(1, true);
ack1To2(1); ack1To2(1);
} else {
sync1To2(1, true);
ack2To1(1);
} }
} }