diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxConstants.java index 51d7f0a7c..6a2ede3ef 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxConstants.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxConstants.java @@ -15,6 +15,12 @@ public interface MailboxConstants { */ TransportId ID = new TransportId("org.briarproject.bramble.mailbox"); + /** + * The highest major version of the mailbox server + * that this client supports. + */ + int MAILBOX_VERSION_MAJOR = 1; + /** * The maximum length of a file that can be uploaded to or downloaded from * a mailbox. diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxStatus.java b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxStatus.java index bbf60cdba..2e517d002 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxStatus.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxStatus.java @@ -2,8 +2,11 @@ package org.briarproject.bramble.api.mailbox; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import java.util.List; + import javax.annotation.concurrent.Immutable; +import static org.briarproject.bramble.api.mailbox.MailboxConstants.MAILBOX_VERSION_MAJOR; import static org.briarproject.bramble.api.mailbox.MailboxConstants.PROBLEM_MS_SINCE_LAST_SUCCESS; import static org.briarproject.bramble.api.mailbox.MailboxConstants.PROBLEM_NUM_CONNECTION_FAILURES; @@ -13,12 +16,15 @@ public class MailboxStatus { private final long lastAttempt, lastSuccess; private final int attemptsSinceSuccess; + private final List serverSupports; public MailboxStatus(long lastAttempt, long lastSuccess, - int attemptsSinceSuccess) { + int attemptsSinceSuccess, + List serverSupports) { this.lastAttempt = lastAttempt; this.lastSuccess = lastSuccess; this.attemptsSinceSuccess = attemptsSinceSuccess; + this.serverSupports = serverSupports; } /** @@ -67,4 +73,16 @@ public class MailboxStatus { return attemptsSinceSuccess >= PROBLEM_NUM_CONNECTION_FAILURES && (now - lastSuccess) >= PROBLEM_MS_SINCE_LAST_SUCCESS; } + + /** + * @return true if the Mailbox is incompatible with this version of Briar, + * so that the mailbox needs to be updated. + */ + public boolean isMailboxIncompatible() { + for (MailboxVersion version : serverSupports) { + if (version.getMajor() <= MAILBOX_VERSION_MAJOR) return false; + } + return true; + } + } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSettingsManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSettingsManagerImpl.java index 9f05e2be7..23f9ca486 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSettingsManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxSettingsManagerImpl.java @@ -23,6 +23,7 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import static java.util.Collections.emptyList; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; @Immutable @@ -60,15 +61,7 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager { String onion = s.get(SETTINGS_KEY_ONION); String token = s.get(SETTINGS_KEY_TOKEN); if (isNullOrEmpty(onion) || isNullOrEmpty(token)) return null; - int[] ints = s.getIntArray(SETTINGS_KEY_SERVER_SUPPORTS); - // We know we were paired, so we must have proper serverSupports - if (ints == null || ints.length == 0 || ints.length % 2 != 0) { - throw new DbException(); - } - List serverSupports = new ArrayList<>(); - for (int i = 0; i < ints.length - 1; i += 2) { - serverSupports.add(new MailboxVersion(ints[i], ints[i + 1])); - } + List serverSupports = parseServerSupports(s); try { MailboxAuthToken tokenId = MailboxAuthToken.fromString(token); return new MailboxProperties(onion, tokenId, serverSupports); @@ -115,18 +108,28 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager { long lastAttempt = s.getLong(SETTINGS_KEY_LAST_ATTEMPT, -1); long lastSuccess = s.getLong(SETTINGS_KEY_LAST_SUCCESS, -1); int attempts = s.getInt(SETTINGS_KEY_ATTEMPTS, 0); - return new MailboxStatus(lastAttempt, lastSuccess, attempts); + List serverSupports; + try { + serverSupports = parseServerSupports(s); + } catch (DbException e) { + serverSupports = emptyList(); + } + return new MailboxStatus(lastAttempt, lastSuccess, attempts, + serverSupports); } @Override public void recordSuccessfulConnection(Transaction txn, long now) throws DbException { + Settings oldSettings = + settingsManager.getSettings(txn, SETTINGS_NAMESPACE); Settings s = new Settings(); s.putLong(SETTINGS_KEY_LAST_ATTEMPT, now); s.putLong(SETTINGS_KEY_LAST_SUCCESS, now); s.putInt(SETTINGS_KEY_ATTEMPTS, 0); settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE); - MailboxStatus status = new MailboxStatus(now, now, 0); + List serverSupports = parseServerSupports(oldSettings); + MailboxStatus status = new MailboxStatus(now, now, 0, serverSupports); txn.attach(new OwnMailboxConnectionStatusEvent(status)); } @@ -141,7 +144,9 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager { newSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now); newSettings.putInt(SETTINGS_KEY_ATTEMPTS, newAttempts); settingsManager.mergeSettings(txn, newSettings, SETTINGS_NAMESPACE); - MailboxStatus status = new MailboxStatus(now, lastSuccess, newAttempts); + List serverSupports = parseServerSupports(oldSettings); + MailboxStatus status = new MailboxStatus(now, lastSuccess, newAttempts, + serverSupports); txn.attach(new OwnMailboxConnectionStatusEvent(status)); if (status.hasProblem(now)) txn.attach(new MailboxProblemEvent()); } @@ -165,4 +170,19 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager { if (isNullOrEmpty(filename)) return null; return filename; } + + private List parseServerSupports(Settings s) + throws DbException { + if (!s.containsKey(SETTINGS_KEY_SERVER_SUPPORTS)) return emptyList(); + int[] ints = s.getIntArray(SETTINGS_KEY_SERVER_SUPPORTS); + // We know we were paired, so we must have proper serverSupports + if (ints == null || ints.length == 0 || ints.length % 2 != 0) { + throw new DbException(); + } + List serverSupports = new ArrayList<>(); + for (int i = 0; i < ints.length - 1; i += 2) { + serverSupports.add(new MailboxVersion(ints[i], ints[i + 1])); + } + return serverSupports; + } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxSettingsManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxSettingsManagerImplTest.java index 78bb64faf..17a9330b6 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxSettingsManagerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxSettingsManagerImplTest.java @@ -146,12 +146,17 @@ public class MailboxSettingsManagerImplTest extends BrambleMockTestCase { @Test public void testRecordsSuccess() throws Exception { Transaction txn = new Transaction(null, false); + Settings oldSettings = new Settings(); + oldSettings + .putIntArray(SETTINGS_KEY_SERVER_SUPPORTS, serverSupportsInts); Settings expectedSettings = new Settings(); expectedSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now); expectedSettings.putLong(SETTINGS_KEY_LAST_SUCCESS, now); expectedSettings.putInt(SETTINGS_KEY_ATTEMPTS, 0); context.checking(new Expectations() {{ + oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE); + will(returnValue(oldSettings)); oneOf(settingsManager).mergeSettings(txn, expectedSettings, SETTINGS_NAMESPACE); }});