From 3a11cb32c4b1ad34bb9e64bdd2468b4c3bcec91d Mon Sep 17 00:00:00 2001 From: akwizgran Date: Mon, 23 Nov 2020 15:42:39 +0000 Subject: [PATCH] Update private group invitation client to include self-destruct timers. --- .../invitation/GroupInvitationManager.java | 2 +- .../invitation/GroupInvitationRequest.java | 7 +- .../invitation/GroupInvitationResponse.java | 7 +- .../invitation/AbstractProtocolEngine.java | 110 +++++++++++++----- .../invitation/CreatorProtocolEngine.java | 4 +- .../DeletableGroupInvitationMessage.java | 24 ++++ .../invitation/GroupInvitationConstants.java | 1 + .../GroupInvitationManagerImpl.java | 29 ++--- .../invitation/GroupInvitationValidator.java | 46 ++++++-- .../invitation/InviteMessage.java | 6 +- .../invitation/InviteeProtocolEngine.java | 2 +- .../privategroup/invitation/JoinMessage.java | 7 +- .../privategroup/invitation/LeaveMessage.java | 7 +- .../invitation/MessageEncoder.java | 35 +++++- .../invitation/MessageEncoderImpl.java | 83 ++++++++++--- .../invitation/MessageMetadata.java | 8 +- .../invitation/MessageParserImpl.java | 39 +++++-- .../AbstractProtocolEngineTest.java | 58 ++++++--- .../invitation/CreatorProtocolEngineTest.java | 14 ++- .../GroupInvitationManagerImplTest.java | 29 ++--- .../GroupInvitationValidatorTest.java | 18 ++- .../invitation/InviteeProtocolEngineTest.java | 23 ++-- .../invitation/PeerProtocolEngineTest.java | 100 +++++++++------- 23 files changed, 460 insertions(+), 199 deletions(-) create mode 100644 briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/DeletableGroupInvitationMessage.java diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java index b9f44e2bc..023d5b172 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationManager.java @@ -32,7 +32,7 @@ public interface GroupInvitationManager extends ConversationClient { /** * The current minor version of the private group invitation client. */ - int MINOR_VERSION = 0; + int MINOR_VERSION = 1; /** * Sends an invitation to share the given private group with the given diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationRequest.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationRequest.java index 6f6abb93b..0282145f2 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationRequest.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationRequest.java @@ -11,8 +11,6 @@ import org.briarproject.briar.api.sharing.InvitationRequest; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; -import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; - @Immutable @NotNullByDefault public class GroupInvitationRequest extends InvitationRequest { @@ -20,9 +18,10 @@ public class GroupInvitationRequest extends InvitationRequest { public GroupInvitationRequest(MessageId id, GroupId groupId, long time, boolean local, boolean read, boolean sent, boolean seen, SessionId sessionId, PrivateGroup shareable, - @Nullable String text, boolean available, boolean canBeOpened) { + @Nullable String text, boolean available, boolean canBeOpened, + long autoDeleteTimer) { super(id, groupId, time, local, read, sent, seen, sessionId, shareable, - text, available, canBeOpened, NO_AUTO_DELETE_TIMER); + text, available, canBeOpened, autoDeleteTimer); } @Override diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java index 0c6b79e34..b461d9dc1 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/invitation/GroupInvitationResponse.java @@ -9,17 +9,16 @@ import org.briarproject.briar.api.sharing.InvitationResponse; import javax.annotation.concurrent.Immutable; -import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; - @Immutable @NotNullByDefault public class GroupInvitationResponse extends InvitationResponse { public GroupInvitationResponse(MessageId id, GroupId groupId, long time, boolean local, boolean read, boolean sent, boolean seen, - SessionId sessionId, boolean accept, GroupId shareableId) { + SessionId sessionId, boolean accept, GroupId shareableId, + long autoDeleteTimer) { super(id, groupId, time, local, read, sent, seen, sessionId, - accept, shareableId, NO_AUTO_DELETE_TIMER); + accept, shareableId, autoDeleteTimer); } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java index 3e5a9842a..44165dcf4 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java @@ -23,14 +23,14 @@ import org.briarproject.briar.api.privategroup.GroupMessageFactory; import org.briarproject.briar.api.privategroup.PrivateGroup; import org.briarproject.briar.api.privategroup.PrivateGroupFactory; import org.briarproject.briar.api.privategroup.PrivateGroupManager; +import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; import java.util.Map; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; -import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID; -import static org.briarproject.briar.api.privategroup.PrivateGroupManager.MAJOR_VERSION; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID; import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT; import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE; @@ -39,7 +39,7 @@ import static org.briarproject.briar.privategroup.invitation.MessageType.LEAVE; @Immutable @NotNullByDefault -abstract class AbstractProtocolEngine +abstract class AbstractProtocolEngine> implements ProtocolEngine { protected final DatabaseComponent db; @@ -90,6 +90,7 @@ abstract class AbstractProtocolEngine return group.getClientId().equals(PrivateGroupManager.CLIENT_ID); } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") boolean isValidDependency(S session, @Nullable MessageId dependency) { MessageId expected = session.getLastRemoteMessageId(); if (dependency == null) return expected == null; @@ -101,44 +102,81 @@ abstract class AbstractProtocolEngine // Apply min of preferred visibility and client's visibility ContactId contactId = getContactId(txn, session.getContactGroupId()); Visibility client = clientVersioningManager.getClientVisibility(txn, - contactId, CLIENT_ID, MAJOR_VERSION); + contactId, PrivateGroupManager.CLIENT_ID, + PrivateGroupManager.MAJOR_VERSION); Visibility min = Visibility.min(preferred, client); db.setGroupVisibility(txn, contactId, session.getPrivateGroupId(), min); } - Message sendInviteMessage(Transaction txn, S session, + Message sendInviteMessage(Transaction txn, S s, @Nullable String text, long timestamp, byte[] signature) throws DbException { - Group g = db.getGroup(txn, session.getPrivateGroupId()); + Group g = db.getGroup(txn, s.getPrivateGroupId()); PrivateGroup privateGroup; try { privateGroup = privateGroupFactory.parsePrivateGroup(g); } catch (FormatException e) { throw new DbException(e); // Invalid group descriptor } - Message m = messageEncoder.encodeInviteMessage( - session.getContactGroupId(), privateGroup.getId(), - timestamp, privateGroup.getName(), privateGroup.getCreator(), - privateGroup.getSalt(), text, signature); - sendMessage(txn, m, INVITE, privateGroup.getId(), true); + Message m; + if (contactSupportsAutoDeletion(txn, s.getContactGroupId())) { + // TODO: Look up the current auto-delete timer + long timer = NO_AUTO_DELETE_TIMER; + m = messageEncoder.encodeInviteMessage(s.getContactGroupId(), + privateGroup.getId(), timestamp, privateGroup.getName(), + privateGroup.getCreator(), privateGroup.getSalt(), text, + signature, timer); + sendMessage(txn, m, INVITE, privateGroup.getId(), true, timer); + } else { + m = messageEncoder.encodeInviteMessage(s.getContactGroupId(), + privateGroup.getId(), timestamp, privateGroup.getName(), + privateGroup.getCreator(), privateGroup.getSalt(), text, + signature); + sendMessage(txn, m, INVITE, privateGroup.getId(), true, + NO_AUTO_DELETE_TIMER); + } return m; } - Message sendJoinMessage(Transaction txn, S session, boolean visibleInUi) + Message sendJoinMessage(Transaction txn, S s, boolean visibleInUi) throws DbException { - Message m = messageEncoder.encodeJoinMessage( - session.getContactGroupId(), session.getPrivateGroupId(), - getLocalTimestamp(session), session.getLastLocalMessageId()); - sendMessage(txn, m, JOIN, session.getPrivateGroupId(), visibleInUi); + Message m; + if (contactSupportsAutoDeletion(txn, s.getContactGroupId())) { + // TODO: Look up the current auto-delete timer + long timer = NO_AUTO_DELETE_TIMER; + m = messageEncoder.encodeJoinMessage(s.getContactGroupId(), + s.getPrivateGroupId(), getLocalTimestamp(s), + s.getLastLocalMessageId(), timer); + sendMessage(txn, m, JOIN, s.getPrivateGroupId(), visibleInUi, + timer); + } else { + m = messageEncoder.encodeJoinMessage(s.getContactGroupId(), + s.getPrivateGroupId(), getLocalTimestamp(s), + s.getLastLocalMessageId()); + sendMessage(txn, m, JOIN, s.getPrivateGroupId(), visibleInUi, + NO_AUTO_DELETE_TIMER); + } return m; } - Message sendLeaveMessage(Transaction txn, S session, boolean visibleInUi) + Message sendLeaveMessage(Transaction txn, S s, boolean visibleInUi) throws DbException { - Message m = messageEncoder.encodeLeaveMessage( - session.getContactGroupId(), session.getPrivateGroupId(), - getLocalTimestamp(session), session.getLastLocalMessageId()); - sendMessage(txn, m, LEAVE, session.getPrivateGroupId(), visibleInUi); + Message m; + if (contactSupportsAutoDeletion(txn, s.getContactGroupId())) { + // TODO: Look up the current auto-delete timer + long timer = NO_AUTO_DELETE_TIMER; + m = messageEncoder.encodeLeaveMessage(s.getContactGroupId(), + s.getPrivateGroupId(), getLocalTimestamp(s), + s.getLastLocalMessageId(), timer); + sendMessage(txn, m, LEAVE, s.getPrivateGroupId(), visibleInUi, + timer); + } else { + m = messageEncoder.encodeLeaveMessage(s.getContactGroupId(), + s.getPrivateGroupId(), getLocalTimestamp(s), + s.getLastLocalMessageId()); + sendMessage(txn, m, LEAVE, s.getPrivateGroupId(), visibleInUi, + NO_AUTO_DELETE_TIMER); + } return m; } @@ -146,7 +184,8 @@ abstract class AbstractProtocolEngine Message m = messageEncoder.encodeAbortMessage( session.getContactGroupId(), session.getPrivateGroupId(), getLocalTimestamp(session)); - sendMessage(txn, m, ABORT, session.getPrivateGroupId(), false); + sendMessage(txn, m, ABORT, session.getPrivateGroupId(), false, + NO_AUTO_DELETE_TIMER); return m; } @@ -217,11 +256,11 @@ abstract class AbstractProtocolEngine } private void sendMessage(Transaction txn, Message m, MessageType type, - GroupId privateGroupId, boolean visibleInConversation) - throws DbException { - BdfDictionary meta = messageEncoder - .encodeMetadata(type, privateGroupId, m.getTimestamp(), true, - true, visibleInConversation, false, false); + GroupId privateGroupId, boolean visibleInConversation, + long autoDeleteTimer) throws DbException { + BdfDictionary meta = messageEncoder.encodeMetadata(type, + privateGroupId, m.getTimestamp(), true, true, + visibleInConversation, false, false, autoDeleteTimer); try { clientHelper.addLocalMessage(txn, m, meta, true, false); } catch (FormatException e) { @@ -229,4 +268,21 @@ abstract class AbstractProtocolEngine } } + boolean contactSupportsAutoDeletion(Transaction txn, GroupId contactGroupId) + throws DbException { + try { + BdfDictionary meta = clientHelper + .getGroupMetadataAsDictionary(txn, contactGroupId); + int contactId = meta.getLong(GROUP_KEY_CONTACT_ID).intValue(); + ContactId c = new ContactId(contactId); + int minorVersion = clientVersioningManager + .getClientMinorVersion(txn, c, + GroupInvitationManager.CLIENT_ID, + GroupInvitationManager.MAJOR_VERSION); + // Auto-delete was added in client version 0.1 + return minorVersion >= 1; + } catch (FormatException e) { + throw new DbException(e); + } + } } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java index 2830db2a2..9709f265a 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngine.java @@ -253,10 +253,10 @@ class CreatorProtocolEngine extends AbstractProtocolEngine { } private GroupInvitationResponse createInvitationResponse( - GroupInvitationMessage m, boolean accept) { + DeletableGroupInvitationMessage m, boolean accept) { SessionId sessionId = new SessionId(m.getPrivateGroupId().getBytes()); return new GroupInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, false, false, sessionId, - accept, m.getPrivateGroupId()); + accept, m.getPrivateGroupId(), m.getAutoDeleteTimer()); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/DeletableGroupInvitationMessage.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/DeletableGroupInvitationMessage.java new file mode 100644 index 000000000..328180b3f --- /dev/null +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/DeletableGroupInvitationMessage.java @@ -0,0 +1,24 @@ +package org.briarproject.briar.privategroup.invitation; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.sync.MessageId; + +import javax.annotation.concurrent.Immutable; + +@Immutable +@NotNullByDefault +abstract class DeletableGroupInvitationMessage extends GroupInvitationMessage { + + private final long autoDeleteTimer; + + DeletableGroupInvitationMessage(MessageId id, GroupId contactGroupId, + GroupId privateGroupId, long timestamp, long autoDeleteTimer) { + super(id, contactGroupId, privateGroupId, timestamp); + this.autoDeleteTimer = autoDeleteTimer; + } + + public long getAutoDeleteTimer() { + return autoDeleteTimer; + } +} diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationConstants.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationConstants.java index 90c0fcd29..dd4f0ef35 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationConstants.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationConstants.java @@ -13,6 +13,7 @@ interface GroupInvitationConstants { String MSG_KEY_VISIBLE_IN_UI = "visibleInUi"; String MSG_KEY_AVAILABLE_TO_ANSWER = "availableToAnswer"; String MSG_KEY_INVITATION_ACCEPTED = "invitationAccepted"; + String MSG_KEY_AUTO_DELETE_TIMER = "autoDeleteTimer"; // Session keys String SESSION_KEY_IS_SESSION = "isSession"; diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java index 8d61d5763..53e6fa838 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java @@ -159,7 +159,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl SessionId sessionId = getSessionId(meta.getPrivateGroupId()); StoredSession ss = getSession(txn, m.getGroupId(), sessionId); // Handle the message - Session session; + Session session; MessageId storageId; if (ss == null) { session = handleFirstMessage(txn, m, body, meta); @@ -189,7 +189,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl results.values().iterator().next()); } - private Session handleFirstMessage(Transaction txn, Message m, BdfList body, + private Session handleFirstMessage(Transaction txn, Message m, BdfList body, MessageMetadata meta) throws DbException, FormatException { GroupId privateGroupId = meta.getPrivateGroupId(); MessageType type = meta.getMessageType(); @@ -206,7 +206,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl } } - private Session handleMessage(Transaction txn, Message m, BdfList body, + private Session handleMessage(Transaction txn, Message m, BdfList body, MessageMetadata meta, BdfDictionary bdfSession) throws DbException, FormatException { MessageType type = meta.getMessageType(); @@ -228,7 +228,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl } } - private S handleMessage(Transaction txn, Message m, + private > S handleMessage(Transaction txn, Message m, BdfList body, MessageType type, S session, ProtocolEngine engine) throws DbException, FormatException { if (type == INVITE) { @@ -256,7 +256,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl } private void storeSession(Transaction txn, MessageId storageId, - Session session) throws DbException, FormatException { + Session session) throws DbException, FormatException { BdfDictionary d = sessionEncoder.encodeSession(session); clientHelper.mergeMessageMetadata(txn, storageId, d); } @@ -354,7 +354,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl } } - private S handleAction(Transaction txn, + private > S handleAction(Transaction txn, LocalAction type, S session, ProtocolEngine engine) throws DbException { if (type == LocalAction.INVITE) { @@ -420,7 +420,8 @@ class GroupInvitationManagerImpl extends ConversationClientImpl return new GroupInvitationRequest(m, contactGroupId, meta.getTimestamp(), meta.isLocal(), meta.isRead(), status.isSent(), status.isSeen(), sessionId, pg, - invite.getText(), meta.isAvailableToAnswer(), canBeOpened); + invite.getText(), meta.isAvailableToAnswer(), canBeOpened, + invite.getAutoDeleteTimer()); } private GroupInvitationResponse parseInvitationResponse( @@ -430,7 +431,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl return new GroupInvitationResponse(m, contactGroupId, meta.getTimestamp(), meta.isLocal(), meta.isRead(), status.isSent(), status.isSeen(), sessionId, accept, - meta.getPrivateGroupId()); + meta.getPrivateGroupId(), meta.getAutoDeleteTimer()); } @Override @@ -508,7 +509,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl SessionId sessionId = getSessionId(privateGroupId); StoredSession ss = getSession(txn, contactGroupId, sessionId); // Create or parse the session - Session session; + Session session; MessageId storageId; if (ss == null) { // If there's no session the contact must be a peer, @@ -543,7 +544,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl StoredSession ss = getSession(txn, contactGroupId, sessionId); if (ss == null) continue; // No session for this contact // Handle the action - Session session = handleAction(txn, LocalAction.LEAVE, + Session session = handleAction(txn, LocalAction.LEAVE, contactGroupId, ss.bdfSession); // Store the updated session storeSession(txn, ss.storageId, session); @@ -553,7 +554,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl } } - private Session handleAction(Transaction txn, LocalAction a, + private Session handleAction(Transaction txn, LocalAction a, GroupId contactGroupId, BdfDictionary bdfSession) throws DbException, FormatException { Role role = sessionParser.getRole(bdfSession); @@ -613,7 +614,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl .getMessageMetadataAsDictionary(txn, contactGroupId, query); Map m = new HashMap<>(); for (BdfDictionary d : results.values()) { - Session s = sessionParser.parseSession(contactGroupId, d); + Session s = sessionParser.parseSession(contactGroupId, d); m.put(s.getPrivateGroupId(), s.getState().getVisibility()); } return m; @@ -644,7 +645,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl Map sessions = new HashMap<>(); for (BdfDictionary d : metadata.values()) { if (!sessionParser.isSession(d)) continue; - Session session; + Session session; try { session = sessionParser.parseSession(g, d); } catch (FormatException e) { @@ -673,7 +674,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl getSessionId(messageMetadata.getPrivateGroupId()); StoredSession ss = getSession(txn1, g, sessionId); if (ss == null) throw new DbException(); - Session session = sessionParser + Session session = sessionParser .parseSession(g, metadata.get(ss.storageId)); sessions.put(session.getPrivateGroupId(), new DeletableSession(session.getState())); diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java index 8e0505759..0896ea6ac 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidator.java @@ -21,10 +21,15 @@ import org.briarproject.briar.api.privategroup.PrivateGroupFactory; import java.security.GeneralSecurityException; import java.util.Collections; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.util.ValidationUtils.checkLength; +import static org.briarproject.bramble.util.ValidationUtils.checkRange; import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_TEXT_LENGTH; @@ -71,8 +76,11 @@ class GroupInvitationValidator extends BdfMessageValidator { private BdfMessageContext validateInviteMessage(Message m, BdfList body) throws FormatException { - // Message type, creator, group name, salt, optional text, signature - checkSize(body, 6); + // Client version 0.0: Message type, creator, group name, salt, + // optional text, signature. + // Client version 0.1: Message type, creator, group name, salt, + // optional text, signature, optional auto-delete timer. + checkSize(body, 6, 7); BdfList creatorList = body.getList(1); String groupName = body.getString(2); checkLength(groupName, 1, MAX_GROUP_NAME_LENGTH); @@ -82,6 +90,8 @@ class GroupInvitationValidator extends BdfMessageValidator { checkLength(text, 1, MAX_GROUP_INVITATION_TEXT_LENGTH); byte[] signature = body.getRaw(5); checkLength(signature, 1, MAX_SIGNATURE_LENGTH); + long timer = NO_AUTO_DELETE_TIMER; + if (body.size() == 7) timer = validateTimer(body.getOptionalLong(6)); // Validate the creator and create the private group Author creator = clientHelper.parseAndValidateAuthor(creatorList); @@ -102,20 +112,27 @@ class GroupInvitationValidator extends BdfMessageValidator { // Create the metadata BdfDictionary meta = messageEncoder.encodeMetadata(INVITE, privateGroup.getId(), m.getTimestamp(), false, false, false, - false, false); + false, false, timer); return new BdfMessageContext(meta); } private BdfMessageContext validateJoinMessage(Message m, BdfList body) throws FormatException { - checkSize(body, 3); + // Client version 0.0: Message type, private group ID, optional + // previous message ID. + // Client version 0.1: Message type, private group ID, optional + // previous message ID, optional auto-delete timer. + checkSize(body, 3, 4); byte[] privateGroupId = body.getRaw(1); checkLength(privateGroupId, UniqueId.LENGTH); byte[] previousMessageId = body.getOptionalRaw(2); checkLength(previousMessageId, UniqueId.LENGTH); + long timer = NO_AUTO_DELETE_TIMER; + if (body.size() == 4) timer = validateTimer(body.getOptionalLong(3)); + BdfDictionary meta = messageEncoder.encodeMetadata(JOIN, new GroupId(privateGroupId), m.getTimestamp(), false, false, - false, false, false); + false, false, false, timer); if (previousMessageId == null) { return new BdfMessageContext(meta); } else { @@ -127,14 +144,21 @@ class GroupInvitationValidator extends BdfMessageValidator { private BdfMessageContext validateLeaveMessage(Message m, BdfList body) throws FormatException { - checkSize(body, 3); + // Client version 0.0: Message type, private group ID, optional + // previous message ID. + // Client version 0.1: Message type, private group ID, optional + // previous message ID, optional auto-delete timer. + checkSize(body, 3, 4); byte[] privateGroupId = body.getRaw(1); checkLength(privateGroupId, UniqueId.LENGTH); byte[] previousMessageId = body.getOptionalRaw(2); checkLength(previousMessageId, UniqueId.LENGTH); + long timer = NO_AUTO_DELETE_TIMER; + if (body.size() == 4) timer = validateTimer(body.getOptionalLong(3)); + BdfDictionary meta = messageEncoder.encodeMetadata(LEAVE, new GroupId(privateGroupId), m.getTimestamp(), false, false, - false, false, false); + false, false, false, timer); if (previousMessageId == null) { return new BdfMessageContext(meta); } else { @@ -151,7 +175,13 @@ class GroupInvitationValidator extends BdfMessageValidator { checkLength(privateGroupId, UniqueId.LENGTH); BdfDictionary meta = messageEncoder.encodeMetadata(ABORT, new GroupId(privateGroupId), m.getTimestamp(), false, false, - false, false, false); + false, false, false, NO_AUTO_DELETE_TIMER); return new BdfMessageContext(meta); } + + private long validateTimer(@Nullable Long timer) throws FormatException { + if (timer == null) return NO_AUTO_DELETE_TIMER; + checkRange(timer, MIN_AUTO_DELETE_TIMER_MS, MAX_AUTO_DELETE_TIMER_MS); + return timer; + } } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteMessage.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteMessage.java index 5d97e3f7e..a9dc59329 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteMessage.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteMessage.java @@ -10,7 +10,7 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -class InviteMessage extends GroupInvitationMessage { +class InviteMessage extends DeletableGroupInvitationMessage { private final String groupName; private final Author creator; @@ -20,8 +20,8 @@ class InviteMessage extends GroupInvitationMessage { InviteMessage(MessageId id, GroupId contactGroupId, GroupId privateGroupId, long timestamp, String groupName, Author creator, byte[] salt, - @Nullable String text, byte[] signature) { - super(id, contactGroupId, privateGroupId, timestamp); + @Nullable String text, byte[] signature, long autoDeleteTimer) { + super(id, contactGroupId, privateGroupId, timestamp, autoDeleteTimer); this.groupName = groupName; this.creator = creator; this.salt = salt; diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java index abf489ac6..b4a7665fd 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngine.java @@ -330,7 +330,7 @@ class InviteeProtocolEngine extends AbstractProtocolEngine { SessionId sessionId = new SessionId(m.getPrivateGroupId().getBytes()); return new GroupInvitationRequest(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, false, false, sessionId, pg, - m.getText(), true, false); + m.getText(), true, false, m.getAutoDeleteTimer()); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/JoinMessage.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/JoinMessage.java index 77d6e3eef..4b4c2b0eb 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/JoinMessage.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/JoinMessage.java @@ -9,14 +9,15 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -class JoinMessage extends GroupInvitationMessage { +class JoinMessage extends DeletableGroupInvitationMessage { @Nullable private final MessageId previousMessageId; JoinMessage(MessageId id, GroupId contactGroupId, GroupId privateGroupId, - long timestamp, @Nullable MessageId previousMessageId) { - super(id, contactGroupId, privateGroupId, timestamp); + long timestamp, @Nullable MessageId previousMessageId, + long autoDeleteTimer) { + super(id, contactGroupId, privateGroupId, timestamp, autoDeleteTimer); this.previousMessageId = previousMessageId; } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LeaveMessage.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LeaveMessage.java index cf323fe81..a442ba894 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LeaveMessage.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/LeaveMessage.java @@ -9,14 +9,15 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -class LeaveMessage extends GroupInvitationMessage { +class LeaveMessage extends DeletableGroupInvitationMessage { @Nullable private final MessageId previousMessageId; LeaveMessage(MessageId id, GroupId contactGroupId, GroupId privateGroupId, - long timestamp, @Nullable MessageId previousMessageId) { - super(id, contactGroupId, privateGroupId, timestamp); + long timestamp, @Nullable MessageId previousMessageId, + long autoDeleteTimer) { + super(id, contactGroupId, privateGroupId, timestamp, autoDeleteTimer); this.previousMessageId = previousMessageId; } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoder.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoder.java index 8ba1caaa7..7f65a8c42 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoder.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoder.java @@ -14,7 +14,7 @@ interface MessageEncoder { BdfDictionary encodeMetadata(MessageType type, GroupId privateGroupId, long timestamp, boolean local, boolean read, boolean visible, - boolean available, boolean accepted); + boolean available, boolean accepted, long autoDeleteTimer); void setVisibleInUi(BdfDictionary meta, boolean visible); @@ -22,16 +22,49 @@ interface MessageEncoder { void setInvitationAccepted(BdfDictionary meta, boolean accepted); + /** + * Encodes an invite message without an auto-delete timer. + */ Message encodeInviteMessage(GroupId contactGroupId, GroupId privateGroupId, long timestamp, String groupName, Author creator, byte[] salt, @Nullable String text, byte[] signature); + /** + * Encodes an invite message with an optional auto-delete timer. This + * requires the contact to support client version 0.1 or higher. + */ + Message encodeInviteMessage(GroupId contactGroupId, GroupId privateGroupId, + long timestamp, String groupName, Author creator, byte[] salt, + @Nullable String text, byte[] signature, long autoDeleteTimer); + + /** + * Encodes a join message without an auto-delete timer. + */ Message encodeJoinMessage(GroupId contactGroupId, GroupId privateGroupId, long timestamp, @Nullable MessageId previousMessageId); + /** + * Encodes a join message with an optional auto-delete timer. This + * requires the contact to support client version 0.1 or higher. + */ + Message encodeJoinMessage(GroupId contactGroupId, GroupId privateGroupId, + long timestamp, @Nullable MessageId previousMessageId, + long autoDeleteTimer); + + /** + * Encodes a leave message without an auto-delete timer. + */ Message encodeLeaveMessage(GroupId contactGroupId, GroupId privateGroupId, long timestamp, @Nullable MessageId previousMessageId); + /** + * Encodes a leave message with an optional auto-delete timer. This + * requires the contact to support client version 0.1 or higher. + */ + Message encodeLeaveMessage(GroupId contactGroupId, GroupId privateGroupId, + long timestamp, @Nullable MessageId previousMessageId, + long autoDeleteTimer); + Message encodeAbortMessage(GroupId contactGroupId, GroupId privateGroupId, long timestamp); } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoderImpl.java index 43f208a94..b326a61b4 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoderImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageEncoderImpl.java @@ -15,7 +15,9 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; +import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AUTO_DELETE_TIMER; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_INVITATION_ACCEPTED; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL; @@ -45,7 +47,8 @@ class MessageEncoderImpl implements MessageEncoder { @Override public BdfDictionary encodeMetadata(MessageType type, GroupId privateGroupId, long timestamp, boolean local, boolean read, - boolean visible, boolean available, boolean accepted) { + boolean visible, boolean available, boolean accepted, + long autoDeleteTimer) { BdfDictionary meta = new BdfDictionary(); meta.put(MSG_KEY_MESSAGE_TYPE, type.getValue()); meta.put(MSG_KEY_PRIVATE_GROUP_ID, privateGroupId); @@ -55,6 +58,9 @@ class MessageEncoderImpl implements MessageEncoder { meta.put(MSG_KEY_VISIBLE_IN_UI, visible); meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available); meta.put(MSG_KEY_INVITATION_ACCEPTED, accepted); + if (autoDeleteTimer != NO_AUTO_DELETE_TIMER) { + meta.put(MSG_KEY_AUTO_DELETE_TIMER, autoDeleteTimer); + } return meta; } @@ -87,12 +93,25 @@ class MessageEncoderImpl implements MessageEncoder { text, signature ); - try { - return messageFactory.createMessage(contactGroupId, timestamp, - clientHelper.toByteArray(body)); - } catch (FormatException e) { - throw new AssertionError(e); - } + return createMessage(contactGroupId, timestamp, body); + } + + @Override + public Message encodeInviteMessage(GroupId contactGroupId, + GroupId privateGroupId, long timestamp, String groupName, + Author creator, byte[] salt, @Nullable String text, + byte[] signature, long autoDeleteTimer) { + BdfList creatorList = clientHelper.toList(creator); + BdfList body = BdfList.of( + INVITE.getValue(), + creatorList, + groupName, + salt, + text, + signature, + encodeTimer(autoDeleteTimer) + ); + return createMessage(contactGroupId, timestamp, body); } @Override @@ -104,12 +123,20 @@ class MessageEncoderImpl implements MessageEncoder { privateGroupId, previousMessageId ); - try { - return messageFactory.createMessage(contactGroupId, timestamp, - clientHelper.toByteArray(body)); - } catch (FormatException e) { - throw new AssertionError(e); - } + return createMessage(contactGroupId, timestamp, body); + } + + @Override + public Message encodeJoinMessage(GroupId contactGroupId, + GroupId privateGroupId, long timestamp, + @Nullable MessageId previousMessageId, long autoDeleteTimer) { + BdfList body = BdfList.of( + JOIN.getValue(), + privateGroupId, + previousMessageId, + encodeTimer(autoDeleteTimer) + ); + return createMessage(contactGroupId, timestamp, body); } @Override @@ -121,12 +148,20 @@ class MessageEncoderImpl implements MessageEncoder { privateGroupId, previousMessageId ); - try { - return messageFactory.createMessage(contactGroupId, timestamp, - clientHelper.toByteArray(body)); - } catch (FormatException e) { - throw new AssertionError(e); - } + return createMessage(contactGroupId, timestamp, body); + } + + @Override + public Message encodeLeaveMessage(GroupId contactGroupId, + GroupId privateGroupId, long timestamp, + @Nullable MessageId previousMessageId, long autoDeleteTimer) { + BdfList body = BdfList.of( + LEAVE.getValue(), + privateGroupId, + previousMessageId, + encodeTimer(autoDeleteTimer) + ); + return createMessage(contactGroupId, timestamp, body); } @Override @@ -136,6 +171,11 @@ class MessageEncoderImpl implements MessageEncoder { ABORT.getValue(), privateGroupId ); + return createMessage(contactGroupId, timestamp, body); + } + + private Message createMessage(GroupId contactGroupId, long timestamp, + BdfList body) { try { return messageFactory.createMessage(contactGroupId, timestamp, clientHelper.toByteArray(body)); @@ -143,4 +183,9 @@ class MessageEncoderImpl implements MessageEncoder { throw new AssertionError(e); } } + + @Nullable + private Long encodeTimer(long autoDeleteTimer) { + return autoDeleteTimer == NO_AUTO_DELETE_TIMER ? null : autoDeleteTimer; + } } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageMetadata.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageMetadata.java index c4490641d..f847a98fd 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageMetadata.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageMetadata.java @@ -11,12 +11,12 @@ class MessageMetadata { private final MessageType type; private final GroupId privateGroupId; - private final long timestamp; + private final long timestamp, autoDeleteTimer; private final boolean local, read, visible, available, accepted; MessageMetadata(MessageType type, GroupId privateGroupId, long timestamp, boolean local, boolean read, boolean visible, - boolean available, boolean accepted) { + boolean available, boolean accepted, long autoDeleteTimer) { this.privateGroupId = privateGroupId; this.type = type; this.timestamp = timestamp; @@ -25,6 +25,7 @@ class MessageMetadata { this.visible = visible; this.available = available; this.accepted = accepted; + this.autoDeleteTimer = autoDeleteTimer; } MessageType getMessageType() { @@ -64,4 +65,7 @@ class MessageMetadata { return accepted; } + public long getAutoDeleteTimer() { + return autoDeleteTimer; + } } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java index cd850f949..4249b7952 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/MessageParserImpl.java @@ -8,7 +8,6 @@ import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.identity.Author; -import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.Message; @@ -19,7 +18,9 @@ import org.briarproject.briar.api.privategroup.PrivateGroupFactory; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; +import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AUTO_DELETE_TIMER; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_INVITATION_ACCEPTED; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_LOCAL; @@ -33,15 +34,12 @@ import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE; @NotNullByDefault class MessageParserImpl implements MessageParser { - private final AuthorFactory authorFactory; private final PrivateGroupFactory privateGroupFactory; private final ClientHelper clientHelper; @Inject - MessageParserImpl(AuthorFactory authorFactory, - PrivateGroupFactory privateGroupFactory, + MessageParserImpl(PrivateGroupFactory privateGroupFactory, ClientHelper clientHelper) { - this.authorFactory = authorFactory; this.privateGroupFactory = privateGroupFactory; this.clientHelper = clientHelper; } @@ -82,8 +80,10 @@ class MessageParserImpl implements MessageParser { boolean visible = meta.getBoolean(MSG_KEY_VISIBLE_IN_UI, false); boolean available = meta.getBoolean(MSG_KEY_AVAILABLE_TO_ANSWER, false); boolean accepted = meta.getBoolean(MSG_KEY_INVITATION_ACCEPTED, false); + long timer = meta.getLong(MSG_KEY_AUTO_DELETE_TIMER, + NO_AUTO_DELETE_TIMER); return new MessageMetadata(type, privateGroupId, timestamp, local, read, - visible, available, accepted); + visible, available, accepted, timer); } @Override @@ -97,39 +97,58 @@ class MessageParserImpl implements MessageParser { @Override public InviteMessage parseInviteMessage(Message m, BdfList body) throws FormatException { - // Message type, creator, group name, salt, optional text, signature + // Client version 0.0: Message type, creator, group name, salt, + // optional text, signature. + // Client version 0.1: Message type, creator, group name, salt, + // optional text, signature, optional auto-delete timer. BdfList creatorList = body.getList(1); String groupName = body.getString(2); byte[] salt = body.getRaw(3); String text = body.getOptionalString(4); byte[] signature = body.getRaw(5); + long timer = NO_AUTO_DELETE_TIMER; + if (body.size() == 7) timer = body.getLong(6, NO_AUTO_DELETE_TIMER); Author creator = clientHelper.parseAndValidateAuthor(creatorList); PrivateGroup privateGroup = privateGroupFactory.createPrivateGroup( groupName, creator, salt); return new InviteMessage(m.getId(), m.getGroupId(), privateGroup.getId(), m.getTimestamp(), groupName, creator, - salt, text, signature); + salt, text, signature, timer); } @Override public JoinMessage parseJoinMessage(Message m, BdfList body) throws FormatException { + // Client version 0.0: Message type, private group ID, optional + // previous message ID. + // Client version 0.1: Message type, private group ID, optional + // previous message ID, optional auto-delete timer. GroupId privateGroupId = new GroupId(body.getRaw(1)); byte[] b = body.getOptionalRaw(2); MessageId previousMessageId = b == null ? null : new MessageId(b); + long timer = NO_AUTO_DELETE_TIMER; + if (body.size() == 4) timer = body.getLong(3, NO_AUTO_DELETE_TIMER); + return new JoinMessage(m.getId(), m.getGroupId(), privateGroupId, - m.getTimestamp(), previousMessageId); + m.getTimestamp(), previousMessageId, timer); } @Override public LeaveMessage parseLeaveMessage(Message m, BdfList body) throws FormatException { + // Client version 0.0: Message type, private group ID, optional + // previous message ID. + // Client version 0.1: Message type, private group ID, optional + // previous message ID, optional auto-delete timer. GroupId privateGroupId = new GroupId(body.getRaw(1)); byte[] b = body.getOptionalRaw(2); MessageId previousMessageId = b == null ? null : new MessageId(b); + long timer = NO_AUTO_DELETE_TIMER; + if (body.size() == 4) timer = body.getLong(3, NO_AUTO_DELETE_TIMER); + return new LeaveMessage(m.getId(), m.getGroupId(), privateGroupId, - m.getTimestamp(), previousMessageId); + m.getTimestamp(), previousMessageId, timer); } @Override diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java index 262327aa2..a003e34a7 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngineTest.java @@ -22,8 +22,10 @@ import org.briarproject.briar.api.privategroup.GroupMessageFactory; import org.briarproject.briar.api.privategroup.PrivateGroup; import org.briarproject.briar.api.privategroup.PrivateGroupFactory; import org.briarproject.briar.api.privategroup.PrivateGroupManager; +import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; import org.jmock.Expectations; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.test.TestUtils.getContact; @@ -35,8 +37,6 @@ import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_TEXT_LENGTH; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH; -import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID; -import static org.briarproject.briar.api.privategroup.PrivateGroupManager.MAJOR_VERSION; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID; import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT; import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE; @@ -67,7 +67,8 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase { final ContactId contactId = contact.getId(); final Author author = contact.getAuthor(); final GroupId contactGroupId = new GroupId(getRandomId()); - final Group privateGroupGroup = getGroup(CLIENT_ID, MAJOR_VERSION); + final Group privateGroupGroup = getGroup(PrivateGroupManager.CLIENT_ID, + PrivateGroupManager.MAJOR_VERSION); final GroupId privateGroupId = privateGroupGroup.getId(); final PrivateGroup privateGroup = new PrivateGroup(privateGroupGroup, getRandomString(MAX_GROUP_NAME_LENGTH), author, @@ -80,30 +81,34 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase { final long messageTimestamp = message.getTimestamp(); final long inviteTimestamp = messageTimestamp - 1; final long localTimestamp = inviteTimestamp - 1; + final BdfDictionary groupMeta = BdfDictionary.of( + new BdfEntry(GROUP_KEY_CONTACT_ID, contactId.getInt())); final InviteMessage inviteMessage = new InviteMessage(new MessageId(getRandomId()), contactGroupId, privateGroupId, 0L, privateGroup.getName(), privateGroup.getCreator(), privateGroup.getSalt(), getRandomString(MAX_GROUP_INVITATION_TEXT_LENGTH), - signature); + signature, NO_AUTO_DELETE_TIMER); final JoinMessage joinMessage = new JoinMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, 0L, lastRemoteMessageId); + privateGroupId, 0L, lastRemoteMessageId, + NO_AUTO_DELETE_TIMER); final LeaveMessage leaveMessage = new LeaveMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, 0L, lastRemoteMessageId); + privateGroupId, 0L, lastRemoteMessageId, + NO_AUTO_DELETE_TIMER); final AbortMessage abortMessage = new AbortMessage(messageId, contactGroupId, privateGroupId, inviteTimestamp + 1); - void assertSessionConstantsUnchanged(Session s1, Session s2) { + void assertSessionConstantsUnchanged(Session s1, Session s2) { assertEquals(s1.getRole(), s2.getRole()); assertEquals(s1.getContactGroupId(), s2.getContactGroupId()); assertEquals(s1.getPrivateGroupId(), s2.getPrivateGroupId()); } - void assertSessionRecordedSentMessage(Session s) { + void assertSessionRecordedSentMessage(Session s) { assertEquals(messageId, s.getLastLocalMessageId()); assertEquals(lastRemoteMessageId, s.getLastRemoteMessageId()); assertEquals(messageTimestamp, s.getLocalTimestamp()); @@ -118,11 +123,13 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase { } void expectSendInviteMessage(String text) throws Exception { + expectCheckWhetherContactSupportsAutoDeletion(); + expectGetLocalTimestamp(messageTimestamp); context.checking(new Expectations() {{ - oneOf(messageEncoder) - .encodeInviteMessage(contactGroupId, privateGroupId, - inviteTimestamp, privateGroup.getName(), author, - privateGroup.getSalt(), text, signature); + oneOf(messageEncoder).encodeInviteMessage(contactGroupId, + privateGroupId, inviteTimestamp, privateGroup.getName(), + author, privateGroup.getSalt(), text, signature, + NO_AUTO_DELETE_TIMER); will(returnValue(message)); }}); expectSendMessage(INVITE, true); @@ -130,22 +137,24 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase { void expectSendJoinMessage(JoinMessage m, boolean visible) throws Exception { + expectCheckWhetherContactSupportsAutoDeletion(); expectGetLocalTimestamp(messageTimestamp); context.checking(new Expectations() {{ oneOf(messageEncoder).encodeJoinMessage(m.getContactGroupId(), m.getPrivateGroupId(), m.getTimestamp(), - lastLocalMessageId); + lastLocalMessageId, NO_AUTO_DELETE_TIMER); will(returnValue(message)); }}); expectSendMessage(JOIN, visible); } void expectSendLeaveMessage(boolean visible) throws Exception { + expectCheckWhetherContactSupportsAutoDeletion(); expectGetLocalTimestamp(messageTimestamp); context.checking(new Expectations() {{ - oneOf(messageEncoder) - .encodeLeaveMessage(contactGroupId, privateGroupId, - messageTimestamp, lastLocalMessageId); + oneOf(messageEncoder).encodeLeaveMessage(contactGroupId, + privateGroupId, messageTimestamp, lastLocalMessageId, + NO_AUTO_DELETE_TIMER); will(returnValue(message)); }}); expectSendMessage(LEAVE, visible); @@ -167,7 +176,8 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase { BdfDictionary meta = BdfDictionary.of(new BdfEntry("me", "ta")); context.checking(new Expectations() {{ oneOf(messageEncoder).encodeMetadata(type, privateGroupId, - message.getTimestamp(), true, true, visible, false, false); + message.getTimestamp(), true, true, visible, false, false, + NO_AUTO_DELETE_TIMER); will(returnValue(meta)); oneOf(clientHelper).addLocalMessage(txn, message, meta, true, false); @@ -178,7 +188,8 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase { expectGetContactId(); context.checking(new Expectations() {{ oneOf(clientVersioningManager).getClientVisibility(txn, contactId, - CLIENT_ID, MAJOR_VERSION); + PrivateGroupManager.CLIENT_ID, + PrivateGroupManager.MAJOR_VERSION); will(returnValue(SHARED)); oneOf(db).setGroupVisibility(txn, contactId, privateGroupId, v); }}); @@ -218,4 +229,15 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase { }}); } + void expectCheckWhetherContactSupportsAutoDeletion() throws Exception { + context.checking(new Expectations() {{ + oneOf(clientHelper).getGroupMetadataAsDictionary(txn, + contactGroupId); + will(returnValue(groupMeta)); + oneOf(clientVersioningManager).getClientMinorVersion(txn, contactId, + GroupInvitationManager.CLIENT_ID, + GroupInvitationManager.MAJOR_VERSION); + will(returnValue(GroupInvitationManager.MINOR_VERSION)); + }}); + } } diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java index 9495b19ec..559a6de93 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/CreatorProtocolEngineTest.java @@ -5,6 +5,7 @@ import org.briarproject.briar.api.client.ProtocolStateException; import org.jmock.Expectations; import org.junit.Test; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.test.TestUtils.getRandomId; @@ -77,7 +78,6 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest { oneOf(messageTracker).trackOutgoingMessage(txn, message); }}); expectSendInviteMessage(text); - expectGetLocalTimestamp(messageTimestamp); } @Test(expected = ProtocolStateException.class) @@ -289,7 +289,7 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest { CreatorSession session = getDefaultSession(INVITED); JoinMessage invalidJoinMessage = new JoinMessage(messageId, contactGroupId, privateGroupId, - inviteTimestamp + 1, messageId); + inviteTimestamp + 1, messageId, NO_AUTO_DELETE_TIMER); expectAbortWhenSubscribedToGroup(); CreatorSession newSession = @@ -303,7 +303,7 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest { JoinMessage properJoinMessage = new JoinMessage(new MessageId(getRandomId()), contactGroupId, privateGroupId, inviteTimestamp + 1, - lastRemoteMessageId); + lastRemoteMessageId, NO_AUTO_DELETE_TIMER); expectSendJoinMessage(properJoinMessage, false); expectMarkMessageVisibleInUi(properJoinMessage.getId()); @@ -343,7 +343,8 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest { public void testOnLeaveMessageFromStart() throws Exception { LeaveMessage leaveMessage = new LeaveMessage(messageId, contactGroupId, privateGroupId, - inviteTimestamp, lastLocalMessageId); + inviteTimestamp, lastLocalMessageId, + NO_AUTO_DELETE_TIMER); CreatorSession session = getDefaultSession(START); expectAbortWhenSubscribedToGroup(); @@ -377,7 +378,8 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest { throws Exception { LeaveMessage invalidLeaveMessage = new LeaveMessage(messageId, contactGroupId, privateGroupId, - inviteTimestamp + 1, lastLocalMessageId); + inviteTimestamp + 1, lastLocalMessageId, + NO_AUTO_DELETE_TIMER); CreatorSession session = getDefaultSession(INVITED); expectAbortWhenSubscribedToGroup(); @@ -392,7 +394,7 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest { LeaveMessage properLeaveMessage = new LeaveMessage(new MessageId(getRandomId()), contactGroupId, privateGroupId, inviteTimestamp + 1, - lastRemoteMessageId); + lastRemoteMessageId, NO_AUTO_DELETE_TIMER); CreatorSession session = getDefaultSession(INVITED); expectMarkMessageVisibleInUi(properLeaveMessage.getId()); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java index 58df14e7c..60d0e3758 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java @@ -45,6 +45,7 @@ import javax.annotation.Nullable; import static java.util.Arrays.asList; import static junit.framework.TestCase.fail; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getContact; @@ -230,7 +231,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { }}); } - private void expectStoreSession(Session session, MessageId storageId) + private void expectStoreSession(Session session, MessageId storageId) throws Exception { context.checking(new Expectations() {{ oneOf(sessionEncoder).encodeSession(session); @@ -320,7 +321,8 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { throws Exception { expectParseMessageMetadata(); expectGetSession(noResults, sessionId, contactGroup.getId()); - Session session = expectHandleFirstMessage(role, messageMetadata, type); + Session session = + expectHandleFirstMessage(role, messageMetadata, type); if (session != null) { expectCreateStorageId(); expectStoreSession(session, storageMessage.getId()); @@ -347,13 +349,13 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { BdfDictionary bdfSession) throws Exception { expectParseMessageMetadata(); expectGetSession(oneResult, sessionId, contactGroup.getId()); - Session session = expectHandleMessage(role, messageMetadata, bdfSession, - type); + Session session = + expectHandleMessage(role, messageMetadata, bdfSession, type); expectStoreSession(session, storageMessage.getId()); } @Nullable - private Session expectHandleFirstMessage(Role role, + private Session expectHandleFirstMessage(Role role, MessageMetadata messageMetadata, MessageType type) throws Exception { context.checking(new Expectations() {{ @@ -382,7 +384,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { } @Nullable - private Session expectHandleMessage(Role role, + private Session expectHandleMessage(Role role, MessageMetadata messageMetadata, BdfDictionary state, MessageType type) throws Exception { context.checking(new Expectations() {{ @@ -420,8 +422,9 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { } } - private void expectIndividualMessage(MessageType type, - ProtocolEngine engine, S session) throws Exception { + private > void expectIndividualMessage( + MessageType type, ProtocolEngine engine, S session) + throws Exception { if (type == INVITE) { InviteMessage msg = context.mock(InviteMessage.class); context.checking(new Expectations() {{ @@ -657,14 +660,14 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { long time1 = 1L, time2 = 2L; MessageMetadata messageMetadata1 = new MessageMetadata(INVITE, privateGroup.getId(), time1, true, - true, true, false, true); + true, true, false, true, NO_AUTO_DELETE_TIMER); MessageMetadata messageMetadata2 = new MessageMetadata(JOIN, privateGroup.getId(), time2, true, - true, true, true, false); + true, true, true, false, NO_AUTO_DELETE_TIMER); InviteMessage invite = new InviteMessage(message.getId(), contactGroup.getId(), privateGroup.getId(), time1, "name", author, - new byte[0], null, new byte[0]); + new byte[0], null, new byte[0], NO_AUTO_DELETE_TIMER); PrivateGroup pg = new PrivateGroup(privateGroup, invite.getGroupName(), invite.getCreator(), invite.getSalt()); @@ -731,11 +734,11 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { InviteMessage inviteMessage1 = new InviteMessage(message.getId(), contactGroup.getId(), privateGroup.getId(), time1, groupName, author, salt, - null, getRandomBytes(5)); + null, getRandomBytes(5), NO_AUTO_DELETE_TIMER); InviteMessage inviteMessage2 = new InviteMessage(message2.getId(), contactGroup.getId(), privateGroup.getId(), time2, groupName, author, salt, - null, getRandomBytes(5)); + null, getRandomBytes(5), NO_AUTO_DELETE_TIMER); PrivateGroup pg = new PrivateGroup(privateGroup, groupName, author, salt); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java index 386c35448..d8e7c0600 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java @@ -16,6 +16,7 @@ import org.junit.Test; import java.security.GeneralSecurityException; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; @@ -263,7 +264,7 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase { } else { oneOf(messageEncoder).encodeMetadata(INVITE, message.getGroupId(), message.getTimestamp(), false, - false, false, false, false); + false, false, false, false, NO_AUTO_DELETE_TIMER); will(returnValue(meta)); } }}); @@ -341,7 +342,8 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase { BdfList body = BdfList.of(JOIN.getValue(), privateGroup.getId(), null); context.checking(new Expectations() {{ oneOf(messageEncoder).encodeMetadata(JOIN, message.getGroupId(), - message.getTimestamp(), false, false, false, false, false); + message.getTimestamp(), false, false, false, false, false, + NO_AUTO_DELETE_TIMER); will(returnValue(meta)); }}); BdfMessageContext messageContext = @@ -356,7 +358,8 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase { previousMessageId); context.checking(new Expectations() {{ oneOf(messageEncoder).encodeMetadata(JOIN, message.getGroupId(), - message.getTimestamp(), false, false, false, false, false); + message.getTimestamp(), false, false, false, false, false, + NO_AUTO_DELETE_TIMER); will(returnValue(meta)); }}); BdfMessageContext messageContext = @@ -439,7 +442,8 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase { BdfList body = BdfList.of(LEAVE.getValue(), privateGroup.getId(), null); context.checking(new Expectations() {{ oneOf(messageEncoder).encodeMetadata(LEAVE, message.getGroupId(), - message.getTimestamp(), false, false, false, false, false); + message.getTimestamp(), false, false, false, false, false, + NO_AUTO_DELETE_TIMER); will(returnValue(meta)); }}); BdfMessageContext messageContext = @@ -452,7 +456,8 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase { public void testAcceptsValidLeaveMessage() throws Exception { context.checking(new Expectations() {{ oneOf(messageEncoder).encodeMetadata(LEAVE, message.getGroupId(), - message.getTimestamp(), false, false, false, false, false); + message.getTimestamp(), false, false, false, false, false, + NO_AUTO_DELETE_TIMER); will(returnValue(meta)); }}); BdfList body = BdfList.of(LEAVE.getValue(), privateGroup.getId(), @@ -509,7 +514,8 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase { public void testAcceptsValidAbortMessage() throws Exception { context.checking(new Expectations() {{ oneOf(messageEncoder).encodeMetadata(ABORT, message.getGroupId(), - message.getTimestamp(), false, false, false, false, false); + message.getTimestamp(), false, false, false, false, false, + NO_AUTO_DELETE_TIMER); will(returnValue(meta)); }}); BdfList body = BdfList.of(ABORT.getValue(), privateGroup.getId()); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java index e4464c389..fee724bb8 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java @@ -13,6 +13,7 @@ import org.junit.Test; import java.util.Collections; import java.util.Map; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; @@ -131,7 +132,8 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { public void testOnJoinActionFromInvited() throws Exception { JoinMessage properJoinMessage = new JoinMessage(messageId, contactGroupId, privateGroupId, - messageTimestamp, lastRemoteMessageId); + messageTimestamp, lastRemoteMessageId, + NO_AUTO_DELETE_TIMER); long timestamp = 0L; GroupMessage joinGroupMessage = new GroupMessage(message, null, localAuthor); @@ -329,7 +331,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { privateGroup.getName(), privateGroup.getCreator(), privateGroup.getSalt(), getRandomString(MAX_GROUP_INVITATION_TEXT_LENGTH), - signature); + signature, NO_AUTO_DELETE_TIMER); Contact notCreatorContact = getContact(contactId, getAuthor(), localAuthor.getId(), true); @@ -352,7 +354,8 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { new InviteMessage(new MessageId(getRandomId()), contactGroupId, privateGroupId, session.getInviteTimestamp() + 1, privateGroup.getName(), privateGroup.getCreator(), - privateGroup.getSalt(), "msg", signature); + privateGroup.getSalt(), "msg", signature, + NO_AUTO_DELETE_TIMER); assertEquals(contact.getAuthor(), privateGroup.getCreator()); expectGetContactId(); @@ -505,7 +508,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { JoinMessage invalidJoinMessage = new JoinMessage(new MessageId(getRandomId()), contactGroupId, privateGroupId, session.getInviteTimestamp() + 1, - lastLocalMessageId); + lastLocalMessageId, NO_AUTO_DELETE_TIMER); assertFalse(invalidJoinMessage.getTimestamp() <= session.getInviteTimestamp()); assertNotNull(session.getLastRemoteMessageId()); @@ -525,7 +528,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { JoinMessage properJoinMessage = new JoinMessage(new MessageId(getRandomId()), contactGroupId, privateGroupId, session.getInviteTimestamp() + 1, - lastRemoteMessageId); + lastRemoteMessageId, NO_AUTO_DELETE_TIMER); assertFalse(properJoinMessage.getTimestamp() <= session.getInviteTimestamp()); assertNotNull(session.getLastRemoteMessageId()); @@ -607,7 +610,8 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { InviteeSession session = getDefaultSession(INVITED); LeaveMessage invalidLeaveMessage = new LeaveMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, session.getInviteTimestamp() + 1, null); + privateGroupId, session.getInviteTimestamp() + 1, null, + NO_AUTO_DELETE_TIMER); assertFalse(invalidLeaveMessage.getTimestamp() <= session.getInviteTimestamp()); assertNull(invalidLeaveMessage.getPreviousMessageId()); @@ -624,7 +628,8 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { InviteeSession session = getDefaultSession(LEFT); LeaveMessage invalidLeaveMessage = new LeaveMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, session.getInviteTimestamp() + 1, null); + privateGroupId, session.getInviteTimestamp() + 1, null, + NO_AUTO_DELETE_TIMER); assertFalse(invalidLeaveMessage.getTimestamp() <= session.getInviteTimestamp()); assertNull(invalidLeaveMessage.getPreviousMessageId()); @@ -641,7 +646,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { LeaveMessage properLeaveMessage = new LeaveMessage(new MessageId(getRandomId()), contactGroupId, privateGroupId, session.getInviteTimestamp() + 1, - lastRemoteMessageId); + lastRemoteMessageId, NO_AUTO_DELETE_TIMER); assertFalse(properLeaveMessage.getTimestamp() <= session.getInviteTimestamp()); assertNotNull(session.getLastRemoteMessageId()); @@ -671,7 +676,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { LeaveMessage properLeaveMessage = new LeaveMessage(new MessageId(getRandomId()), contactGroupId, privateGroupId, session.getInviteTimestamp() + 1, - lastRemoteMessageId); + lastRemoteMessageId, NO_AUTO_DELETE_TIMER); assertFalse(properLeaveMessage.getTimestamp() <= session.getInviteTimestamp()); assertNotNull(session.getLastRemoteMessageId()); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/PeerProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/PeerProtocolEngineTest.java index 05c0920c5..2be8c0a94 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/PeerProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/PeerProtocolEngineTest.java @@ -5,6 +5,7 @@ import org.briarproject.briar.api.client.ProtocolStateException; import org.jmock.Expectations; import org.junit.Test; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; @@ -17,9 +18,8 @@ import static org.briarproject.briar.privategroup.invitation.PeerState.LOCAL_LEF import static org.briarproject.briar.privategroup.invitation.PeerState.NEITHER_JOINED; import static org.briarproject.briar.privategroup.invitation.PeerState.START; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { @@ -37,43 +37,43 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { // onInviteAction @Test(expected = UnsupportedOperationException.class) - public void testOnInviteActionFromStart() throws Exception { + public void testOnInviteActionFromStart() { engine.onInviteAction(txn, getDefaultSession(START), null, messageTimestamp, signature); } @Test(expected = UnsupportedOperationException.class) - public void testOnInviteActionFromAwaitMember() throws Exception { + public void testOnInviteActionFromAwaitMember() { engine.onInviteAction(txn, getDefaultSession(AWAIT_MEMBER), null, messageTimestamp, signature); } @Test(expected = UnsupportedOperationException.class) - public void testOnInviteActionFromNeitherJoined() throws Exception { + public void testOnInviteActionFromNeitherJoined() { engine.onInviteAction(txn, getDefaultSession(NEITHER_JOINED), null, messageTimestamp, signature); } @Test(expected = UnsupportedOperationException.class) - public void testOnInviteActionFromLocalJoined() throws Exception { + public void testOnInviteActionFromLocalJoined() { engine.onInviteAction(txn, getDefaultSession(LOCAL_JOINED), null, messageTimestamp, signature); } @Test(expected = UnsupportedOperationException.class) - public void testOnInviteActionFromBothJoined() throws Exception { + public void testOnInviteActionFromBothJoined() { engine.onInviteAction(txn, getDefaultSession(BOTH_JOINED), null, messageTimestamp, signature); } @Test(expected = UnsupportedOperationException.class) - public void testOnInviteActionFromLocalLeft() throws Exception { + public void testOnInviteActionFromLocalLeft() { engine.onInviteAction(txn, getDefaultSession(LOCAL_LEFT), null, messageTimestamp, signature); } @Test(expected = UnsupportedOperationException.class) - public void testOnInviteActionFromError() throws Exception { + public void testOnInviteActionFromError() { engine.onInviteAction(txn, getDefaultSession(ERROR), null, messageTimestamp, signature); } @@ -109,7 +109,8 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { public void testOnJoinActionFromNeitherJoined() throws Exception { JoinMessage joinMessage = new JoinMessage(messageId, contactGroupId, - privateGroupId, messageTimestamp, lastRemoteMessageId); + privateGroupId, messageTimestamp, lastRemoteMessageId, + NO_AUTO_DELETE_TIMER); PeerSession session = getDefaultSession(NEITHER_JOINED); expectSendJoinMessage(joinMessage, false); @@ -125,7 +126,8 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { public void testOnJoinActionFromLocalLeft() throws Exception { JoinMessage joinMessage = new JoinMessage(messageId, contactGroupId, - privateGroupId, messageTimestamp, lastRemoteMessageId); + privateGroupId, messageTimestamp, lastRemoteMessageId, + NO_AUTO_DELETE_TIMER); PeerSession session = getDefaultSession(LOCAL_LEFT); expectSendJoinMessage(joinMessage, false); @@ -216,7 +218,8 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { public void testOnMemberAddedFromAwaitMember() throws Exception { JoinMessage joinMessage = new JoinMessage(messageId, contactGroupId, - privateGroupId, messageTimestamp, lastRemoteMessageId); + privateGroupId, messageTimestamp, lastRemoteMessageId, + NO_AUTO_DELETE_TIMER); PeerSession session = getDefaultSession(AWAIT_MEMBER); expectSendJoinMessage(joinMessage, false); @@ -361,12 +364,13 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { throws Exception { JoinMessage invalidJoinMessage = new JoinMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, 0L, lastLocalMessageId); + privateGroupId, 0L, lastLocalMessageId, + NO_AUTO_DELETE_TIMER); PeerSession session = getDefaultSession(START); assertNotNull(invalidJoinMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertFalse(invalidJoinMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertNotEquals(invalidJoinMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); expectAbortWhenNotSubscribedToGroup(); PeerSession newSession = @@ -379,8 +383,8 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { PeerSession session = getDefaultSession(START); assertNotNull(joinMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertTrue(joinMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertEquals(joinMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); PeerSession newSession = engine.onJoinMessage(txn, session, joinMessage); @@ -399,12 +403,13 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { throws Exception { JoinMessage invalidJoinMessage = new JoinMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, 0L, lastLocalMessageId); + privateGroupId, 0L, lastLocalMessageId, + NO_AUTO_DELETE_TIMER); PeerSession session = getDefaultSession(NEITHER_JOINED); assertNotNull(invalidJoinMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertFalse(invalidJoinMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertNotEquals(invalidJoinMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); expectAbortWhenNotSubscribedToGroup(); PeerSession newSession = @@ -417,10 +422,11 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { PeerSession session = getDefaultSession(NEITHER_JOINED); assertNotNull(joinMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertTrue(joinMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertEquals(joinMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); JoinMessage myJoinMessage = new JoinMessage(messageId, contactGroupId, - privateGroupId, messageTimestamp, lastRemoteMessageId); + privateGroupId, messageTimestamp, lastRemoteMessageId, + NO_AUTO_DELETE_TIMER); expectSendJoinMessage(myJoinMessage, false); expectSetPrivateGroupVisibility(SHARED); @@ -441,12 +447,13 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { throws Exception { JoinMessage invalidJoinMessage = new JoinMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, 0L, lastLocalMessageId); + privateGroupId, 0L, lastLocalMessageId, + NO_AUTO_DELETE_TIMER); PeerSession session = getDefaultSession(LOCAL_JOINED); assertNotNull(invalidJoinMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertFalse(invalidJoinMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertNotEquals(invalidJoinMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); expectAbortWhenNotSubscribedToGroup(); PeerSession newSession = @@ -459,8 +466,8 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { PeerSession session = getDefaultSession(LOCAL_JOINED); assertNotNull(joinMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertTrue(joinMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertEquals(joinMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); expectSetPrivateGroupVisibility(SHARED); expectRelationshipRevealed(false); @@ -520,12 +527,13 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { throws Exception { LeaveMessage invalidLeaveMessage = new LeaveMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, 0L, lastLocalMessageId); + privateGroupId, 0L, lastLocalMessageId, + NO_AUTO_DELETE_TIMER); PeerSession session = getDefaultSession(AWAIT_MEMBER); assertNotNull(invalidLeaveMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertFalse(invalidLeaveMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertNotEquals(invalidLeaveMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); expectAbortWhenSubscribedToGroup(); PeerSession newSession = @@ -538,8 +546,8 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { PeerSession session = getDefaultSession(AWAIT_MEMBER); assertNotNull(leaveMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertTrue(leaveMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertEquals(leaveMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); PeerSession newSession = engine.onLeaveMessage(txn, session, leaveMessage); @@ -558,12 +566,13 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { throws Exception { LeaveMessage invalidLeaveMessage = new LeaveMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, 0L, lastLocalMessageId); + privateGroupId, 0L, lastLocalMessageId, + NO_AUTO_DELETE_TIMER); PeerSession session = getDefaultSession(LOCAL_LEFT); assertNotNull(invalidLeaveMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertFalse(invalidLeaveMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertNotEquals(invalidLeaveMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); expectAbortWhenSubscribedToGroup(); PeerSession newSession = @@ -576,8 +585,8 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { PeerSession session = getDefaultSession(LOCAL_LEFT); assertNotNull(leaveMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertTrue(leaveMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertEquals(leaveMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); PeerSession newSession = engine.onLeaveMessage(txn, session, leaveMessage); @@ -596,12 +605,13 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { throws Exception { LeaveMessage invalidLeaveMessage = new LeaveMessage(new MessageId(getRandomId()), contactGroupId, - privateGroupId, 0L, lastLocalMessageId); + privateGroupId, 0L, lastLocalMessageId, + NO_AUTO_DELETE_TIMER); PeerSession session = getDefaultSession(BOTH_JOINED); assertNotNull(invalidLeaveMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertFalse(invalidLeaveMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertNotEquals(invalidLeaveMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); expectAbortWhenSubscribedToGroup(); PeerSession newSession = @@ -614,8 +624,8 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { PeerSession session = getDefaultSession(BOTH_JOINED); assertNotNull(leaveMessage.getPreviousMessageId()); assertNotNull(session.getLastRemoteMessageId()); - assertTrue(leaveMessage.getPreviousMessageId() - .equals(session.getLastRemoteMessageId())); + assertEquals(leaveMessage.getPreviousMessageId(), + session.getLastRemoteMessageId()); expectSetPrivateGroupVisibility(VISIBLE); // FIXME correct? PeerSession newSession = @@ -685,14 +695,14 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest { } private void assertSessionAborted(PeerSession oldSession, - PeerSession newSession) throws Exception { + PeerSession newSession) { assertEquals(ERROR, newSession.getState()); assertSessionRecordedSentMessage(newSession); assertSessionConstantsUnchanged(oldSession, newSession); } @Override - protected void assertSessionRecordedSentMessage(Session s) { + protected void assertSessionRecordedSentMessage(Session s) { assertEquals(messageId, s.getLastLocalMessageId()); assertEquals(lastRemoteMessageId, s.getLastRemoteMessageId()); assertEquals(messageTimestamp, s.getLocalTimestamp());