From 26fe2f804f8fb349c96807c57cb2d631badcd4e0 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 20 Nov 2020 17:08:55 +0000 Subject: [PATCH] Update blog and forum sharing clients to include self-destruct timers. --- .../briar/api/blog/BlogInvitationRequest.java | 4 +- .../api/blog/BlogInvitationResponse.java | 5 +- .../briar/api/blog/BlogSharingManager.java | 2 +- .../api/forum/ForumInvitationRequest.java | 4 +- .../api/forum/ForumInvitationResponse.java | 5 +- .../briar/api/forum/ForumSharingManager.java | 2 +- .../invitation/GroupInvitationRequest.java | 4 +- .../invitation/GroupInvitationResponse.java | 4 +- .../briar/api/sharing/InvitationRequest.java | 6 +- .../briar/api/sharing/InvitationResponse.java | 7 +- .../briar/sharing/AcceptMessage.java | 8 +- .../sharing/BlogInvitationFactoryImpl.java | 12 +- .../briar/sharing/BlogProtocolEngineImpl.java | 22 ++-- .../briar/sharing/DeclineMessage.java | 7 +- .../sharing/DeletableSharingMessage.java | 22 ++++ .../sharing/ForumInvitationFactoryImpl.java | 12 +- .../sharing/ForumProtocolEngineImpl.java | 26 ++--- .../briar/sharing/InvitationFactory.java | 4 +- .../briar/sharing/InviteMessage.java | 6 +- .../briar/sharing/MessageEncoder.java | 35 +++++- .../briar/sharing/MessageEncoderImpl.java | 66 ++++++++++- .../briar/sharing/MessageMetadata.java | 8 +- .../briar/sharing/MessageParserImpl.java | 18 ++- .../briar/sharing/ProtocolEngineImpl.java | 110 +++++++++++++----- .../briar/sharing/SharingConstants.java | 1 + .../briar/sharing/SharingManagerImpl.java | 6 +- .../briar/sharing/SharingValidator.java | 70 ++++++++--- .../sharing/BlogSharingValidatorTest.java | 64 +++++++++- .../sharing/ForumSharingValidatorTest.java | 64 +++++++++- .../briar/sharing/SharingValidatorTest.java | 100 ++++++++++++++-- 30 files changed, 562 insertions(+), 142 deletions(-) create mode 100644 briar-core/src/main/java/org/briarproject/briar/sharing/DeletableSharingMessage.java diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationRequest.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationRequest.java index 8250dbc71..2f2db1da8 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationRequest.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationRequest.java @@ -15,9 +15,9 @@ public class BlogInvitationRequest extends InvitationRequest { public BlogInvitationRequest(MessageId id, GroupId groupId, long time, boolean local, boolean read, boolean sent, boolean seen, SessionId sessionId, Blog blog, @Nullable String text, - boolean available, boolean canBeOpened) { + boolean available, boolean canBeOpened, long autoDeleteTimer) { super(id, groupId, time, local, read, sent, seen, sessionId, blog, - text, available, canBeOpened); + text, available, canBeOpened, autoDeleteTimer); } @Override diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java index 29b3553f9..37cfef49a 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogInvitationResponse.java @@ -12,9 +12,10 @@ public class BlogInvitationResponse extends InvitationResponse { public BlogInvitationResponse(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); + accept, shareableId, autoDeleteTimer); } @Override diff --git a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingManager.java b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingManager.java index f2f04afc5..cf03267b1 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/blog/BlogSharingManager.java @@ -18,5 +18,5 @@ public interface BlogSharingManager extends SharingManager { /** * The current minor version of the blog sharing client. */ - int MINOR_VERSION = 0; + int MINOR_VERSION = 1; } diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationRequest.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationRequest.java index 26d0e94c9..954e344bf 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationRequest.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationRequest.java @@ -17,9 +17,9 @@ public class ForumInvitationRequest extends InvitationRequest { public ForumInvitationRequest(MessageId id, GroupId groupId, long time, boolean local, boolean read, boolean sent, boolean seen, SessionId sessionId, Forum forum, @Nullable String text, - boolean available, boolean canBeOpened) { + boolean available, boolean canBeOpened, long autoDeleteTimer) { super(id, groupId, time, local, read, sent, seen, sessionId, forum, - text, available, canBeOpened); + text, available, canBeOpened, autoDeleteTimer); } @Override diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java index edaeb2cf0..be3757e35 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumInvitationResponse.java @@ -15,9 +15,10 @@ public class ForumInvitationResponse extends InvitationResponse { public ForumInvitationResponse(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); + accept, shareableId, autoDeleteTimer); } @Override diff --git a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingManager.java b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingManager.java index 29b2468d0..1ff441326 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/forum/ForumSharingManager.java @@ -18,5 +18,5 @@ public interface ForumSharingManager extends SharingManager { /** * The current minor version of the forum sharing client. */ - int MINOR_VERSION = 0; + int MINOR_VERSION = 1; } 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 caab08faf..6f6abb93b 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,6 +11,8 @@ 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,7 +22,7 @@ public class GroupInvitationRequest extends InvitationRequest { SessionId sessionId, PrivateGroup shareable, @Nullable String text, boolean available, boolean canBeOpened) { super(id, groupId, time, local, read, sent, seen, sessionId, shareable, - text, available, canBeOpened); + text, available, canBeOpened, NO_AUTO_DELETE_TIMER); } @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 a6d72ae0a..0c6b79e34 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,6 +9,8 @@ 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 { @@ -17,7 +19,7 @@ public class GroupInvitationResponse extends InvitationResponse { boolean local, boolean read, boolean sent, boolean seen, SessionId sessionId, boolean accept, GroupId shareableId) { super(id, groupId, time, local, read, sent, seen, sessionId, - accept, shareableId); + accept, shareableId, NO_AUTO_DELETE_TIMER); } @Override diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationRequest.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationRequest.java index 432d71cf5..80a6f881a 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationRequest.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationRequest.java @@ -7,8 +7,6 @@ import org.briarproject.briar.api.conversation.ConversationRequest; import javax.annotation.Nullable; -import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; - public abstract class InvitationRequest extends ConversationRequest { @@ -17,9 +15,9 @@ public abstract class InvitationRequest extends public InvitationRequest(MessageId messageId, GroupId groupId, long time, boolean local, boolean read, boolean sent, boolean seen, SessionId sessionId, S object, @Nullable String text, - boolean available, boolean canBeOpened) { + boolean available, boolean canBeOpened, long autoDeleteTimer) { super(messageId, groupId, time, local, read, sent, seen, sessionId, - object, text, !available, NO_AUTO_DELETE_TIMER); + object, text, !available, autoDeleteTimer); this.canBeOpened = canBeOpened; } diff --git a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java index 6a305cf7c..fd14fa051 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/sharing/InvitationResponse.java @@ -5,17 +5,16 @@ import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.conversation.ConversationResponse; -import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; - public abstract class InvitationResponse extends ConversationResponse { private final GroupId shareableId; public InvitationResponse(MessageId id, GroupId groupId, long time, boolean local, boolean read, boolean sent, boolean seen, - SessionId sessionId, boolean accepted, GroupId shareableId) { + SessionId sessionId, boolean accepted, GroupId shareableId, + long autoDeleteTimer) { super(id, groupId, time, local, read, sent, seen, sessionId, accepted, - NO_AUTO_DELETE_TIMER); + autoDeleteTimer); this.shareableId = shareableId; } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/AcceptMessage.java b/briar-core/src/main/java/org/briarproject/briar/sharing/AcceptMessage.java index 0a440a5cd..33644cb63 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/AcceptMessage.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/AcceptMessage.java @@ -9,11 +9,13 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -class AcceptMessage extends SharingMessage { +class AcceptMessage extends DeletableSharingMessage { AcceptMessage(MessageId id, @Nullable MessageId previousMessageId, - GroupId contactGroupId, GroupId shareableId, long timestamp) { - super(id, contactGroupId, shareableId, timestamp, previousMessageId); + GroupId contactGroupId, GroupId shareableId, long timestamp, + long autoDeleteTimer) { + super(id, contactGroupId, shareableId, timestamp, previousMessageId, + autoDeleteTimer); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInvitationFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInvitationFactoryImpl.java index 10f4d1e31..afa8f4046 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInvitationFactoryImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogInvitationFactoryImpl.java @@ -20,20 +20,24 @@ public class BlogInvitationFactoryImpl @Override public BlogInvitationRequest createInvitationRequest(boolean local, boolean sent, boolean seen, boolean read, InviteMessage m, - ContactId c, boolean available, boolean canBeOpened) { + ContactId c, boolean available, boolean canBeOpened, + long autoDeleteTimer) { SessionId sessionId = new SessionId(m.getShareableId().getBytes()); return new BlogInvitationRequest(m.getId(), m.getContactGroupId(), m.getTimestamp(), local, read, sent, seen, sessionId, - m.getShareable(), m.getText(), available, canBeOpened); + m.getShareable(), m.getText(), available, canBeOpened, + autoDeleteTimer); } @Override public BlogInvitationResponse createInvitationResponse(MessageId id, GroupId contactGroupId, long time, boolean local, boolean sent, - boolean seen, boolean read, boolean accept, GroupId shareableId) { + boolean seen, boolean read, boolean accept, GroupId shareableId, + long autoDeleteTimer) { SessionId sessionId = new SessionId(shareableId.getBytes()); return new BlogInvitationResponse(id, contactGroupId, time, local, read, - sent, seen, sessionId, accept, shareableId); + sent, seen, sessionId, accept, shareableId, + autoDeleteTimer); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java index d9454f0b8..79dfaaa42 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/BlogProtocolEngineImpl.java @@ -8,13 +8,13 @@ import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.bramble.api.sync.ClientId; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.versioning.ClientVersioningManager; import org.briarproject.briar.api.blog.Blog; import org.briarproject.briar.api.blog.BlogInvitationResponse; import org.briarproject.briar.api.blog.BlogManager; +import org.briarproject.briar.api.blog.BlogSharingManager; import org.briarproject.briar.api.blog.event.BlogInvitationRequestReceivedEvent; import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent; import org.briarproject.briar.api.client.MessageTracker; @@ -23,9 +23,6 @@ import org.briarproject.briar.api.conversation.ConversationRequest; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; -import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID; -import static org.briarproject.briar.api.blog.BlogManager.MAJOR_VERSION; - @Immutable @NotNullByDefault class BlogProtocolEngineImpl extends ProtocolEngineImpl { @@ -41,8 +38,9 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl { MessageTracker messageTracker, Clock clock, BlogManager blogManager, InvitationFactory invitationFactory) { super(db, clientHelper, clientVersioningManager, messageEncoder, - messageParser, messageTracker, clock, CLIENT_ID, - MAJOR_VERSION); + messageParser, messageTracker, clock, + BlogSharingManager.CLIENT_ID, BlogSharingManager.MAJOR_VERSION, + BlogManager.CLIENT_ID, BlogManager.MAJOR_VERSION); this.blogManager = blogManager; this.invitationFactory = invitationFactory; } @@ -52,7 +50,8 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl { ContactId contactId, boolean available, boolean canBeOpened) { ConversationRequest request = invitationFactory .createInvitationRequest(false, false, true, false, m, - contactId, available, canBeOpened); + contactId, available, canBeOpened, + m.getAutoDeleteTimer()); return new BlogInvitationRequestReceivedEvent(request, contactId); } @@ -62,7 +61,7 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl { BlogInvitationResponse response = invitationFactory .createInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, false, false, - true, m.getShareableId()); + true, m.getShareableId(), m.getAutoDeleteTimer()); return new BlogInvitationResponseReceivedEvent(response, contactId); } @@ -72,15 +71,10 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl { BlogInvitationResponse response = invitationFactory .createInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, false, false, - false, m.getShareableId()); + false, m.getShareableId(), m.getAutoDeleteTimer()); return new BlogInvitationResponseReceivedEvent(response, contactId); } - @Override - protected ClientId getShareableClientId() { - return CLIENT_ID; - } - @Override protected void addShareable(Transaction txn, MessageId inviteId) throws DbException, FormatException { diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/DeclineMessage.java b/briar-core/src/main/java/org/briarproject/briar/sharing/DeclineMessage.java index 65f9a9fe1..e392ef701 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/DeclineMessage.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/DeclineMessage.java @@ -9,12 +9,13 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -class DeclineMessage extends SharingMessage { +class DeclineMessage extends DeletableSharingMessage { DeclineMessage(MessageId id, GroupId contactGroupId, GroupId shareableId, long timestamp, - @Nullable MessageId previousMessageId) { - super(id, contactGroupId, shareableId, timestamp, previousMessageId); + @Nullable MessageId previousMessageId, long autoDeleteTimer) { + super(id, contactGroupId, shareableId, timestamp, previousMessageId, + autoDeleteTimer); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/DeletableSharingMessage.java b/briar-core/src/main/java/org/briarproject/briar/sharing/DeletableSharingMessage.java new file mode 100644 index 000000000..c4dca6f87 --- /dev/null +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/DeletableSharingMessage.java @@ -0,0 +1,22 @@ +package org.briarproject.briar.sharing; + +import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.sync.MessageId; + +import javax.annotation.Nullable; + +abstract class DeletableSharingMessage extends SharingMessage { + + private final long autoDeleteTimer; + + DeletableSharingMessage(MessageId id, GroupId contactGroupId, + GroupId shareableId, long timestamp, + @Nullable MessageId previousMessageId, long autoDeleteTimer) { + super(id, contactGroupId, shareableId, timestamp, previousMessageId); + this.autoDeleteTimer = autoDeleteTimer; + } + + public long getAutoDeleteTimer() { + return autoDeleteTimer; + } +} diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInvitationFactoryImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInvitationFactoryImpl.java index 09fcd9896..a83b37102 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInvitationFactoryImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumInvitationFactoryImpl.java @@ -20,20 +20,24 @@ public class ForumInvitationFactoryImpl @Override public ForumInvitationRequest createInvitationRequest(boolean local, boolean sent, boolean seen, boolean read, InviteMessage m, - ContactId c, boolean available, boolean canBeOpened) { + ContactId c, boolean available, boolean canBeOpened, + long autoDeleteTimer) { SessionId sessionId = new SessionId(m.getShareableId().getBytes()); return new ForumInvitationRequest(m.getId(), m.getContactGroupId(), m.getTimestamp(), local, read, sent, seen, sessionId, - m.getShareable(), m.getText(), available, canBeOpened); + m.getShareable(), m.getText(), available, canBeOpened, + autoDeleteTimer); } @Override public ForumInvitationResponse createInvitationResponse(MessageId id, GroupId contactGroupId, long time, boolean local, boolean sent, - boolean seen, boolean read, boolean accept, GroupId shareableId) { + boolean seen, boolean read, boolean accept, GroupId shareableId, + long autoDeleteTimer) { SessionId sessionId = new SessionId(shareableId.getBytes()); return new ForumInvitationResponse(id, contactGroupId, time, local, - read, sent, seen, sessionId, accept, shareableId); + read, sent, seen, sessionId, accept, shareableId, + autoDeleteTimer); } } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java index 22acc4231..e6df8fc48 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ForumProtocolEngineImpl.java @@ -8,7 +8,6 @@ import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; -import org.briarproject.bramble.api.sync.ClientId; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.versioning.ClientVersioningManager; @@ -17,21 +16,20 @@ import org.briarproject.briar.api.conversation.ConversationRequest; import org.briarproject.briar.api.forum.Forum; import org.briarproject.briar.api.forum.ForumInvitationResponse; import org.briarproject.briar.api.forum.ForumManager; +import org.briarproject.briar.api.forum.ForumSharingManager; import org.briarproject.briar.api.forum.event.ForumInvitationRequestReceivedEvent; import org.briarproject.briar.api.forum.event.ForumInvitationResponseReceivedEvent; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; -import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID; -import static org.briarproject.briar.api.forum.ForumManager.MAJOR_VERSION; - @Immutable @NotNullByDefault class ForumProtocolEngineImpl extends ProtocolEngineImpl { private final ForumManager forumManager; - private final InvitationFactory invitationFactory; + private final InvitationFactory + invitationFactory; @Inject ForumProtocolEngineImpl(DatabaseComponent db, @@ -42,8 +40,10 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl { ForumManager forumManager, InvitationFactory invitationFactory) { super(db, clientHelper, clientVersioningManager, messageEncoder, - messageParser, messageTracker, clock, CLIENT_ID, - MAJOR_VERSION); + messageParser, messageTracker, clock, + ForumSharingManager.CLIENT_ID, + ForumSharingManager.MAJOR_VERSION, + ForumManager.CLIENT_ID, ForumManager.MAJOR_VERSION); this.forumManager = forumManager; this.invitationFactory = invitationFactory; } @@ -53,7 +53,8 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl { ContactId contactId, boolean available, boolean canBeOpened) { ConversationRequest request = invitationFactory .createInvitationRequest(false, false, true, false, m, - contactId, available, canBeOpened); + contactId, available, canBeOpened, + m.getAutoDeleteTimer()); return new ForumInvitationRequestReceivedEvent(request, contactId); } @@ -63,7 +64,7 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl { ForumInvitationResponse response = invitationFactory .createInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, true, false, - true, m.getShareableId()); + true, m.getShareableId(), m.getAutoDeleteTimer()); return new ForumInvitationResponseReceivedEvent(response, contactId); } @@ -73,15 +74,10 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl { ForumInvitationResponse response = invitationFactory .createInvitationResponse(m.getId(), m.getContactGroupId(), m.getTimestamp(), false, false, true, false, - false, m.getShareableId()); + false, m.getShareableId(), m.getAutoDeleteTimer()); return new ForumInvitationResponseReceivedEvent(response, contactId); } - @Override - protected ClientId getShareableClientId() { - return CLIENT_ID; - } - @Override protected void addShareable(Transaction txn, MessageId inviteId) throws DbException, FormatException { diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java index 6c7287649..c156df0e2 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/InvitationFactory.java @@ -11,10 +11,10 @@ public interface InvitationFactory createInvitationRequest(boolean local, boolean sent, boolean seen, boolean read, InviteMessage m, ContactId c, - boolean available, boolean canBeOpened); + boolean available, boolean canBeOpened, long autoDeleteTimer); R createInvitationResponse(MessageId id, GroupId contactGroupId, long time, boolean local, boolean sent, boolean seen, boolean read, - boolean accept, GroupId shareableId); + boolean accept, GroupId shareableId, long autoDeleteTimer); } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/InviteMessage.java b/briar-core/src/main/java/org/briarproject/briar/sharing/InviteMessage.java index d94fe4f60..d83a3a3f7 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/InviteMessage.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/InviteMessage.java @@ -10,7 +10,7 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -class InviteMessage extends SharingMessage { +class InviteMessage extends DeletableSharingMessage { private final S shareable; @Nullable @@ -18,9 +18,9 @@ class InviteMessage extends SharingMessage { InviteMessage(MessageId id, @Nullable MessageId previousMessageId, GroupId contactGroupId, S shareable, @Nullable String text, - long timestamp) { + long timestamp, long autoDeleteTimer) { super(id, contactGroupId, shareable.getId(), timestamp, - previousMessageId); + previousMessageId, autoDeleteTimer); if (text != null && text.isEmpty()) throw new IllegalArgumentException(); this.shareable = shareable; diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageEncoder.java b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageEncoder.java index 6723ea0bb..a7d823531 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageEncoder.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageEncoder.java @@ -14,7 +14,7 @@ interface MessageEncoder { BdfDictionary encodeMetadata(MessageType type, GroupId shareableId, 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, long timestamp, @Nullable MessageId previousMessageId, BdfList descriptor, @Nullable String text); + /** + * 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, long timestamp, + @Nullable MessageId previousMessageId, BdfList descriptor, + @Nullable String text, long autoDeleteTimer); + + /** + * Encodes an accept message without an auto-delete timer. + */ Message encodeAcceptMessage(GroupId contactGroupId, GroupId shareableId, long timestamp, @Nullable MessageId previousMessageId); + /** + * Encodes an accept message with an optional auto-delete timer. This + * requires the contact to support client version 0.1 or higher. + */ + Message encodeAcceptMessage(GroupId contactGroupId, GroupId shareableId, + long timestamp, @Nullable MessageId previousMessageId, + long autoDeleteTimer); + + /** + * Encodes a decline message without an auto-delete timer. + */ Message encodeDeclineMessage(GroupId contactGroupId, GroupId shareableId, long timestamp, @Nullable MessageId previousMessageId); + /** + * Encodes a decline message with an optional auto-delete timer. This + * requires the contact to support client version 0.1 or higher. + */ + Message encodeDeclineMessage(GroupId contactGroupId, GroupId shareableId, + long timestamp, @Nullable MessageId previousMessageId, + long autoDeleteTimer); + Message encodeLeaveMessage(GroupId contactGroupId, GroupId shareableId, long timestamp, @Nullable MessageId previousMessageId); diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageEncoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageEncoderImpl.java index 295fcf871..42d5985d8 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageEncoderImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageEncoderImpl.java @@ -14,11 +14,13 @@ 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.sharing.MessageType.ABORT; import static org.briarproject.briar.sharing.MessageType.ACCEPT; import static org.briarproject.briar.sharing.MessageType.DECLINE; import static org.briarproject.briar.sharing.MessageType.INVITE; import static org.briarproject.briar.sharing.MessageType.LEAVE; +import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_AUTO_DELETE_TIMER; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_AVAILABLE_TO_ANSWER; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_INVITATION_ACCEPTED; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_LOCAL; @@ -45,7 +47,8 @@ class MessageEncoderImpl implements MessageEncoder { @Override public BdfDictionary encodeMetadata(MessageType type, GroupId shareableId, 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_SHAREABLE_ID, shareableId); @@ -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; } @@ -93,6 +99,27 @@ class MessageEncoderImpl implements MessageEncoder { } } + @Override + public Message encodeInviteMessage(GroupId contactGroupId, long timestamp, + @Nullable MessageId previousMessageId, BdfList descriptor, + @Nullable String text, long autoDeleteTimer) { + if (text != null && text.isEmpty()) + throw new IllegalArgumentException(); + BdfList body = BdfList.of( + INVITE.getValue(), + previousMessageId, + descriptor, + text, + encodeTimer(autoDeleteTimer) + ); + try { + return messageFactory.createMessage(contactGroupId, timestamp, + clientHelper.toByteArray(body)); + } catch (FormatException e) { + throw new AssertionError(e); + } + } + @Override public Message encodeAcceptMessage(GroupId contactGroupId, GroupId shareableId, long timestamp, @@ -101,6 +128,14 @@ class MessageEncoderImpl implements MessageEncoder { previousMessageId); } + @Override + public Message encodeAcceptMessage(GroupId contactGroupId, + GroupId shareableId, long timestamp, + @Nullable MessageId previousMessageId, long autoDeleteTimer) { + return encodeMessage(ACCEPT, contactGroupId, shareableId, timestamp, + previousMessageId, autoDeleteTimer); + } + @Override public Message encodeDeclineMessage(GroupId contactGroupId, GroupId shareableId, long timestamp, @@ -109,6 +144,14 @@ class MessageEncoderImpl implements MessageEncoder { previousMessageId); } + @Override + public Message encodeDeclineMessage(GroupId contactGroupId, + GroupId shareableId, long timestamp, + @Nullable MessageId previousMessageId, long autoDeleteTimer) { + return encodeMessage(DECLINE, contactGroupId, shareableId, timestamp, + previousMessageId, autoDeleteTimer); + } + @Override public Message encodeLeaveMessage(GroupId contactGroupId, GroupId shareableId, long timestamp, @@ -141,4 +184,25 @@ class MessageEncoderImpl implements MessageEncoder { } } + private Message encodeMessage(MessageType type, GroupId contactGroupId, + GroupId shareableId, long timestamp, + @Nullable MessageId previousMessageId, long autoDeleteTimer) { + BdfList body = BdfList.of( + type.getValue(), + shareableId, + previousMessageId, + encodeTimer(autoDeleteTimer) + ); + try { + return messageFactory.createMessage(contactGroupId, timestamp, + clientHelper.toByteArray(body)); + } catch (FormatException e) { + 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/sharing/MessageMetadata.java b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageMetadata.java index a9f1662d5..34f096b8b 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageMetadata.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageMetadata.java @@ -11,12 +11,12 @@ class MessageMetadata { private final MessageType type; private final GroupId shareableId; - private final long timestamp; + private final long timestamp, autoDeleteTimer; private final boolean local, read, visible, available, accepted; MessageMetadata(MessageType type, GroupId shareableId, long timestamp, boolean local, boolean read, boolean visible, boolean available, - boolean accepted) { + boolean accepted, long autoDeleteTimer) { this.shareableId = shareableId; 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/sharing/MessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java index 48a001c4a..2cadda417 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/MessageParserImpl.java @@ -15,7 +15,9 @@ import org.briarproject.briar.api.sharing.Shareable; import javax.annotation.concurrent.Immutable; +import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER; import static org.briarproject.briar.sharing.MessageType.INVITE; +import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_AUTO_DELETE_TIMER; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_AVAILABLE_TO_ANSWER; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_INVITATION_ACCEPTED; import static org.briarproject.briar.sharing.SharingConstants.MSG_KEY_LOCAL; @@ -70,8 +72,10 @@ abstract class MessageParserImpl 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, shareableId, timestamp, local, read, - visible, available, accepted); + visible, available, accepted, timer); } @Override @@ -90,8 +94,10 @@ abstract class MessageParserImpl BdfList descriptor = body.getList(2); S shareable = createShareable(descriptor); String text = body.getOptionalString(3); + long timer = NO_AUTO_DELETE_TIMER; + if (body.size() == 5) timer = body.getLong(4, NO_AUTO_DELETE_TIMER); return new InviteMessage<>(m.getId(), previousMessageId, - m.getGroupId(), shareable, text, m.getTimestamp()); + m.getGroupId(), shareable, text, m.getTimestamp(), timer); } @Override @@ -100,8 +106,10 @@ abstract class MessageParserImpl GroupId shareableId = 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 AcceptMessage(m.getId(), previousMessageId, m.getGroupId(), - shareableId, m.getTimestamp()); + shareableId, m.getTimestamp(), timer); } @Override @@ -110,8 +118,10 @@ abstract class MessageParserImpl GroupId shareableId = 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 DeclineMessage(m.getId(), m.getGroupId(), shareableId, - m.getTimestamp(), previousMessageId); + m.getTimestamp(), previousMessageId, timer); } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java index 8e151e0cc..9d47cf327 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/ProtocolEngineImpl.java @@ -28,6 +28,7 @@ import java.util.Map; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +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; @@ -57,14 +58,15 @@ abstract class ProtocolEngineImpl private final MessageEncoder messageEncoder; private final MessageTracker messageTracker; private final Clock clock; - private final ClientId shareableClientId; - private final int shareableClientVersion; + private final ClientId sharingClientId, shareableClientId; + private final int sharingClientMajorVersion, shareableClientMajorVersion; ProtocolEngineImpl(DatabaseComponent db, ClientHelper clientHelper, ClientVersioningManager clientVersioningManager, MessageEncoder messageEncoder, MessageParser messageParser, MessageTracker messageTracker, Clock clock, - ClientId shareableClientId, int shareableClientVersion) { + ClientId sharingClientId, int sharingClientMajorVersion, + ClientId shareableClientId, int shareableClientMajorVersion) { this.db = db; this.clientHelper = clientHelper; this.clientVersioningManager = clientVersioningManager; @@ -72,8 +74,10 @@ abstract class ProtocolEngineImpl this.messageParser = messageParser; this.messageTracker = messageTracker; this.clock = clock; + this.sharingClientId = sharingClientId; + this.sharingClientMajorVersion = sharingClientMajorVersion; this.shareableClientId = shareableClientId; - this.shareableClientVersion = shareableClientVersion; + this.shareableClientMajorVersion = shareableClientMajorVersion; } @Override @@ -121,9 +125,21 @@ abstract class ProtocolEngineImpl throw new DbException(e); // Invalid group descriptor } long localTimestamp = Math.max(timestamp, getLocalTimestamp(s)); - Message m = messageEncoder.encodeInviteMessage(s.getContactGroupId(), - localTimestamp, s.getLastLocalMessageId(), descriptor, text); - sendMessage(txn, m, INVITE, s.getShareableId(), 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(), + localTimestamp, s.getLastLocalMessageId(), descriptor, + text, timer); + sendMessage(txn, m, INVITE, s.getShareableId(), true, timer); + } else { + m = messageEncoder.encodeInviteMessage(s.getContactGroupId(), + localTimestamp, s.getLastLocalMessageId(), descriptor, + text); + sendMessage(txn, m, INVITE, s.getShareableId(), true, + NO_AUTO_DELETE_TIMER); + } return m; } @@ -173,12 +189,23 @@ abstract class ProtocolEngineImpl protected abstract void addShareable(Transaction txn, MessageId inviteId) throws DbException, FormatException; - private Message sendAcceptMessage(Transaction txn, Session session) + private Message sendAcceptMessage(Transaction txn, Session s) throws DbException { - Message m = messageEncoder.encodeAcceptMessage( - session.getContactGroupId(), session.getShareableId(), - getLocalTimestamp(session), session.getLastLocalMessageId()); - sendMessage(txn, m, ACCEPT, session.getShareableId(), true); + Message m; + if (contactSupportsAutoDeletion(txn, s.getContactGroupId())) { + // TODO: Look up the current auto-delete timer + long timer = NO_AUTO_DELETE_TIMER; + m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(), + s.getShareableId(), getLocalTimestamp(s), + s.getLastLocalMessageId(), timer); + sendMessage(txn, m, ACCEPT, s.getShareableId(), true, timer); + } else { + m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(), + s.getShareableId(), getLocalTimestamp(s), + s.getLastLocalMessageId()); + sendMessage(txn, m, ACCEPT, s.getShareableId(), true, + NO_AUTO_DELETE_TIMER); + } return m; } @@ -215,12 +242,23 @@ abstract class ProtocolEngineImpl s.getInviteTimestamp()); } - private Message sendDeclineMessage(Transaction txn, Session session) + private Message sendDeclineMessage(Transaction txn, Session s) throws DbException { - Message m = messageEncoder.encodeDeclineMessage( - session.getContactGroupId(), session.getShareableId(), - getLocalTimestamp(session), session.getLastLocalMessageId()); - sendMessage(txn, m, DECLINE, session.getShareableId(), true); + Message m; + if (contactSupportsAutoDeletion(txn, s.getContactGroupId())) { + // TODO: Look up the current auto-delete timer + long timer = NO_AUTO_DELETE_TIMER; + m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(), + s.getShareableId(), getLocalTimestamp(s), + s.getLastLocalMessageId(), timer); + sendMessage(txn, m, DECLINE, s.getShareableId(), true, timer); + } else { + m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(), + s.getShareableId(), getLocalTimestamp(s), + s.getLastLocalMessageId()); + sendMessage(txn, m, DECLINE, s.getShareableId(), true, + NO_AUTO_DELETE_TIMER); + } return m; } @@ -263,7 +301,8 @@ abstract class ProtocolEngineImpl Message m = messageEncoder.encodeLeaveMessage( session.getContactGroupId(), session.getShareableId(), getLocalTimestamp(session), session.getLastLocalMessageId()); - sendMessage(txn, m, LEAVE, session.getShareableId(), false); + sendMessage(txn, m, LEAVE, session.getShareableId(), false, + NO_AUTO_DELETE_TIMER); return m; } @@ -547,26 +586,25 @@ abstract class ProtocolEngineImpl throws DbException { if (!db.containsGroup(txn, g)) return false; Group group = db.getGroup(txn, g); - return group.getClientId().equals(getShareableClientId()); + return group.getClientId().equals(shareableClientId); } - protected abstract ClientId getShareableClientId(); - private Message sendAbortMessage(Transaction txn, Session session) throws DbException { Message m = messageEncoder.encodeAbortMessage( session.getContactGroupId(), session.getShareableId(), getLocalTimestamp(session), session.getLastLocalMessageId()); - sendMessage(txn, m, ABORT, session.getShareableId(), false); + sendMessage(txn, m, ABORT, session.getShareableId(), false, + NO_AUTO_DELETE_TIMER); return m; } private void sendMessage(Transaction txn, Message m, MessageType type, - GroupId shareableId, boolean visibleInConversation) - throws DbException { - BdfDictionary meta = messageEncoder - .encodeMetadata(type, shareableId, m.getTimestamp(), true, true, - visibleInConversation, false, false); + GroupId shareableId, boolean visibleInConversation, + long autoDeleteTimer) throws DbException { + BdfDictionary meta = messageEncoder.encodeMetadata(type, shareableId, + m.getTimestamp(), true, true, visibleInConversation, false, + false, autoDeleteTimer); try { clientHelper.addLocalMessage(txn, m, meta, true, false); } catch (FormatException e) { @@ -612,7 +650,7 @@ abstract class ProtocolEngineImpl // Apply min of preferred visibility and client's visibility ContactId contactId = getContactId(txn, session.getContactGroupId()); Visibility client = clientVersioningManager.getClientVisibility(txn, - contactId, shareableClientId, shareableClientVersion); + contactId, shareableClientId, shareableClientMajorVersion); Visibility min = Visibility.min(preferred, client); db.setGroupVisibility(txn, contactId, session.getShareableId(), min); } @@ -637,4 +675,20 @@ abstract class ProtocolEngineImpl session.getInviteTimestamp()) + 1); } + 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, sharingClientId, + sharingClientMajorVersion); + // 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/sharing/SharingConstants.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java index f2522d1a9..9d45467a5 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingConstants.java @@ -16,6 +16,7 @@ interface SharingConstants { 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/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java index 4a24ece90..82f2a0d9a 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java @@ -368,7 +368,8 @@ abstract class SharingManagerImpl return invitationFactory .createInvitationRequest(meta.isLocal(), status.isSent(), status.isSeen(), meta.isRead(), invite, c, - meta.isAvailableToAnswer(), canBeOpened); + meta.isAvailableToAnswer(), canBeOpened, + meta.getAutoDeleteTimer()); } private InvitationResponse parseInvitationResponse(GroupId contactGroupId, @@ -376,7 +377,8 @@ abstract class SharingManagerImpl boolean accept) { return invitationFactory.createInvitationResponse(m, contactGroupId, meta.getTimestamp(), meta.isLocal(), status.isSent(), - status.isSeen(), meta.isRead(), accept, meta.getShareableId()); + status.isSeen(), meta.isRead(), accept, meta.getShareableId(), + meta.getAutoDeleteTimer()); } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingValidator.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingValidator.java index dcf38bf7b..f8cd581ea 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingValidator.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingValidator.java @@ -15,11 +15,15 @@ import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.system.Clock; -import java.util.Collections; - +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +import static java.util.Collections.singletonList; +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.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.sharing.SharingConstants.MAX_INVITATION_TEXT_LENGTH; import static org.briarproject.briar.sharing.MessageType.INVITE; @@ -45,9 +49,10 @@ abstract class SharingValidator extends BdfMessageValidator { return validateInviteMessage(m, body); case ACCEPT: case DECLINE: + return validateNonInviteMessageWithOptionalTimer(type, m, body); case LEAVE: case ABORT: - return validateNonInviteMessage(type, m, body); + return validateNonInviteMessageWithoutTimer(type, m, body); default: throw new FormatException(); } @@ -55,47 +60,80 @@ abstract class SharingValidator extends BdfMessageValidator { private BdfMessageContext validateInviteMessage(Message m, BdfList body) throws FormatException { - checkSize(body, 4); + // Client version 0.0: Message type, optional previous message ID, + // descriptor, optional text. + // Client version 0.1: Message type, optional previous message ID, + // descriptor, optional text, optional auto-delete timer. + checkSize(body, 4, 5); byte[] previousMessageId = body.getOptionalRaw(1); checkLength(previousMessageId, UniqueId.LENGTH); BdfList descriptor = body.getList(2); GroupId shareableId = validateDescriptor(descriptor); String text = body.getOptionalString(3); checkLength(text, 1, MAX_INVITATION_TEXT_LENGTH); + long timer = NO_AUTO_DELETE_TIMER; + if (body.size() == 5) timer = validateTimer(body.getOptionalLong(4)); - BdfDictionary meta = messageEncoder - .encodeMetadata(INVITE, shareableId, m.getTimestamp(), false, - false, false, false, false); + BdfDictionary meta = messageEncoder.encodeMetadata(INVITE, shareableId, + m.getTimestamp(), false, false, false, false, false, timer); if (previousMessageId == null) { return new BdfMessageContext(meta); } else { MessageId dependency = new MessageId(previousMessageId); - return new BdfMessageContext(meta, - Collections.singletonList(dependency)); + return new BdfMessageContext(meta, singletonList(dependency)); } } protected abstract GroupId validateDescriptor(BdfList descriptor) throws FormatException; - private BdfMessageContext validateNonInviteMessage(MessageType type, - Message m, BdfList body) throws FormatException { + private BdfMessageContext validateNonInviteMessageWithoutTimer( + MessageType type, Message m, BdfList body) throws FormatException { checkSize(body, 3); byte[] shareableId = body.getRaw(1); checkLength(shareableId, UniqueId.LENGTH); byte[] previousMessageId = body.getOptionalRaw(2); checkLength(previousMessageId, UniqueId.LENGTH); - BdfDictionary meta = messageEncoder - .encodeMetadata(type, new GroupId(shareableId), - m.getTimestamp(), false, false, false, false, false); + BdfDictionary meta = messageEncoder.encodeMetadata(type, + new GroupId(shareableId), m.getTimestamp(), false, false, + false, false, false, NO_AUTO_DELETE_TIMER); if (previousMessageId == null) { return new BdfMessageContext(meta); } else { MessageId dependency = new MessageId(previousMessageId); - return new BdfMessageContext(meta, - Collections.singletonList(dependency)); + return new BdfMessageContext(meta, singletonList(dependency)); } } + private BdfMessageContext validateNonInviteMessageWithOptionalTimer( + MessageType type, Message m, BdfList body) throws FormatException { + // Client version 0.0: Message type, shareable ID, optional previous + // message ID. + // Client version 0.1: Message type, shareable ID, optional previous + // message ID, optional auto-delete timer. + checkSize(body, 3, 4); + byte[] shareableId = body.getRaw(1); + checkLength(shareableId, 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(type, + new GroupId(shareableId), m.getTimestamp(), false, false, + false, false, false, timer); + if (previousMessageId == null) { + return new BdfMessageContext(meta); + } else { + MessageId dependency = new MessageId(previousMessageId); + return new BdfMessageContext(meta, singletonList(dependency)); + } + } + + 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/test/java/org/briarproject/briar/sharing/BlogSharingValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingValidatorTest.java index 01b0ffd2a..8ce003360 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingValidatorTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingValidatorTest.java @@ -8,10 +8,16 @@ import org.briarproject.briar.api.blog.Blog; import org.jmock.Expectations; import org.junit.Test; +import javax.annotation.Nullable; + +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.test.TestUtils.getAuthor; import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_TEXT_LENGTH; import static org.briarproject.briar.sharing.MessageType.INVITE; +import static org.junit.Assert.fail; public class BlogSharingValidatorTest extends SharingValidatorTest { @@ -31,7 +37,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest { @Test public void testAcceptsInvitationWithText() throws Exception { expectCreateBlog(); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), previousMsgId, descriptor, text)); assertExpectedContext(context, previousMsgId); @@ -40,7 +46,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest { @Test public void testAcceptsInvitationWithNullText() throws Exception { expectCreateBlog(); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), previousMsgId, descriptor, null)); assertExpectedContext(context, previousMsgId); @@ -49,16 +55,64 @@ public class BlogSharingValidatorTest extends SharingValidatorTest { @Test public void testAcceptsInvitationWithNullPreviousMsgId() throws Exception { expectCreateBlog(); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), null, descriptor, text)); assertExpectedContext(context, null); } + @Test + public void testAcceptsInvitationWithMinAutoDeleteTimer() throws Exception { + testAcceptsInvitationWithAutoDeleteTimer(MIN_AUTO_DELETE_TIMER_MS); + } + + @Test + public void testAcceptsInvitationWithMaxAutoDeleteTimer() throws Exception { + testAcceptsInvitationWithAutoDeleteTimer(MAX_AUTO_DELETE_TIMER_MS); + } + + @Test + public void testAcceptsInvitationWithNullAutoDeleteTimer() + throws Exception { + testAcceptsInvitationWithAutoDeleteTimer(null); + } + + private void testAcceptsInvitationWithAutoDeleteTimer(@Nullable Long timer) + throws Exception { + expectCreateBlog(); + expectEncodeMetadata(INVITE, + timer == null ? NO_AUTO_DELETE_TIMER : timer); + BdfMessageContext context = validator.validateMessage(message, group, + BdfList.of(INVITE.getValue(), previousMsgId, descriptor, text, + timer)); + assertExpectedContext(context, previousMsgId); + } + + @Test(expected = FormatException.class) + public void testRejectsInvitationWithTooBigAutoDeleteTimer() + throws Exception { + testRejectsInvitationWithAutoDeleteTimer(MAX_AUTO_DELETE_TIMER_MS + 1); + } + + @Test(expected = FormatException.class) + public void testRejectsInvitationWithTooSmallAutoDeleteTimer() + throws Exception { + testRejectsInvitationWithAutoDeleteTimer(MIN_AUTO_DELETE_TIMER_MS - 1); + } + + private void testRejectsInvitationWithAutoDeleteTimer(Long timer) + throws Exception { + expectCreateBlog(); + validator.validateMessage(message, group, + BdfList.of(INVITE.getValue(), previousMsgId, descriptor, text, + timer)); + fail(); + } + @Test public void testAcceptsInvitationForRssBlog() throws Exception { expectCreateRssBlog(); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfList rssDescriptor = BdfList.of(authorList, true); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), previousMsgId, rssDescriptor, @@ -93,7 +147,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest { public void testAcceptsMinLengthText() throws Exception { String shortText = getRandomString(1); expectCreateBlog(); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), previousMsgId, descriptor, shortText)); diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingValidatorTest.java index 69e626d24..c42a3b7f3 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingValidatorTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingValidatorTest.java @@ -7,12 +7,18 @@ import org.briarproject.briar.api.forum.Forum; import org.jmock.Expectations; import org.junit.Test; +import javax.annotation.Nullable; + +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.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT_LENGTH; import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH; import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_TEXT_LENGTH; import static org.briarproject.briar.sharing.MessageType.INVITE; +import static org.junit.Assert.fail; public class ForumSharingValidatorTest extends SharingValidatorTest { @@ -31,7 +37,7 @@ public class ForumSharingValidatorTest extends SharingValidatorTest { @Test public void testAcceptsInvitationWithText() throws Exception { expectCreateForum(forumName); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), previousMsgId, descriptor, text)); assertExpectedContext(context, previousMsgId); @@ -40,7 +46,7 @@ public class ForumSharingValidatorTest extends SharingValidatorTest { @Test public void testAcceptsInvitationWithNullText() throws Exception { expectCreateForum(forumName); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), previousMsgId, descriptor, null)); assertExpectedContext(context, previousMsgId); @@ -49,12 +55,60 @@ public class ForumSharingValidatorTest extends SharingValidatorTest { @Test public void testAcceptsInvitationWithNullPreviousMsgId() throws Exception { expectCreateForum(forumName); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), null, descriptor, null)); assertExpectedContext(context, null); } + @Test + public void testAcceptsInvitationWithMinAutoDeleteTimer() throws Exception { + testAcceptsInvitationWithAutoDeleteTimer(MIN_AUTO_DELETE_TIMER_MS); + } + + @Test + public void testAcceptsInvitationWithMaxAutoDeleteTimer() throws Exception { + testAcceptsInvitationWithAutoDeleteTimer(MAX_AUTO_DELETE_TIMER_MS); + } + + @Test + public void testAcceptsInvitationWithNullAutoDeleteTimer() + throws Exception { + testAcceptsInvitationWithAutoDeleteTimer(null); + } + + private void testAcceptsInvitationWithAutoDeleteTimer(@Nullable Long timer) + throws Exception { + expectCreateForum(forumName); + expectEncodeMetadata(INVITE, + timer == null ? NO_AUTO_DELETE_TIMER : timer); + BdfMessageContext context = validator.validateMessage(message, group, + BdfList.of(INVITE.getValue(), previousMsgId, descriptor, text, + timer)); + assertExpectedContext(context, previousMsgId); + } + + @Test(expected = FormatException.class) + public void testRejectsInvitationWithTooBigAutoDeleteTimer() + throws Exception { + testRejectsInvitationWithAutoDeleteTimer(MAX_AUTO_DELETE_TIMER_MS + 1); + } + + @Test(expected = FormatException.class) + public void testRejectsInvitationWithTooSmallAutoDeleteTimer() + throws Exception { + testRejectsInvitationWithAutoDeleteTimer(MIN_AUTO_DELETE_TIMER_MS - 1); + } + + private void testRejectsInvitationWithAutoDeleteTimer(long timer) + throws FormatException { + expectCreateForum(forumName); + validator.validateMessage(message, group, + BdfList.of(INVITE.getValue(), previousMsgId, descriptor, text, + timer)); + fail(); + } + @Test(expected = FormatException.class) public void testRejectsNullForumName() throws Exception { BdfList invalidDescriptor = BdfList.of(null, salt); @@ -84,7 +138,7 @@ public class ForumSharingValidatorTest extends SharingValidatorTest { String shortForumName = getRandomString(1); BdfList validDescriptor = BdfList.of(shortForumName, salt); expectCreateForum(shortForumName); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), previousMsgId, validDescriptor, null)); @@ -144,7 +198,7 @@ public class ForumSharingValidatorTest extends SharingValidatorTest { @Test public void testAcceptsMinLengthText() throws Exception { expectCreateForum(forumName); - expectEncodeMetadata(INVITE); + expectEncodeMetadata(INVITE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(INVITE.getValue(), previousMsgId, descriptor, "1")); assertExpectedContext(context, previousMsgId); diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/SharingValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/SharingValidatorTest.java index f001fb680..c5c6349e0 100644 --- a/briar-core/src/test/java/org/briarproject/briar/sharing/SharingValidatorTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/sharing/SharingValidatorTest.java @@ -16,6 +16,11 @@ import java.util.Collection; import javax.annotation.Nullable; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +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.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.briar.sharing.MessageType.ABORT; @@ -24,7 +29,7 @@ import static org.briarproject.briar.sharing.MessageType.DECLINE; import static org.briarproject.briar.sharing.MessageType.INVITE; import static org.briarproject.briar.sharing.MessageType.LEAVE; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; public abstract class SharingValidatorTest extends ValidatorTestCase { @@ -54,23 +59,84 @@ public abstract class SharingValidatorTest extends ValidatorTestCase { @Test public void testAcceptsAccept() throws Exception { - expectEncodeMetadata(ACCEPT); + expectEncodeMetadata(ACCEPT, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(ACCEPT.getValue(), groupId, previousMsgId)); assertExpectedContext(context, previousMsgId); } + @Test + public void testAcceptsAcceptWithMinAutoDeleteTimer() throws Exception { + testAcceptsResponseWithAutoDeleteTimer(ACCEPT, + MIN_AUTO_DELETE_TIMER_MS); + } + + @Test + public void testAcceptsAcceptWithMaxAutoDeleteTimer() throws Exception { + testAcceptsResponseWithAutoDeleteTimer(ACCEPT, + MAX_AUTO_DELETE_TIMER_MS); + } + + @Test + public void testAcceptsAcceptWithNullAutoDeleteTimer() throws Exception { + testAcceptsResponseWithAutoDeleteTimer(ACCEPT, null); + } + + @Test(expected = FormatException.class) + public void testRejectsAcceptWithTooBigAutoDeleteTimer() throws Exception { + testRejectsResponseWithAutoDeleteTimer(ACCEPT, + MAX_AUTO_DELETE_TIMER_MS + 1); + } + + @Test(expected = FormatException.class) + public void testRejectsAcceptWithTooSmallAutoDeleteTimer() + throws Exception { + testRejectsResponseWithAutoDeleteTimer(ACCEPT, + MIN_AUTO_DELETE_TIMER_MS - 1); + } + @Test public void testAcceptsDecline() throws Exception { - expectEncodeMetadata(DECLINE); + expectEncodeMetadata(DECLINE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(DECLINE.getValue(), groupId, previousMsgId)); assertExpectedContext(context, previousMsgId); } + @Test + public void testAcceptsDeclineWithMinAutoDeleteTimer() throws Exception { + testAcceptsResponseWithAutoDeleteTimer(DECLINE, + MIN_AUTO_DELETE_TIMER_MS); + } + + @Test + public void testAcceptsDeclineWithMaxAutoDeleteTimer() throws Exception { + testAcceptsResponseWithAutoDeleteTimer(DECLINE, + MAX_AUTO_DELETE_TIMER_MS); + } + + @Test + public void testAcceptsDeclineWithNullAutoDeleteTimer() throws Exception { + testAcceptsResponseWithAutoDeleteTimer(DECLINE, null); + } + + @Test(expected = FormatException.class) + public void testRejectsDeclineWithTooBigAutoDeleteTimer() + throws Exception { + testRejectsResponseWithAutoDeleteTimer(DECLINE, + MAX_AUTO_DELETE_TIMER_MS + 1); + } + + @Test(expected = FormatException.class) + public void testRejectsDeclineWithTooSmallAutoDeleteTimer() + throws Exception { + testRejectsResponseWithAutoDeleteTimer(DECLINE, + MIN_AUTO_DELETE_TIMER_MS - 1); + } + @Test public void testAcceptsLeave() throws Exception { - expectEncodeMetadata(LEAVE); + expectEncodeMetadata(LEAVE, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(LEAVE.getValue(), groupId, previousMsgId)); assertExpectedContext(context, previousMsgId); @@ -78,7 +144,7 @@ public abstract class SharingValidatorTest extends ValidatorTestCase { @Test public void testAcceptsAbort() throws Exception { - expectEncodeMetadata(ABORT); + expectEncodeMetadata(ABORT, NO_AUTO_DELETE_TIMER); BdfMessageContext context = validator.validateMessage(message, group, BdfList.of(ABORT.getValue(), groupId, previousMsgId)); assertExpectedContext(context, previousMsgId); @@ -141,10 +207,10 @@ public abstract class SharingValidatorTest extends ValidatorTestCase { BdfList.of(ABORT.getValue(), groupId, previousMsgId, 123)); } - void expectEncodeMetadata(MessageType type) { + void expectEncodeMetadata(MessageType type, long autoDeleteTimer) { context.checking(new Expectations() {{ oneOf(messageEncoder).encodeMetadata(type, groupId, timestamp, - false, false, false, false, false); + false, false, false, false, false, autoDeleteTimer); will(returnValue(meta)); }}); } @@ -153,12 +219,26 @@ public abstract class SharingValidatorTest extends ValidatorTestCase { @Nullable MessageId previousMsgId) { Collection dependencies = messageContext.getDependencies(); if (previousMsgId == null) { - assertTrue(dependencies.isEmpty()); + assertEquals(emptyList(), dependencies); } else { - assertEquals(1, dependencies.size()); - assertTrue(dependencies.contains(previousMsgId)); + assertEquals(singletonList(previousMsgId), dependencies); } assertEquals(meta, messageContext.getDictionary()); } + private void testAcceptsResponseWithAutoDeleteTimer(MessageType type, + @Nullable Long timer) throws Exception { + expectEncodeMetadata(type, + timer == null ? NO_AUTO_DELETE_TIMER : timer); + BdfMessageContext context = validator.validateMessage(message, group, + BdfList.of(type.getValue(), groupId, previousMsgId, timer)); + assertExpectedContext(context, previousMsgId); + } + + private void testRejectsResponseWithAutoDeleteTimer(MessageType type, + long timer) throws FormatException { + validator.validateMessage(message, group, + BdfList.of(type.getValue(), groupId, previousMsgId, timer)); + fail(); + } }