mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 13:19:52 +01:00
Mirror the remote auto-delete timer.
This commit is contained in:
@@ -328,7 +328,8 @@ public class ConversationViewModel extends DbViewModel
|
|||||||
return privateMessageFactory.createPrivateMessage(groupId,
|
return privateMessageFactory.createPrivateMessage(groupId,
|
||||||
timestamp, text, headers);
|
timestamp, text, headers);
|
||||||
} else {
|
} else {
|
||||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||||
|
timestamp);
|
||||||
return privateMessageFactory.createPrivateMessage(groupId,
|
return privateMessageFactory.createPrivateMessage(groupId,
|
||||||
timestamp, text, headers, timer);
|
timestamp, text, headers, timer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,7 +173,8 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
|||||||
Contact contact = contactManager.getContact(txn, c);
|
Contact contact = contactManager.getContact(txn, c);
|
||||||
long timestamp = conversationManager
|
long timestamp = conversationManager
|
||||||
.getTimestampForOutgoingMessage(txn, c);
|
.getTimestampForOutgoingMessage(txn, c);
|
||||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||||
|
timestamp);
|
||||||
contexts.add(new InvitationContext(contact, timestamp, timer));
|
contexts.add(new InvitationContext(contact, timestamp, timer));
|
||||||
} catch (NoSuchContactException e) {
|
} catch (NoSuchContactException e) {
|
||||||
// Continue
|
// Continue
|
||||||
|
|||||||
@@ -24,8 +24,26 @@ public interface AutoDeleteManager {
|
|||||||
*/
|
*/
|
||||||
int MINOR_VERSION = 0;
|
int MINOR_VERSION = 0;
|
||||||
|
|
||||||
long getAutoDeleteTimer(Transaction txn, ContactId c) throws DbException;
|
/**
|
||||||
|
* Returns the auto-delete timer duration for the given contact, for use in
|
||||||
|
* a message with the given timestamp. The timestamp is stored.
|
||||||
|
*/
|
||||||
|
long getAutoDeleteTimer(Transaction txn, ContactId c, long timestamp)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the auto-delete timer duration for the given contact.
|
||||||
|
*/
|
||||||
void setAutoDeleteTimer(Transaction txn, ContactId c, long timer)
|
void setAutoDeleteTimer(Transaction txn, ContactId c, long timer)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives an auto-delete timer duration from the given contact, carried
|
||||||
|
* in a message with the given timestamp. The local timer is set to the
|
||||||
|
* same duration unless it has been
|
||||||
|
* {@link #setAutoDeleteTimer(Transaction, ContactId, long) changed} more
|
||||||
|
* recently than the remote timer.
|
||||||
|
*/
|
||||||
|
void receiveAutoDeleteTimer(Transaction txn, ContactId c, long timer,
|
||||||
|
long timestamp) throws DbException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,28 @@ package org.briarproject.briar.autodelete;
|
|||||||
|
|
||||||
interface AutoDeleteConstants {
|
interface AutoDeleteConstants {
|
||||||
|
|
||||||
// Group metadata key for storing the auto-delete timer
|
/**
|
||||||
String GROUP_KEY_AUTO_DELETE_TIMER = "autoDeleteTimer";
|
* Group metadata key for storing the auto-delete timer duration.
|
||||||
|
*/
|
||||||
|
String GROUP_KEY_TIMER = "autoDeleteTimer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group metadata key for storing the timestamp of the latest incoming or
|
||||||
|
* outgoing message carrying an auto-delete timer (including a null timer).
|
||||||
|
*/
|
||||||
|
String GROUP_KEY_TIMESTAMP = "autoDeleteTimestamp";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group metadata key for storing the previous auto-delete timer duration.
|
||||||
|
* This is used to decide whether a local change to the duration should be
|
||||||
|
* overwritten by a duration received from the contact.
|
||||||
|
*/
|
||||||
|
String GROUP_KEY_PREVIOUS_TIMER = "autoDeletePreviousTimer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special value for {@link #GROUP_KEY_PREVIOUS_TIMER} indicating that
|
||||||
|
* there are no local changes to the auto-delete timer duration that need
|
||||||
|
* to be compared with durations received from the contact.
|
||||||
|
*/
|
||||||
|
long NO_PREVIOUS_TIMER = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,19 +17,29 @@ import org.briarproject.bramble.api.sync.Group;
|
|||||||
import org.briarproject.bramble.api.sync.GroupFactory;
|
import org.briarproject.bramble.api.sync.GroupFactory;
|
||||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||||
|
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS;
|
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS;
|
||||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS;
|
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS;
|
||||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_AUTO_DELETE_TIMER;
|
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_PREVIOUS_TIMER;
|
||||||
|
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_TIMER;
|
||||||
|
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_TIMESTAMP;
|
||||||
|
import static org.briarproject.briar.autodelete.AutoDeleteConstants.NO_PREVIOUS_TIMER;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class AutoDeleteManagerImpl
|
class AutoDeleteManagerImpl
|
||||||
implements AutoDeleteManager, OpenDatabaseHook, ContactHook {
|
implements AutoDeleteManager, OpenDatabaseHook, ContactHook {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
getLogger(AutoDeleteManagerImpl.class.getName());
|
||||||
|
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
private final ClientHelper clientHelper;
|
private final ClientHelper clientHelper;
|
||||||
private final GroupFactory groupFactory;
|
private final GroupFactory groupFactory;
|
||||||
@@ -69,14 +79,22 @@ class AutoDeleteManagerImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getAutoDeleteTimer(Transaction txn, ContactId c)
|
public long getAutoDeleteTimer(Transaction txn, ContactId c, long timestamp)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
try {
|
try {
|
||||||
Group g = getGroup(db.getContact(txn, c));
|
Group g = getGroup(db.getContact(txn, c));
|
||||||
BdfDictionary meta =
|
BdfDictionary meta =
|
||||||
clientHelper.getGroupMetadataAsDictionary(txn, g.getId());
|
clientHelper.getGroupMetadataAsDictionary(txn, g.getId());
|
||||||
return meta.getLong(GROUP_KEY_AUTO_DELETE_TIMER,
|
long timer = meta.getLong(GROUP_KEY_TIMER, NO_AUTO_DELETE_TIMER);
|
||||||
NO_AUTO_DELETE_TIMER);
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Sending message with auto-delete timer " + timer);
|
||||||
|
}
|
||||||
|
// Update the timestamp and clear the previous timer, if any
|
||||||
|
meta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, timestamp),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER));
|
||||||
|
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
|
||||||
|
return timer;
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
@@ -85,18 +103,60 @@ class AutoDeleteManagerImpl
|
|||||||
@Override
|
@Override
|
||||||
public void setAutoDeleteTimer(Transaction txn, ContactId c, long timer)
|
public void setAutoDeleteTimer(Transaction txn, ContactId c, long timer)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
if (timer != NO_AUTO_DELETE_TIMER &&
|
validateTimer(timer);
|
||||||
(timer < MIN_AUTO_DELETE_TIMER_MS ||
|
|
||||||
timer > MAX_AUTO_DELETE_TIMER_MS)) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
Group g = getGroup(db.getContact(txn, c));
|
Group g = getGroup(db.getContact(txn, c));
|
||||||
BdfDictionary meta = BdfDictionary.of(
|
BdfDictionary meta =
|
||||||
new BdfEntry(GROUP_KEY_AUTO_DELETE_TIMER, timer));
|
clientHelper.getGroupMetadataAsDictionary(txn, g.getId());
|
||||||
|
long oldTimer = meta.getLong(GROUP_KEY_TIMER, NO_AUTO_DELETE_TIMER);
|
||||||
|
if (timer == oldTimer) return;
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Setting auto-delete timer to " + timer);
|
||||||
|
}
|
||||||
|
// Store the new timer and the previous timer
|
||||||
|
meta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, timer),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, oldTimer));
|
||||||
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
|
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new AssertionError(e);
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveAutoDeleteTimer(Transaction txn, ContactId c,
|
||||||
|
long timer, long timestamp) throws DbException {
|
||||||
|
validateTimer(timer);
|
||||||
|
try {
|
||||||
|
Group g = getGroup(db.getContact(txn, c));
|
||||||
|
BdfDictionary meta =
|
||||||
|
clientHelper.getGroupMetadataAsDictionary(txn, g.getId());
|
||||||
|
long oldTimestamp = meta.getLong(GROUP_KEY_TIMESTAMP, 0L);
|
||||||
|
if (timestamp <= oldTimestamp) return;
|
||||||
|
long oldTimer =
|
||||||
|
meta.getLong(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER);
|
||||||
|
meta = new BdfDictionary();
|
||||||
|
if (oldTimer == NO_PREVIOUS_TIMER) {
|
||||||
|
// We don't have an unsent change. Mirror their timer
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Mirroring auto-delete timer " + timer);
|
||||||
|
}
|
||||||
|
meta.put(GROUP_KEY_TIMER, timer);
|
||||||
|
} else if (timer != oldTimer) {
|
||||||
|
// Their sent change trumps our unsent change. Mirror their
|
||||||
|
// timer and clear the previous timer to drop our unsent change
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Mirroring auto-delete timer " + timer
|
||||||
|
+ " and forgetting unsent change");
|
||||||
|
}
|
||||||
|
meta.put(GROUP_KEY_TIMER, timer);
|
||||||
|
meta.put(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER);
|
||||||
|
}
|
||||||
|
// Always update the timestamp
|
||||||
|
meta.put(GROUP_KEY_TIMESTAMP, timestamp);
|
||||||
|
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
|
||||||
|
} catch (FormatException e) {
|
||||||
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,4 +164,12 @@ class AutoDeleteManagerImpl
|
|||||||
byte[] descriptor = c.getAuthor().getId().getBytes();
|
byte[] descriptor = c.getAuthor().getId().getBytes();
|
||||||
return groupFactory.createGroup(CLIENT_ID, MAJOR_VERSION, descriptor);
|
return groupFactory.createGroup(CLIENT_ID, MAJOR_VERSION, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateTimer(long timer) {
|
||||||
|
if (timer != NO_AUTO_DELETE_TIMER &&
|
||||||
|
(timer < MIN_AUTO_DELETE_TIMER_MS ||
|
||||||
|
timer > MAX_AUTO_DELETE_TIMER_MS)) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
|||||||
Message m;
|
Message m;
|
||||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||||
if (contactSupportsAutoDeletion(txn, c)) {
|
if (contactSupportsAutoDeletion(txn, c)) {
|
||||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||||
|
timestamp);
|
||||||
m = messageEncoder.encodeRequestMessage(s.getContactGroupId(),
|
m = messageEncoder.encodeRequestMessage(s.getContactGroupId(),
|
||||||
timestamp, s.getLastLocalMessageId(), author, text, timer);
|
timestamp, s.getLastLocalMessageId(), author, text, timer);
|
||||||
sendMessage(txn, REQUEST, s.getSessionId(), m, true, timer);
|
sendMessage(txn, REQUEST, s.getSessionId(), m, true, timer);
|
||||||
@@ -120,7 +121,8 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
|||||||
Message m;
|
Message m;
|
||||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||||
if (contactSupportsAutoDeletion(txn, c)) {
|
if (contactSupportsAutoDeletion(txn, c)) {
|
||||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||||
|
timestamp);
|
||||||
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
||||||
timestamp, s.getLastLocalMessageId(), s.getSessionId(),
|
timestamp, s.getLastLocalMessageId(), s.getSessionId(),
|
||||||
ephemeralPublicKey, acceptTimestamp, transportProperties,
|
ephemeralPublicKey, acceptTimestamp, transportProperties,
|
||||||
@@ -141,7 +143,8 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
|||||||
Message m;
|
Message m;
|
||||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||||
if (contactSupportsAutoDeletion(txn, c)) {
|
if (contactSupportsAutoDeletion(txn, c)) {
|
||||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||||
|
timestamp);
|
||||||
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
||||||
timestamp, s.getLastLocalMessageId(), s.getSessionId(),
|
timestamp, s.getLastLocalMessageId(), s.getSessionId(),
|
||||||
timer);
|
timer);
|
||||||
|
|||||||
@@ -152,9 +152,11 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
|||||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||||
if (contactSupportsAutoDeletion(txn, c)) {
|
if (contactSupportsAutoDeletion(txn, c)) {
|
||||||
// Set auto-delete timer if manually accepting an invitation
|
// Set auto-delete timer if manually accepting an invitation
|
||||||
long timer = visibleInUi
|
long timer = NO_AUTO_DELETE_TIMER;
|
||||||
? autoDeleteManager.getAutoDeleteTimer(txn, c)
|
if (visibleInUi) {
|
||||||
: NO_AUTO_DELETE_TIMER;
|
timer = autoDeleteManager
|
||||||
|
.getAutoDeleteTimer(txn, c, localTimestamp);
|
||||||
|
}
|
||||||
m = messageEncoder.encodeJoinMessage(s.getContactGroupId(),
|
m = messageEncoder.encodeJoinMessage(s.getContactGroupId(),
|
||||||
s.getPrivateGroupId(), localTimestamp,
|
s.getPrivateGroupId(), localTimestamp,
|
||||||
s.getLastLocalMessageId(), timer);
|
s.getLastLocalMessageId(), timer);
|
||||||
@@ -179,9 +181,11 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
|||||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||||
if (contactSupportsAutoDeletion(txn, c)) {
|
if (contactSupportsAutoDeletion(txn, c)) {
|
||||||
// Set auto-delete timer if manually accepting an invitation
|
// Set auto-delete timer if manually accepting an invitation
|
||||||
long timer = visibleInUi
|
long timer = NO_AUTO_DELETE_TIMER;
|
||||||
? autoDeleteManager.getAutoDeleteTimer(txn, c)
|
if (visibleInUi) {
|
||||||
: NO_AUTO_DELETE_TIMER;
|
timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||||
|
localTimestamp);
|
||||||
|
}
|
||||||
m = messageEncoder.encodeLeaveMessage(s.getContactGroupId(),
|
m = messageEncoder.encodeLeaveMessage(s.getContactGroupId(),
|
||||||
s.getPrivateGroupId(), localTimestamp,
|
s.getPrivateGroupId(), localTimestamp,
|
||||||
s.getLastLocalMessageId(), timer);
|
s.getLastLocalMessageId(), timer);
|
||||||
|
|||||||
@@ -142,7 +142,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
|||||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||||
if (contactSupportsAutoDeletion(txn, c)) {
|
if (contactSupportsAutoDeletion(txn, c)) {
|
||||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||||
|
localTimestamp);
|
||||||
m = messageEncoder.encodeInviteMessage(s.getContactGroupId(),
|
m = messageEncoder.encodeInviteMessage(s.getContactGroupId(),
|
||||||
localTimestamp, s.getLastLocalMessageId(), descriptor,
|
localTimestamp, s.getLastLocalMessageId(), descriptor,
|
||||||
text, timer);
|
text, timer);
|
||||||
@@ -209,7 +210,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
|||||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||||
if (contactSupportsAutoDeletion(txn, c)) {
|
if (contactSupportsAutoDeletion(txn, c)) {
|
||||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||||
|
localTimestamp);
|
||||||
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
||||||
s.getShareableId(), localTimestamp,
|
s.getShareableId(), localTimestamp,
|
||||||
s.getLastLocalMessageId(), timer);
|
s.getLastLocalMessageId(), timer);
|
||||||
@@ -263,7 +265,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
|||||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||||
if (contactSupportsAutoDeletion(txn, c)) {
|
if (contactSupportsAutoDeletion(txn, c)) {
|
||||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c,
|
||||||
|
localTimestamp);
|
||||||
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
||||||
s.getShareableId(), localTimestamp,
|
s.getShareableId(), localTimestamp,
|
||||||
s.getLastLocalMessageId(), timer);
|
s.getLastLocalMessageId(), timer);
|
||||||
|
|||||||
@@ -18,12 +18,18 @@ import static org.briarproject.bramble.api.client.ContactGroupConstants.GROUP_KE
|
|||||||
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.briar.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS;
|
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS;
|
||||||
|
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS;
|
||||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||||
import static org.briarproject.briar.api.autodelete.AutoDeleteManager.CLIENT_ID;
|
import static org.briarproject.briar.api.autodelete.AutoDeleteManager.CLIENT_ID;
|
||||||
import static org.briarproject.briar.api.autodelete.AutoDeleteManager.MAJOR_VERSION;
|
import static org.briarproject.briar.api.autodelete.AutoDeleteManager.MAJOR_VERSION;
|
||||||
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_AUTO_DELETE_TIMER;
|
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_PREVIOUS_TIMER;
|
||||||
|
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_TIMER;
|
||||||
|
import static org.briarproject.briar.autodelete.AutoDeleteConstants.GROUP_KEY_TIMESTAMP;
|
||||||
|
import static org.briarproject.briar.autodelete.AutoDeleteConstants.NO_PREVIOUS_TIMER;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
// Thank you, I'm using them for readability
|
||||||
|
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||||
public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||||
@@ -35,6 +41,7 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
|||||||
private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||||
private final Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
private final Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||||
private final Contact contact = getContact();
|
private final Contact contact = getContact();
|
||||||
|
private final long now = System.currentTimeMillis();
|
||||||
|
|
||||||
private final AutoDeleteManagerImpl autoDeleteManager;
|
private final AutoDeleteManagerImpl autoDeleteManager;
|
||||||
|
|
||||||
@@ -113,15 +120,44 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testStoresTimer() throws Exception {
|
public void testStoresTimer() throws Exception {
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
long timer = MAX_AUTO_DELETE_TIMER_MS;
|
long oldTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||||
BdfDictionary meta = BdfDictionary.of(
|
long newTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||||
new BdfEntry(GROUP_KEY_AUTO_DELETE_TIMER, timer));
|
BdfDictionary oldMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, oldTimer),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER),
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||||
|
BdfDictionary newMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, newTimer),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, oldTimer));
|
||||||
|
|
||||||
expectGetContact(txn);
|
expectGetContact(txn);
|
||||||
expectGetContactGroup();
|
expectGetContactGroup();
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
contactGroup.getId());
|
||||||
|
will(returnValue(oldMeta));
|
||||||
oneOf(clientHelper).mergeGroupMetadata(txn,
|
oneOf(clientHelper).mergeGroupMetadata(txn,
|
||||||
contactGroup.getId(), meta);
|
contactGroup.getId(), newMeta);
|
||||||
|
}});
|
||||||
|
|
||||||
|
autoDeleteManager.setAutoDeleteTimer(txn, contact.getId(), newTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesNotStoreTimerIfUnchanged() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
long timer = MAX_AUTO_DELETE_TIMER_MS;
|
||||||
|
BdfDictionary meta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, timer),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER),
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||||
|
|
||||||
|
expectGetContact(txn);
|
||||||
|
expectGetContactGroup();
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
contactGroup.getId());
|
||||||
|
will(returnValue(meta));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
autoDeleteManager.setAutoDeleteTimer(txn, contact.getId(), timer);
|
autoDeleteManager.setAutoDeleteTimer(txn, contact.getId(), timer);
|
||||||
@@ -133,7 +169,10 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
|||||||
long timer = MAX_AUTO_DELETE_TIMER_MS;
|
long timer = MAX_AUTO_DELETE_TIMER_MS;
|
||||||
BdfDictionary meta = BdfDictionary.of(
|
BdfDictionary meta = BdfDictionary.of(
|
||||||
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()),
|
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()),
|
||||||
new BdfEntry(GROUP_KEY_AUTO_DELETE_TIMER, timer));
|
new BdfEntry(GROUP_KEY_TIMER, timer));
|
||||||
|
BdfDictionary newMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, now),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER));
|
||||||
|
|
||||||
expectGetContact(txn);
|
expectGetContact(txn);
|
||||||
expectGetContactGroup();
|
expectGetContactGroup();
|
||||||
@@ -141,10 +180,12 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
contactGroup.getId());
|
contactGroup.getId());
|
||||||
will(returnValue(meta));
|
will(returnValue(meta));
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(txn, contactGroup.getId(),
|
||||||
|
newMeta);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(timer,
|
assertEquals(timer, autoDeleteManager
|
||||||
autoDeleteManager.getAutoDeleteTimer(txn, contact.getId()));
|
.getAutoDeleteTimer(txn, contact.getId(), now));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -152,6 +193,44 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
|||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
BdfDictionary meta = BdfDictionary.of(
|
BdfDictionary meta = BdfDictionary.of(
|
||||||
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()));
|
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()));
|
||||||
|
BdfDictionary newMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, now),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER));
|
||||||
|
|
||||||
|
expectGetContact(txn);
|
||||||
|
expectGetContactGroup();
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
contactGroup.getId());
|
||||||
|
will(returnValue(meta));
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(txn, contactGroup.getId(),
|
||||||
|
newMeta);
|
||||||
|
}});
|
||||||
|
|
||||||
|
assertEquals(NO_AUTO_DELETE_TIMER, autoDeleteManager
|
||||||
|
.getAutoDeleteTimer(txn, contact.getId(), now));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIgnoresReceivedTimerWithEarlierTimestamp()
|
||||||
|
throws Exception {
|
||||||
|
testIgnoresReceivedTimerWithTimestamp(now - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIgnoresReceivedTimerWithEqualTimestamp() throws Exception {
|
||||||
|
testIgnoresReceivedTimerWithTimestamp(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testIgnoresReceivedTimerWithTimestamp(long remoteTimestamp)
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
long localTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||||
|
long remoteTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||||
|
BdfDictionary meta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, localTimer),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER),
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||||
|
|
||||||
expectGetContact(txn);
|
expectGetContact(txn);
|
||||||
expectGetContactGroup();
|
expectGetContactGroup();
|
||||||
@@ -161,8 +240,99 @@ public class AutoDeleteManagerImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(meta));
|
will(returnValue(meta));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(NO_AUTO_DELETE_TIMER,
|
autoDeleteManager.receiveAutoDeleteTimer(txn, contact.getId(),
|
||||||
autoDeleteManager.getAutoDeleteTimer(txn, contact.getId()));
|
remoteTimer, remoteTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMirrorsRemoteTimestampIfNoUnsentChange() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
long localTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||||
|
long remoteTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||||
|
long remoteTimestamp = now + 1;
|
||||||
|
BdfDictionary oldMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, localTimer),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER),
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||||
|
// The timestamp should be updated and the timer should be mirrored
|
||||||
|
BdfDictionary newMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, remoteTimestamp),
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, remoteTimer));
|
||||||
|
|
||||||
|
expectGetContact(txn);
|
||||||
|
expectGetContactGroup();
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
contactGroup.getId());
|
||||||
|
will(returnValue(oldMeta));
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(txn,
|
||||||
|
contactGroup.getId(), newMeta);
|
||||||
|
}});
|
||||||
|
|
||||||
|
autoDeleteManager.receiveAutoDeleteTimer(txn, contact.getId(),
|
||||||
|
remoteTimer, remoteTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesNotMirrorUnchangedRemoteTimestampIfUnsentChange()
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
long localTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||||
|
long remoteTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||||
|
long remoteTimestamp = now + 1;
|
||||||
|
BdfDictionary oldMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, localTimer),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, remoteTimer),
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||||
|
// The timestamp should be updated but the timer should not revert
|
||||||
|
BdfDictionary newMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, remoteTimestamp));
|
||||||
|
|
||||||
|
expectGetContact(txn);
|
||||||
|
expectGetContactGroup();
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
contactGroup.getId());
|
||||||
|
will(returnValue(oldMeta));
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(txn,
|
||||||
|
contactGroup.getId(), newMeta);
|
||||||
|
}});
|
||||||
|
|
||||||
|
autoDeleteManager.receiveAutoDeleteTimer(txn, contact.getId(),
|
||||||
|
remoteTimer, remoteTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMirrorsChangedRemoteTimestampIfUnsentChange()
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
long localTimer = MIN_AUTO_DELETE_TIMER_MS;
|
||||||
|
long oldRemoteTimer = MAX_AUTO_DELETE_TIMER_MS;
|
||||||
|
long newRemoteTimer = MAX_AUTO_DELETE_TIMER_MS - 1;
|
||||||
|
long remoteTimestamp = now + 1;
|
||||||
|
BdfDictionary oldMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, localTimer),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, oldRemoteTimer),
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, now));
|
||||||
|
// The timestamp should be updated , the timer should be mirrored and
|
||||||
|
// the previous timer should be cleared
|
||||||
|
BdfDictionary newMeta = BdfDictionary.of(
|
||||||
|
new BdfEntry(GROUP_KEY_TIMESTAMP, remoteTimestamp),
|
||||||
|
new BdfEntry(GROUP_KEY_TIMER, newRemoteTimer),
|
||||||
|
new BdfEntry(GROUP_KEY_PREVIOUS_TIMER, NO_PREVIOUS_TIMER));
|
||||||
|
|
||||||
|
expectGetContact(txn);
|
||||||
|
expectGetContactGroup();
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
|
||||||
|
contactGroup.getId());
|
||||||
|
will(returnValue(oldMeta));
|
||||||
|
oneOf(clientHelper).mergeGroupMetadata(txn,
|
||||||
|
contactGroup.getId(), newMeta);
|
||||||
|
}});
|
||||||
|
|
||||||
|
autoDeleteManager.receiveAutoDeleteTimer(txn, contact.getId(),
|
||||||
|
newRemoteTimer, remoteTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expectGetContact(Transaction txn) throws Exception {
|
private void expectGetContact(Transaction txn) throws Exception {
|
||||||
|
|||||||
@@ -256,7 +256,8 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
void expectGetAutoDeleteTimer() throws Exception {
|
void expectGetAutoDeleteTimer() throws Exception {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId);
|
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId,
|
||||||
|
localTimestamp);
|
||||||
will(returnValue(NO_AUTO_DELETE_TIMER));
|
will(returnValue(NO_AUTO_DELETE_TIMER));
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user