mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 02:39:05 +01:00
Merge branch '1832-use-conversation-timestamp' into '804-self-destructing-messages'
Use latest conversation timestamp for all invitation/introduction messages See merge request briar/briar!1310
This commit is contained in:
@@ -14,6 +14,7 @@ import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.TransactionManager;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
|
||||
@@ -39,6 +40,7 @@ import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.android.DozeWatchdog;
|
||||
import org.briarproject.briar.api.android.LockManager;
|
||||
import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.blog.BlogManager;
|
||||
import org.briarproject.briar.api.blog.BlogPostFactory;
|
||||
import org.briarproject.briar.api.blog.BlogSharingManager;
|
||||
@@ -169,6 +171,10 @@ public interface AndroidComponent
|
||||
|
||||
AndroidWakeLockManager wakeLockManager();
|
||||
|
||||
TransactionManager transactionManager();
|
||||
|
||||
AutoDeleteManager autoDeleteManager();
|
||||
|
||||
void inject(SignInReminderReceiver briarService);
|
||||
|
||||
void inject(BriarService briarService);
|
||||
|
||||
@@ -753,18 +753,10 @@ public class ConversationActivity extends BriarActivity
|
||||
List<AttachmentHeader> attachmentHeaders) {
|
||||
if (isNullOrEmpty(text) && attachmentHeaders.isEmpty())
|
||||
throw new AssertionError();
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
||||
viewModel.sendMessage(text, attachmentHeaders, timestamp);
|
||||
viewModel.sendMessage(text, attachmentHeaders);
|
||||
textInputView.clearText();
|
||||
}
|
||||
|
||||
private long getMinTimestampForNewMessage() {
|
||||
// Don't use an earlier timestamp than the newest message
|
||||
ConversationItem item = adapter.getLastItem();
|
||||
return item == null ? 0 : item.getTime() + 1;
|
||||
}
|
||||
|
||||
private void onAddedPrivateMessage(@Nullable PrivateMessageHeader h) {
|
||||
if (h == null) return;
|
||||
addConversationItem(h.accept(visitor));
|
||||
@@ -969,13 +961,11 @@ public class ConversationActivity extends BriarActivity
|
||||
adapter.notifyItemChanged(position, item);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
||||
try {
|
||||
switch (item.getRequestType()) {
|
||||
case INTRODUCTION:
|
||||
respondToIntroductionRequest(item.getSessionId(),
|
||||
accept, timestamp);
|
||||
accept);
|
||||
break;
|
||||
case FORUM:
|
||||
respondToForumRequest(item.getSessionId(), accept);
|
||||
@@ -1051,9 +1041,8 @@ public class ConversationActivity extends BriarActivity
|
||||
|
||||
@DatabaseExecutor
|
||||
private void respondToIntroductionRequest(SessionId sessionId,
|
||||
boolean accept, long time) throws DbException {
|
||||
introductionManager.respondToIntroduction(contactId, sessionId, time,
|
||||
accept);
|
||||
boolean accept) throws DbException {
|
||||
introductionManager.respondToIntroduction(contactId, sessionId, accept);
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.briarproject.briar.android.util.UiUtils;
|
||||
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.messaging.AttachmentHeader;
|
||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessage;
|
||||
@@ -86,6 +87,7 @@ public class ConversationViewModel extends AndroidViewModel
|
||||
private final AttachmentRetriever attachmentRetriever;
|
||||
private final AttachmentCreator attachmentCreator;
|
||||
private final AutoDeleteManager autoDeleteManager;
|
||||
private final ConversationManager conversationManager;
|
||||
|
||||
@Nullable
|
||||
private ContactId contactId = null;
|
||||
@@ -119,7 +121,8 @@ public class ConversationViewModel extends AndroidViewModel
|
||||
PrivateMessageFactory privateMessageFactory,
|
||||
AttachmentRetriever attachmentRetriever,
|
||||
AttachmentCreator attachmentCreator,
|
||||
AutoDeleteManager autoDeleteManager) {
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager) {
|
||||
super(application);
|
||||
this.dbExecutor = dbExecutor;
|
||||
this.db = db;
|
||||
@@ -131,6 +134,7 @@ public class ConversationViewModel extends AndroidViewModel
|
||||
this.attachmentRetriever = attachmentRetriever;
|
||||
this.attachmentCreator = attachmentCreator;
|
||||
this.autoDeleteManager = autoDeleteManager;
|
||||
this.conversationManager = conversationManager;
|
||||
messagingGroupId = Transformations
|
||||
.map(contact, c -> messagingManager.getContactGroup(c).getId());
|
||||
contactDeleted.setValue(false);
|
||||
@@ -213,14 +217,13 @@ public class ConversationViewModel extends AndroidViewModel
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void sendMessage(@Nullable String text,
|
||||
List<AttachmentHeader> headers, long timestamp) {
|
||||
void sendMessage(@Nullable String text, List<AttachmentHeader> headers) {
|
||||
// messagingGroupId is loaded with the contact
|
||||
observeForeverOnce(messagingGroupId, groupId -> {
|
||||
requireNonNull(groupId);
|
||||
observeForeverOnce(privateMessageFormat, format ->
|
||||
storeMessage(requireNonNull(contactId), groupId, text,
|
||||
headers, timestamp, format));
|
||||
headers, format));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -282,8 +285,10 @@ public class ConversationViewModel extends AndroidViewModel
|
||||
|
||||
private PrivateMessage createMessage(Transaction txn, ContactId c,
|
||||
GroupId groupId, @Nullable String text,
|
||||
List<AttachmentHeader> headers, long timestamp,
|
||||
PrivateMessageFormat format) throws DbException {
|
||||
List<AttachmentHeader> headers, PrivateMessageFormat format)
|
||||
throws DbException {
|
||||
long timestamp =
|
||||
conversationManager.getTimestampForOutgoingMessage(txn, c);
|
||||
try {
|
||||
if (format == TEXT_ONLY) {
|
||||
return privateMessageFactory.createLegacyPrivateMessage(
|
||||
@@ -304,13 +309,13 @@ public class ConversationViewModel extends AndroidViewModel
|
||||
@UiThread
|
||||
private void storeMessage(ContactId c, GroupId groupId,
|
||||
@Nullable String text, List<AttachmentHeader> headers,
|
||||
long timestamp, PrivateMessageFormat format) {
|
||||
PrivateMessageFormat format) {
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
long start = now();
|
||||
PrivateMessage m = createMessage(txn, c, groupId, text,
|
||||
headers, timestamp, format);
|
||||
headers, format);
|
||||
messagingManager.addLocalMessage(txn, m);
|
||||
logDuration(LOG, "Storing message", start);
|
||||
Message message = m.getMessage();
|
||||
|
||||
@@ -211,8 +211,7 @@ public class IntroductionMessageFragment extends BaseFragment
|
||||
introductionActivity.runOnDbThread(() -> {
|
||||
// actually make the introduction
|
||||
try {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
introductionManager.makeIntroduction(c1, c2, text, timestamp);
|
||||
introductionManager.makeIntroduction(c1, c2, text);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
introductionError();
|
||||
|
||||
@@ -7,6 +7,8 @@ import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.NoSuchContactException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.db.TransactionManager;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
@@ -15,6 +17,8 @@ import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.android.contactselection.ContactSelectorControllerImpl;
|
||||
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessage;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
||||
@@ -35,6 +39,8 @@ import javax.inject.Inject;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@Immutable
|
||||
@@ -43,9 +49,12 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
implements CreateGroupController {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(CreateGroupControllerImpl.class.getName());
|
||||
getLogger(CreateGroupControllerImpl.class.getName());
|
||||
|
||||
private final Executor cryptoExecutor;
|
||||
private final TransactionManager db;
|
||||
private final AutoDeleteManager autoDeleteManager;
|
||||
private final ConversationManager conversationManager;
|
||||
private final ContactManager contactManager;
|
||||
private final IdentityManager identityManager;
|
||||
private final PrivateGroupFactory groupFactory;
|
||||
@@ -56,16 +65,26 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
CreateGroupControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||
CreateGroupControllerImpl(
|
||||
@DatabaseExecutor Executor dbExecutor,
|
||||
@CryptoExecutor Executor cryptoExecutor,
|
||||
LifecycleManager lifecycleManager, ContactManager contactManager,
|
||||
IdentityManager identityManager, PrivateGroupFactory groupFactory,
|
||||
TransactionManager db,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
LifecycleManager lifecycleManager,
|
||||
ContactManager contactManager,
|
||||
IdentityManager identityManager,
|
||||
PrivateGroupFactory groupFactory,
|
||||
GroupMessageFactory groupMessageFactory,
|
||||
PrivateGroupManager groupManager,
|
||||
GroupInvitationFactory groupInvitationFactory,
|
||||
GroupInvitationManager groupInvitationManager, Clock clock) {
|
||||
GroupInvitationManager groupInvitationManager,
|
||||
Clock clock) {
|
||||
super(dbExecutor, lifecycleManager, contactManager);
|
||||
this.cryptoExecutor = cryptoExecutor;
|
||||
this.db = db;
|
||||
this.autoDeleteManager = autoDeleteManager;
|
||||
this.conversationManager = conversationManager;
|
||||
this.contactManager = contactManager;
|
||||
this.identityManager = identityManager;
|
||||
this.groupFactory = groupFactory;
|
||||
@@ -129,16 +148,14 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
ResultExceptionHandler<Void, DbException> handler) {
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
||||
List<Contact> contacts = new ArrayList<>();
|
||||
for (ContactId c : contactIds) {
|
||||
try {
|
||||
contacts.add(contactManager.getContact(c));
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
}
|
||||
}
|
||||
signInvitations(g, localAuthor, contacts, text, handler);
|
||||
db.transaction(true, txn -> {
|
||||
LocalAuthor localAuthor =
|
||||
identityManager.getLocalAuthor(txn);
|
||||
List<InvitationContext> contexts =
|
||||
createInvitationContexts(txn, contactIds);
|
||||
txn.attach(() -> signInvitations(g, localAuthor, contexts,
|
||||
text, handler));
|
||||
});
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
handler.onException(e);
|
||||
@@ -146,17 +163,31 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
});
|
||||
}
|
||||
|
||||
private List<InvitationContext> createInvitationContexts(Transaction txn,
|
||||
Collection<ContactId> contactIds) throws DbException {
|
||||
List<InvitationContext> contexts = new ArrayList<>();
|
||||
for (ContactId c : contactIds) {
|
||||
try {
|
||||
Contact contact = contactManager.getContact(txn, c);
|
||||
long timestamp = conversationManager
|
||||
.getTimestampForOutgoingMessage(txn, c);
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
contexts.add(new InvitationContext(contact, timestamp, timer));
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
}
|
||||
}
|
||||
return contexts;
|
||||
}
|
||||
|
||||
private void signInvitations(GroupId g, LocalAuthor localAuthor,
|
||||
Collection<Contact> contacts, @Nullable String text,
|
||||
List<InvitationContext> contexts, @Nullable String text,
|
||||
ResultExceptionHandler<Void, DbException> handler) {
|
||||
cryptoExecutor.execute(() -> {
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
List<InvitationContext> contexts = new ArrayList<>();
|
||||
for (Contact c : contacts) {
|
||||
byte[] signature = groupInvitationFactory.signInvitation(c, g,
|
||||
timestamp, localAuthor.getPrivateKey());
|
||||
contexts.add(new InvitationContext(c.getId(), timestamp,
|
||||
signature));
|
||||
for (InvitationContext ctx : contexts) {
|
||||
ctx.signature = groupInvitationFactory.signInvitation(
|
||||
ctx.contact, g, ctx.timestamp,
|
||||
localAuthor.getPrivateKey());
|
||||
}
|
||||
sendInvitations(g, contexts, text, handler);
|
||||
});
|
||||
@@ -167,16 +198,16 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
ResultExceptionHandler<Void, DbException> handler) {
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
for (InvitationContext context : contexts) {
|
||||
for (InvitationContext ctx : contexts) {
|
||||
try {
|
||||
groupInvitationManager.sendInvitation(g,
|
||||
context.contactId, text, context.timestamp,
|
||||
context.signature);
|
||||
ctx.contact.getId(), text, ctx.timestamp,
|
||||
requireNonNull(ctx.signature),
|
||||
ctx.autoDeleteTimer);
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
}
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
handler.onResult(null);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
@@ -187,15 +218,16 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
|
||||
private static class InvitationContext {
|
||||
|
||||
private final ContactId contactId;
|
||||
private final long timestamp;
|
||||
private final byte[] signature;
|
||||
private final Contact contact;
|
||||
private final long timestamp, autoDeleteTimer;
|
||||
@Nullable
|
||||
private byte[] signature = null;
|
||||
|
||||
private InvitationContext(ContactId contactId, long timestamp,
|
||||
byte[] signature) {
|
||||
this.contactId = contactId;
|
||||
private InvitationContext(Contact contact, long timestamp,
|
||||
long autoDeleteTimer) {
|
||||
this.contact = contact;
|
||||
this.timestamp = timestamp;
|
||||
this.signature = signature;
|
||||
this.autoDeleteTimer = autoDeleteTimer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,9 @@ import org.briarproject.bramble.api.db.NoSuchGroupException;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.android.contactselection.ContactSelectorControllerImpl;
|
||||
import org.briarproject.briar.android.controller.handler.ExceptionHandler;
|
||||
import org.briarproject.briar.api.blog.BlogSharingManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -25,6 +23,7 @@ import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@Immutable
|
||||
@@ -33,21 +32,16 @@ class ShareBlogControllerImpl extends ContactSelectorControllerImpl
|
||||
implements ShareBlogController {
|
||||
|
||||
private final static Logger LOG =
|
||||
Logger.getLogger(ShareBlogControllerImpl.class.getName());
|
||||
getLogger(ShareBlogControllerImpl.class.getName());
|
||||
|
||||
private final ConversationManager conversationManager;
|
||||
private final BlogSharingManager blogSharingManager;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
ShareBlogControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager, ContactManager contactManager,
|
||||
ConversationManager conversationManager,
|
||||
BlogSharingManager blogSharingManager, Clock clock) {
|
||||
BlogSharingManager blogSharingManager) {
|
||||
super(dbExecutor, lifecycleManager, contactManager);
|
||||
this.conversationManager = conversationManager;
|
||||
this.blogSharingManager = blogSharingManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,10 +56,7 @@ class ShareBlogControllerImpl extends ContactSelectorControllerImpl
|
||||
try {
|
||||
for (ContactId c : contacts) {
|
||||
try {
|
||||
long time = Math.max(clock.currentTimeMillis(),
|
||||
conversationManager.getGroupCount(c)
|
||||
.getLatestMsgTime() + 1);
|
||||
blogSharingManager.sendInvitation(g, c, text, time);
|
||||
blogSharingManager.sendInvitation(g, c, text);
|
||||
} catch (NoSuchContactException | NoSuchGroupException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
|
||||
@@ -10,10 +10,8 @@ import org.briarproject.bramble.api.db.NoSuchGroupException;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.android.contactselection.ContactSelectorControllerImpl;
|
||||
import org.briarproject.briar.android.controller.handler.ExceptionHandler;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.forum.ForumSharingManager;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -25,6 +23,7 @@ import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@Immutable
|
||||
@@ -33,21 +32,16 @@ class ShareForumControllerImpl extends ContactSelectorControllerImpl
|
||||
implements ShareForumController {
|
||||
|
||||
private final static Logger LOG =
|
||||
Logger.getLogger(ShareForumControllerImpl.class.getName());
|
||||
getLogger(ShareForumControllerImpl.class.getName());
|
||||
|
||||
private final ConversationManager conversationManager;
|
||||
private final ForumSharingManager forumSharingManager;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
ShareForumControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager, ContactManager contactManager,
|
||||
ConversationManager conversationManager,
|
||||
ForumSharingManager forumSharingManager, Clock clock) {
|
||||
ForumSharingManager forumSharingManager) {
|
||||
super(dbExecutor, lifecycleManager, contactManager);
|
||||
this.conversationManager = conversationManager;
|
||||
this.forumSharingManager = forumSharingManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,10 +56,7 @@ class ShareForumControllerImpl extends ContactSelectorControllerImpl
|
||||
try {
|
||||
for (ContactId c : contacts) {
|
||||
try {
|
||||
long time = Math.max(clock.currentTimeMillis(),
|
||||
conversationManager.getGroupCount(c)
|
||||
.getLatestMsgTime() + 1);
|
||||
forumSharingManager.sendInvitation(g, c, text, time);
|
||||
forumSharingManager.sendInvitation(g, c, text);
|
||||
} catch (NoSuchContactException | NoSuchGroupException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,18 @@ public interface ConversationManager {
|
||||
*/
|
||||
GroupCount getGroupCount(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the unified group count for all private conversation messages.
|
||||
*/
|
||||
GroupCount getGroupCount(Transaction txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns a timestamp for an outgoing message, which is later than the
|
||||
* timestamp of any message in the conversation with the given contact.
|
||||
*/
|
||||
long getTimestampForOutgoingMessage(Transaction txn, ContactId c)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Deletes all messages exchanged with the given contact.
|
||||
*/
|
||||
|
||||
@@ -36,13 +36,13 @@ public interface IntroductionManager extends ConversationClient {
|
||||
/**
|
||||
* Sends two initial introduction messages.
|
||||
*/
|
||||
void makeIntroduction(Contact c1, Contact c2, @Nullable String text,
|
||||
long timestamp) throws DbException;
|
||||
void makeIntroduction(Contact c1, Contact c2, @Nullable String text)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Responds to an introduction.
|
||||
*/
|
||||
void respondToIntroduction(ContactId contactId, SessionId sessionId,
|
||||
long timestamp, boolean accept) throws DbException;
|
||||
boolean accept) throws DbException;
|
||||
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ public interface GroupInvitationManager extends ConversationClient {
|
||||
* pending.
|
||||
*/
|
||||
void sendInvitation(GroupId g, ContactId c, @Nullable String text,
|
||||
long timestamp, byte[] signature) throws DbException;
|
||||
long timestamp, byte[] signature, long autoDeleteTimer)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Responds to a pending private group invitation from the given contact.
|
||||
|
||||
@@ -21,7 +21,7 @@ public interface SharingManager<S extends Shareable>
|
||||
* including optional text.
|
||||
*/
|
||||
void sendInvitation(GroupId shareableId, ContactId contactId,
|
||||
@Nullable String text, long timestamp) throws DbException;
|
||||
@Nullable String text) throws DbException;
|
||||
|
||||
/**
|
||||
* Responds to a pending group invitation
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
|
||||
|
||||
@@ -59,6 +60,7 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
protected final MessageEncoder messageEncoder;
|
||||
protected final ClientVersioningManager clientVersioningManager;
|
||||
protected final AutoDeleteManager autoDeleteManager;
|
||||
protected final ConversationManager conversationManager;
|
||||
protected final Clock clock;
|
||||
|
||||
AbstractProtocolEngine(
|
||||
@@ -72,6 +74,7 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
MessageEncoder messageEncoder,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock) {
|
||||
this.db = db;
|
||||
this.clientHelper = clientHelper;
|
||||
@@ -83,6 +86,7 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
this.messageEncoder = messageEncoder;
|
||||
this.clientVersioningManager = clientVersioningManager;
|
||||
this.autoDeleteManager = autoDeleteManager;
|
||||
this.conversationManager = conversationManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@@ -227,14 +231,10 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
return !dependency.equals(lastRemoteMessageId);
|
||||
}
|
||||
|
||||
long getLocalTimestamp(long localTimestamp, long requestTimestamp) {
|
||||
return Math.max(
|
||||
clock.currentTimeMillis(),
|
||||
Math.max(
|
||||
localTimestamp,
|
||||
requestTimestamp
|
||||
) + 1
|
||||
);
|
||||
long getTimestampForOutgoingMessage(Transaction txn, GroupId contactGroupId)
|
||||
throws DbException {
|
||||
ContactId c = getContactId(txn, contactGroupId);
|
||||
return conversationManager.getTimestampForOutgoingMessage(txn, c);
|
||||
}
|
||||
|
||||
private ContactId getContactId(Transaction txn, GroupId contactGroupId)
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.ProtocolStateException;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionAbortedEvent;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
|
||||
@@ -43,6 +44,7 @@ import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.briar.introduction.IntroduceeState.AWAIT_AUTH;
|
||||
@@ -75,15 +77,17 @@ class IntroduceeProtocolEngine
|
||||
IdentityManager identityManager,
|
||||
MessageParser messageParser,
|
||||
MessageEncoder messageEncoder,
|
||||
Clock clock,
|
||||
IntroductionCrypto crypto,
|
||||
KeyManager keyManager,
|
||||
TransportPropertyManager transportPropertyManager,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
AutoDeleteManager autoDeleteManager) {
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, contactManager, contactGroupFactory,
|
||||
messageTracker, identityManager, messageParser, messageEncoder,
|
||||
clientVersioningManager, autoDeleteManager, clock);
|
||||
clientVersioningManager, autoDeleteManager,
|
||||
conversationManager, clock);
|
||||
this.crypto = crypto;
|
||||
this.keyManager = keyManager;
|
||||
this.transportPropertyManager = transportPropertyManager;
|
||||
@@ -91,18 +95,18 @@ class IntroduceeProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroduceeSession onRequestAction(Transaction txn,
|
||||
IntroduceeSession session, @Nullable String text, long timestamp) {
|
||||
IntroduceeSession session, @Nullable String text) {
|
||||
throw new UnsupportedOperationException(); // Invalid in this role
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntroduceeSession onAcceptAction(Transaction txn,
|
||||
IntroduceeSession session, long timestamp) throws DbException {
|
||||
IntroduceeSession session) throws DbException {
|
||||
switch (session.getState()) {
|
||||
case AWAIT_RESPONSES:
|
||||
case REMOTE_DECLINED:
|
||||
case REMOTE_ACCEPTED:
|
||||
return onLocalAccept(txn, session, timestamp);
|
||||
return onLocalAccept(txn, session);
|
||||
case START:
|
||||
case LOCAL_DECLINED:
|
||||
case LOCAL_ACCEPTED:
|
||||
@@ -116,12 +120,12 @@ class IntroduceeProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroduceeSession onDeclineAction(Transaction txn,
|
||||
IntroduceeSession session, long timestamp) throws DbException {
|
||||
IntroduceeSession session) throws DbException {
|
||||
switch (session.getState()) {
|
||||
case AWAIT_RESPONSES:
|
||||
case REMOTE_DECLINED:
|
||||
case REMOTE_ACCEPTED:
|
||||
return onLocalDecline(txn, session, timestamp);
|
||||
return onLocalDecline(txn, session);
|
||||
case START:
|
||||
case LOCAL_DECLINED:
|
||||
case LOCAL_ACCEPTED:
|
||||
@@ -272,7 +276,7 @@ class IntroduceeProtocolEngine
|
||||
}
|
||||
|
||||
private IntroduceeSession onLocalAccept(Transaction txn,
|
||||
IntroduceeSession s, long timestamp) throws DbException {
|
||||
IntroduceeSession s) throws DbException {
|
||||
// Mark the request message unavailable to answer
|
||||
markRequestsUnavailableToAnswer(txn, s);
|
||||
|
||||
@@ -283,8 +287,8 @@ class IntroduceeProtocolEngine
|
||||
Map<TransportId, TransportProperties> transportProperties =
|
||||
transportPropertyManager.getLocalProperties(txn);
|
||||
|
||||
// Send a ACCEPT message
|
||||
long localTimestamp = Math.max(timestamp + 1, getLocalTimestamp(s));
|
||||
// Send an ACCEPT message
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||
Message sent = sendAcceptMessage(txn, s, localTimestamp, publicKey,
|
||||
localTimestamp, transportProperties, true);
|
||||
// Track the message
|
||||
@@ -309,12 +313,12 @@ class IntroduceeProtocolEngine
|
||||
}
|
||||
|
||||
private IntroduceeSession onLocalDecline(Transaction txn,
|
||||
IntroduceeSession s, long timestamp) throws DbException {
|
||||
IntroduceeSession s) throws DbException {
|
||||
// Mark the request message unavailable to answer
|
||||
markRequestsUnavailableToAnswer(txn, s);
|
||||
|
||||
// Send a DECLINE message
|
||||
long localTimestamp = Math.max(timestamp + 1, getLocalTimestamp(s));
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||
Message sent = sendDeclineMessage(txn, s, localTimestamp, true);
|
||||
|
||||
// Track the message
|
||||
@@ -412,8 +416,8 @@ class IntroduceeProtocolEngine
|
||||
return abort(txn, s);
|
||||
}
|
||||
if (s.getState() != AWAIT_AUTH) throw new AssertionError();
|
||||
Message sent = sendAuthMessage(txn, s, getLocalTimestamp(s), mac,
|
||||
signature);
|
||||
long localTimestamp = getTimestampForInvisibleMessage(s);
|
||||
Message sent = sendAuthMessage(txn, s, localTimestamp, mac, signature);
|
||||
return IntroduceeSession.addLocalAuth(s, AWAIT_AUTH, sent, masterKey,
|
||||
aliceMacKey, bobMacKey);
|
||||
}
|
||||
@@ -464,7 +468,8 @@ class IntroduceeProtocolEngine
|
||||
|
||||
// send ACTIVATE message with a MAC
|
||||
byte[] mac = crypto.activateMac(s);
|
||||
Message sent = sendActivateMessage(txn, s, getLocalTimestamp(s), mac);
|
||||
long localTimestamp = getTimestampForInvisibleMessage(s);
|
||||
Message sent = sendActivateMessage(txn, s, localTimestamp, mac);
|
||||
|
||||
// Move to AWAIT_ACTIVATE state and clear key material from session
|
||||
return IntroduceeSession.awaitActivate(s, m, sent, keys);
|
||||
@@ -515,7 +520,8 @@ class IntroduceeProtocolEngine
|
||||
markRequestsUnavailableToAnswer(txn, s);
|
||||
|
||||
// Send an ABORT message
|
||||
Message sent = sendAbortMessage(txn, s, getLocalTimestamp(s));
|
||||
long localTimestamp = getTimestampForInvisibleMessage(s);
|
||||
Message sent = sendAbortMessage(txn, s, localTimestamp);
|
||||
|
||||
// Broadcast abort event for testing
|
||||
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
||||
@@ -530,9 +536,34 @@ class IntroduceeProtocolEngine
|
||||
return isInvalidDependency(s.getLastRemoteMessageId(), dependency);
|
||||
}
|
||||
|
||||
private long getLocalTimestamp(IntroduceeSession s) {
|
||||
return getLocalTimestamp(s.getLocalTimestamp(),
|
||||
s.getRequestTimestamp());
|
||||
/**
|
||||
* Returns a timestamp for a visible outgoing message. The timestamp is
|
||||
* later than the timestamp of any message sent or received so far in the
|
||||
* conversation, and later than the {@link
|
||||
* #getSessionTimestamp(IntroduceeSession) session timestamp}.
|
||||
*/
|
||||
private long getTimestampForVisibleMessage(Transaction txn,
|
||||
IntroduceeSession s) throws DbException {
|
||||
long conversationTimestamp =
|
||||
getTimestampForOutgoingMessage(txn, s.getContactGroupId());
|
||||
return max(conversationTimestamp, getSessionTimestamp(s) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a timestamp for an invisible outgoing message. The timestamp is
|
||||
* later than the {@link #getSessionTimestamp(IntroduceeSession) session
|
||||
* timestamp}.
|
||||
*/
|
||||
private long getTimestampForInvisibleMessage(IntroduceeSession s) {
|
||||
return max(clock.currentTimeMillis(), getSessionTimestamp(s) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest timestamp of any message sent so far in the session,
|
||||
* and any request message received so far in the session.
|
||||
*/
|
||||
private long getSessionTimestamp(IntroduceeSession s) {
|
||||
return max(s.getLocalTimestamp(), s.getRequestTimestamp());
|
||||
}
|
||||
|
||||
private void addSessionId(Transaction txn, MessageId m, SessionId sessionId)
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.ProtocolStateException;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionAbortedEvent;
|
||||
import org.briarproject.briar.introduction.IntroducerSession.Introducee;
|
||||
|
||||
@@ -24,6 +25,7 @@ import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
import static org.briarproject.briar.introduction.IntroducerState.AWAIT_ACTIVATES;
|
||||
import static org.briarproject.briar.introduction.IntroducerState.AWAIT_ACTIVATE_A;
|
||||
import static org.briarproject.briar.introduction.IntroducerState.AWAIT_ACTIVATE_B;
|
||||
@@ -54,19 +56,21 @@ class IntroducerProtocolEngine
|
||||
MessageEncoder messageEncoder,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, contactManager, contactGroupFactory,
|
||||
messageTracker, identityManager, messageParser, messageEncoder,
|
||||
clientVersioningManager, autoDeleteManager, clock);
|
||||
clientVersioningManager, autoDeleteManager,
|
||||
conversationManager, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntroducerSession onRequestAction(Transaction txn,
|
||||
IntroducerSession s, @Nullable String text, long timestamp)
|
||||
IntroducerSession s, @Nullable String text)
|
||||
throws DbException {
|
||||
switch (s.getState()) {
|
||||
case START:
|
||||
return onLocalRequest(txn, s, text, timestamp);
|
||||
return onLocalRequest(txn, s, text);
|
||||
case AWAIT_RESPONSES:
|
||||
case AWAIT_RESPONSE_A:
|
||||
case AWAIT_RESPONSE_B:
|
||||
@@ -86,37 +90,24 @@ class IntroducerProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroducerSession onAcceptAction(Transaction txn,
|
||||
IntroducerSession s, long timestamp) {
|
||||
IntroducerSession s) {
|
||||
throw new UnsupportedOperationException(); // Invalid in this role
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntroducerSession onDeclineAction(Transaction txn,
|
||||
IntroducerSession s, long timestamp) {
|
||||
IntroducerSession s) {
|
||||
throw new UnsupportedOperationException(); // Invalid in this role
|
||||
}
|
||||
|
||||
IntroducerSession onIntroduceeRemoved(Transaction txn,
|
||||
Introducee remainingIntroducee, IntroducerSession session)
|
||||
throws DbException {
|
||||
// abort session
|
||||
IntroducerSession s = abort(txn, session);
|
||||
// reset information for introducee that was removed
|
||||
Introducee introduceeA, introduceeB;
|
||||
if (remainingIntroducee.author.equals(s.getIntroduceeA().author)) {
|
||||
introduceeA = s.getIntroduceeA();
|
||||
introduceeB =
|
||||
new Introducee(s.getSessionId(), s.getIntroduceeB().groupId,
|
||||
s.getIntroduceeB().author);
|
||||
} else if (remainingIntroducee.author
|
||||
.equals(s.getIntroduceeB().author)) {
|
||||
introduceeA =
|
||||
new Introducee(s.getSessionId(), s.getIntroduceeA().groupId,
|
||||
s.getIntroduceeA().author);
|
||||
introduceeB = s.getIntroduceeB();
|
||||
} else throw new DbException();
|
||||
// abort session with remaining introducee
|
||||
IntroducerSession s = abort(txn, session, remainingIntroducee);
|
||||
return new IntroducerSession(s.getSessionId(), s.getState(),
|
||||
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||
s.getRequestTimestamp(), s.getIntroduceeA(),
|
||||
s.getIntroduceeB());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -226,13 +217,13 @@ class IntroducerProtocolEngine
|
||||
}
|
||||
|
||||
private IntroducerSession onLocalRequest(Transaction txn,
|
||||
IntroducerSession s, @Nullable String text, long timestamp)
|
||||
throws DbException {
|
||||
IntroducerSession s, @Nullable String text) throws DbException {
|
||||
// Send REQUEST messages
|
||||
long maxIntroduceeTimestamp =
|
||||
Math.max(getLocalTimestamp(s, s.getIntroduceeA()),
|
||||
getLocalTimestamp(s, s.getIntroduceeB()));
|
||||
long localTimestamp = Math.max(timestamp, maxIntroduceeTimestamp);
|
||||
long timestampA =
|
||||
getTimestampForVisibleMessage(txn, s, s.getIntroduceeA());
|
||||
long timestampB =
|
||||
getTimestampForVisibleMessage(txn, s, s.getIntroduceeB());
|
||||
long localTimestamp = max(timestampA, timestampB);
|
||||
Message sentA = sendRequestMessage(txn, s.getIntroduceeA(),
|
||||
localTimestamp, s.getIntroduceeB().author, text);
|
||||
Message sentB = sendRequestMessage(txn, s.getIntroduceeB(),
|
||||
@@ -272,11 +263,11 @@ class IntroducerProtocolEngine
|
||||
|
||||
// Forward ACCEPT message
|
||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||
long timestamp = getLocalTimestamp(s, i);
|
||||
Message sent =
|
||||
sendAcceptMessage(txn, i, timestamp, m.getEphemeralPublicKey(),
|
||||
m.getAcceptTimestamp(), m.getTransportProperties(),
|
||||
false);
|
||||
// The forwarded message will not be visible to the introducee
|
||||
long localTimestamp = getTimestampForInvisibleMessage(s, i);
|
||||
Message sent = sendAcceptMessage(txn, i, localTimestamp,
|
||||
m.getEphemeralPublicKey(), m.getAcceptTimestamp(),
|
||||
m.getTransportProperties(), false);
|
||||
|
||||
// Create the next state
|
||||
IntroducerState state = AWAIT_AUTHS;
|
||||
@@ -333,7 +324,9 @@ class IntroducerProtocolEngine
|
||||
|
||||
// Forward ACCEPT message
|
||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||
Message sent = sendAcceptMessage(txn, i, getLocalTimestamp(s, i),
|
||||
// The forwarded message will not be visible to the introducee
|
||||
long localTimestamp = getTimestampForInvisibleMessage(s, i);
|
||||
Message sent = sendAcceptMessage(txn, i, localTimestamp,
|
||||
m.getEphemeralPublicKey(), m.getAcceptTimestamp(),
|
||||
m.getTransportProperties(), false);
|
||||
|
||||
@@ -384,8 +377,9 @@ class IntroducerProtocolEngine
|
||||
|
||||
// Forward DECLINE message
|
||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||
long timestamp = getLocalTimestamp(s, i);
|
||||
Message sent = sendDeclineMessage(txn, i, timestamp, false);
|
||||
// The forwarded message will be visible to the introducee
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s, i);
|
||||
Message sent = sendDeclineMessage(txn, i, localTimestamp, false);
|
||||
|
||||
// Create the next state
|
||||
IntroducerState state = START;
|
||||
@@ -436,8 +430,9 @@ class IntroducerProtocolEngine
|
||||
|
||||
// Forward DECLINE message
|
||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||
long timestamp = getLocalTimestamp(s, i);
|
||||
Message sent = sendDeclineMessage(txn, i, timestamp, false);
|
||||
// The forwarded message will be visible to the introducee
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s, i);
|
||||
Message sent = sendDeclineMessage(txn, i, localTimestamp, false);
|
||||
|
||||
Introducee introduceeA, introduceeB;
|
||||
Author sender, other;
|
||||
@@ -477,8 +472,8 @@ class IntroducerProtocolEngine
|
||||
|
||||
// Forward AUTH message
|
||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||
long timestamp = getLocalTimestamp(s, i);
|
||||
Message sent = sendAuthMessage(txn, i, timestamp, m.getMac(),
|
||||
long localTimestamp = getTimestampForInvisibleMessage(s, i);
|
||||
Message sent = sendAuthMessage(txn, i, localTimestamp, m.getMac(),
|
||||
m.getSignature());
|
||||
|
||||
// Move to the next state
|
||||
@@ -513,8 +508,8 @@ class IntroducerProtocolEngine
|
||||
|
||||
// Forward ACTIVATE message
|
||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||
long timestamp = getLocalTimestamp(s, i);
|
||||
Message sent = sendActivateMessage(txn, i, timestamp, m.getMac());
|
||||
long localTimestamp = getTimestampForInvisibleMessage(s, i);
|
||||
Message sent = sendActivateMessage(txn, i, localTimestamp, m.getMac());
|
||||
|
||||
// Move to the next state
|
||||
IntroducerState state = START;
|
||||
@@ -536,8 +531,8 @@ class IntroducerProtocolEngine
|
||||
IntroducerSession s, AbortMessage m) throws DbException {
|
||||
// Forward ABORT message
|
||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||
long timestamp = getLocalTimestamp(s, i);
|
||||
Message sent = sendAbortMessage(txn, i, timestamp);
|
||||
long localTimestamp = getTimestampForInvisibleMessage(s, i);
|
||||
Message sent = sendAbortMessage(txn, i, localTimestamp);
|
||||
|
||||
// Broadcast abort event for testing
|
||||
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
||||
@@ -555,15 +550,45 @@ class IntroducerProtocolEngine
|
||||
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||
}
|
||||
|
||||
private IntroducerSession abort(Transaction txn,
|
||||
IntroducerSession s) throws DbException {
|
||||
private IntroducerSession abort(Transaction txn, IntroducerSession s,
|
||||
Introducee remainingIntroducee) throws DbException {
|
||||
// Broadcast abort event for testing
|
||||
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
||||
|
||||
// Send an ABORT message to the remaining introducee
|
||||
long localTimestamp =
|
||||
getTimestampForInvisibleMessage(s, remainingIntroducee);
|
||||
Message sent =
|
||||
sendAbortMessage(txn, remainingIntroducee, localTimestamp);
|
||||
// Reset the session back to initial state
|
||||
Introducee introduceeA = s.getIntroduceeA();
|
||||
Introducee introduceeB = s.getIntroduceeB();
|
||||
if (remainingIntroducee.author.equals(introduceeA.author)) {
|
||||
introduceeA = new Introducee(introduceeA, sent);
|
||||
introduceeB = new Introducee(s.getSessionId(), introduceeB.groupId,
|
||||
introduceeB.author);
|
||||
} else if (remainingIntroducee.author.equals(introduceeB.author)) {
|
||||
introduceeA = new Introducee(s.getSessionId(), introduceeA.groupId,
|
||||
introduceeA.author);
|
||||
introduceeB = new Introducee(introduceeB, sent);
|
||||
} else {
|
||||
throw new DbException();
|
||||
}
|
||||
return new IntroducerSession(s.getSessionId(), START,
|
||||
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||
}
|
||||
|
||||
private IntroducerSession abort(Transaction txn, IntroducerSession s)
|
||||
throws DbException {
|
||||
// Broadcast abort event for testing
|
||||
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
||||
|
||||
// Send an ABORT message to both introducees
|
||||
long timestampA = getLocalTimestamp(s, s.getIntroduceeA());
|
||||
long timestampA =
|
||||
getTimestampForInvisibleMessage(s, s.getIntroduceeA());
|
||||
Message sentA = sendAbortMessage(txn, s.getIntroduceeA(), timestampA);
|
||||
long timestampB = getLocalTimestamp(s, s.getIntroduceeB());
|
||||
long timestampB =
|
||||
getTimestampForInvisibleMessage(s, s.getIntroduceeB());
|
||||
Message sentB = sendAbortMessage(txn, s.getIntroduceeB(), timestampB);
|
||||
// Reset the session back to initial state
|
||||
Introducee introduceeA = new Introducee(s.getIntroduceeA(), sentA);
|
||||
@@ -593,9 +618,33 @@ class IntroducerProtocolEngine
|
||||
return isInvalidDependency(expected, dependency);
|
||||
}
|
||||
|
||||
private long getLocalTimestamp(IntroducerSession s, PeerSession p) {
|
||||
return getLocalTimestamp(p.getLocalTimestamp(),
|
||||
s.getRequestTimestamp());
|
||||
/**
|
||||
* Returns a timestamp for a visible outgoing message. The timestamp is
|
||||
* later than the timestamp of any message sent or received so far in the
|
||||
* conversation, and later than the {@link
|
||||
* #getSessionTimestamp(IntroducerSession, PeerSession) session timestamp}.
|
||||
*/
|
||||
private long getTimestampForVisibleMessage(Transaction txn,
|
||||
IntroducerSession s, PeerSession p) throws DbException {
|
||||
long conversationTimestamp =
|
||||
getTimestampForOutgoingMessage(txn, p.getContactGroupId());
|
||||
return max(conversationTimestamp, getSessionTimestamp(s, p) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a timestamp for an invisible outgoing message. The timestamp is
|
||||
* later than the {@link #getSessionTimestamp(IntroducerSession, PeerSession)
|
||||
* session timestamp}.
|
||||
*/
|
||||
private long getTimestampForInvisibleMessage(IntroducerSession s,
|
||||
PeerSession p) {
|
||||
return max(clock.currentTimeMillis(), getSessionTimestamp(s, p) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest timestamp of any message sent so far in the session.
|
||||
*/
|
||||
private long getSessionTimestamp(IntroducerSession s, PeerSession p) {
|
||||
return max(p.getLocalTimestamp(), s.getRequestTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,8 +311,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeIntroduction(Contact c1, Contact c2, @Nullable String text,
|
||||
long timestamp) throws DbException {
|
||||
public void makeIntroduction(Contact c1, Contact c2, @Nullable String text)
|
||||
throws DbException {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
// Look up the session, if there is one
|
||||
@@ -344,8 +344,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
storageId = ss.storageId;
|
||||
}
|
||||
// Handle the request action
|
||||
session = introducerEngine
|
||||
.onRequestAction(txn, session, text, timestamp);
|
||||
session = introducerEngine.onRequestAction(txn, session, text);
|
||||
// Store the updated session
|
||||
storeSession(txn, storageId, session);
|
||||
db.commitTransaction(txn);
|
||||
@@ -358,7 +357,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
|
||||
@Override
|
||||
public void respondToIntroduction(ContactId contactId, SessionId sessionId,
|
||||
long timestamp, boolean accept) throws DbException {
|
||||
boolean accept) throws DbException {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
// Look up the session
|
||||
@@ -376,11 +375,9 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
.parseIntroduceeSession(contactGroupId, ss.bdfSession);
|
||||
// Handle the join or leave action
|
||||
if (accept) {
|
||||
session = introduceeEngine
|
||||
.onAcceptAction(txn, session, timestamp);
|
||||
session = introduceeEngine.onAcceptAction(txn, session);
|
||||
} else {
|
||||
session = introduceeEngine
|
||||
.onDeclineAction(txn, session, timestamp);
|
||||
session = introduceeEngine.onDeclineAction(txn, session);
|
||||
}
|
||||
// Store the updated session
|
||||
storeSession(txn, ss.storageId, session);
|
||||
|
||||
@@ -8,16 +8,14 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@NotNullByDefault
|
||||
interface ProtocolEngine<S extends Session> {
|
||||
interface ProtocolEngine<S extends Session<?>> {
|
||||
|
||||
S onRequestAction(Transaction txn, S session, @Nullable String text,
|
||||
long timestamp) throws DbException;
|
||||
|
||||
S onAcceptAction(Transaction txn, S session, long timestamp)
|
||||
S onRequestAction(Transaction txn, S session, @Nullable String text)
|
||||
throws DbException;
|
||||
|
||||
S onDeclineAction(Transaction txn, S session, long timestamp)
|
||||
throws DbException;
|
||||
S onAcceptAction(Transaction txn, S session) throws DbException;
|
||||
|
||||
S onDeclineAction(Transaction txn, S session) throws DbException;
|
||||
|
||||
S onRequestMessage(Transaction txn, S session, RequestMessage m)
|
||||
throws DbException, FormatException;
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
|
||||
@@ -20,16 +21,20 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
|
||||
@ThreadSafe
|
||||
@NotNullByDefault
|
||||
class ConversationManagerImpl implements ConversationManager {
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final Clock clock;
|
||||
private final Set<ConversationClient> clients;
|
||||
|
||||
@Inject
|
||||
ConversationManagerImpl(DatabaseComponent db) {
|
||||
ConversationManagerImpl(DatabaseComponent db, Clock clock) {
|
||||
this.db = db;
|
||||
this.clock = clock;
|
||||
clients = new CopyOnWriteArraySet<>();
|
||||
}
|
||||
|
||||
@@ -57,24 +62,33 @@ class ConversationManagerImpl implements ConversationManager {
|
||||
|
||||
@Override
|
||||
public GroupCount getGroupCount(ContactId contactId) throws DbException {
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getGroupCount(txn, contactId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupCount getGroupCount(Transaction txn, ContactId contactId)
|
||||
throws DbException {
|
||||
int msgCount = 0, unreadCount = 0;
|
||||
long latestTime = 0;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
for (ConversationClient client : clients) {
|
||||
GroupCount count = client.getGroupCount(txn, contactId);
|
||||
msgCount += count.getMsgCount();
|
||||
unreadCount += count.getUnreadCount();
|
||||
if (count.getLatestMsgTime() > latestTime)
|
||||
latestTime = count.getLatestMsgTime();
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
for (ConversationClient client : clients) {
|
||||
GroupCount count = client.getGroupCount(txn, contactId);
|
||||
msgCount += count.getMsgCount();
|
||||
unreadCount += count.getUnreadCount();
|
||||
if (count.getLatestMsgTime() > latestTime)
|
||||
latestTime = count.getLatestMsgTime();
|
||||
}
|
||||
return new GroupCount(msgCount, unreadCount, latestTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimestampForOutgoingMessage(Transaction txn, ContactId c)
|
||||
throws DbException {
|
||||
long now = clock.currentTimeMillis();
|
||||
GroupCount gc = getGroupCount(txn, c);
|
||||
return max(now, gc.getLatestMsgTime() + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeletionResult deleteAllMessages(ContactId c) throws DbException {
|
||||
return db.transactionWithResult(false, txn -> {
|
||||
@@ -87,8 +101,8 @@ class ConversationManagerImpl implements ConversationManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeletionResult deleteMessages(ContactId c, Collection<MessageId> toDelete)
|
||||
throws DbException {
|
||||
public DeletionResult deleteMessages(ContactId c,
|
||||
Collection<MessageId> toDelete) throws DbException {
|
||||
return db.transactionWithResult(false, txn -> {
|
||||
DeletionResult result = new DeletionResult();
|
||||
for (ConversationClient client : clients) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessage;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
||||
@@ -31,6 +32,7 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
|
||||
import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
|
||||
@@ -54,6 +56,7 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
private final MessageParser messageParser;
|
||||
private final MessageEncoder messageEncoder;
|
||||
private final AutoDeleteManager autoDeleteManager;
|
||||
private final ConversationManager conversationManager;
|
||||
private final Clock clock;
|
||||
|
||||
AbstractProtocolEngine(
|
||||
@@ -68,6 +71,7 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
MessageEncoder messageEncoder,
|
||||
MessageTracker messageTracker,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock) {
|
||||
this.db = db;
|
||||
this.clientHelper = clientHelper;
|
||||
@@ -80,6 +84,7 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
this.messageEncoder = messageEncoder;
|
||||
this.messageTracker = messageTracker;
|
||||
this.autoDeleteManager = autoDeleteManager;
|
||||
this.conversationManager = conversationManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@@ -110,8 +115,8 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
}
|
||||
|
||||
Message sendInviteMessage(Transaction txn, S s,
|
||||
@Nullable String text, long timestamp, byte[] signature)
|
||||
throws DbException {
|
||||
@Nullable String text, long timestamp, byte[] signature,
|
||||
long timer) throws DbException {
|
||||
Group g = db.getGroup(txn, s.getPrivateGroupId());
|
||||
PrivateGroup privateGroup;
|
||||
try {
|
||||
@@ -122,7 +127,6 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
Message m;
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
m = messageEncoder.encodeInviteMessage(s.getContactGroupId(),
|
||||
privateGroup.getId(), timestamp, privateGroup.getName(),
|
||||
privateGroup.getCreator(), privateGroup.getSalt(), text,
|
||||
@@ -142,6 +146,9 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
Message sendJoinMessage(Transaction txn, S s, boolean visibleInUi)
|
||||
throws DbException {
|
||||
Message m;
|
||||
long localTimestamp = visibleInUi
|
||||
? getTimestampForVisibleMessage(txn, s)
|
||||
: getTimestampForInvisibleMessage(s);
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
// Set auto-delete timer if manually accepting an invitation
|
||||
@@ -149,13 +156,13 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
? autoDeleteManager.getAutoDeleteTimer(txn, c)
|
||||
: NO_AUTO_DELETE_TIMER;
|
||||
m = messageEncoder.encodeJoinMessage(s.getContactGroupId(),
|
||||
s.getPrivateGroupId(), getLocalTimestamp(s),
|
||||
s.getPrivateGroupId(), localTimestamp,
|
||||
s.getLastLocalMessageId(), timer);
|
||||
sendMessage(txn, m, JOIN, s.getPrivateGroupId(), visibleInUi,
|
||||
timer);
|
||||
} else {
|
||||
m = messageEncoder.encodeJoinMessage(s.getContactGroupId(),
|
||||
s.getPrivateGroupId(), getLocalTimestamp(s),
|
||||
s.getPrivateGroupId(), localTimestamp,
|
||||
s.getLastLocalMessageId());
|
||||
sendMessage(txn, m, JOIN, s.getPrivateGroupId(), visibleInUi,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
@@ -166,6 +173,9 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
Message sendLeaveMessage(Transaction txn, S s, boolean visibleInUi)
|
||||
throws DbException {
|
||||
Message m;
|
||||
long localTimestamp = visibleInUi
|
||||
? getTimestampForVisibleMessage(txn, s)
|
||||
: getTimestampForInvisibleMessage(s);
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
// Set auto-delete timer if manually accepting an invitation
|
||||
@@ -173,13 +183,13 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
? autoDeleteManager.getAutoDeleteTimer(txn, c)
|
||||
: NO_AUTO_DELETE_TIMER;
|
||||
m = messageEncoder.encodeLeaveMessage(s.getContactGroupId(),
|
||||
s.getPrivateGroupId(), getLocalTimestamp(s),
|
||||
s.getPrivateGroupId(), localTimestamp,
|
||||
s.getLastLocalMessageId(), timer);
|
||||
sendMessage(txn, m, LEAVE, s.getPrivateGroupId(), visibleInUi,
|
||||
timer);
|
||||
} else {
|
||||
m = messageEncoder.encodeLeaveMessage(s.getContactGroupId(),
|
||||
s.getPrivateGroupId(), getLocalTimestamp(s),
|
||||
s.getPrivateGroupId(), localTimestamp,
|
||||
s.getLastLocalMessageId());
|
||||
sendMessage(txn, m, LEAVE, s.getPrivateGroupId(), visibleInUi,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
@@ -190,7 +200,7 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
Message sendAbortMessage(Transaction txn, S session) throws DbException {
|
||||
Message m = messageEncoder.encodeAbortMessage(
|
||||
session.getContactGroupId(), session.getPrivateGroupId(),
|
||||
getLocalTimestamp(session));
|
||||
getTimestampForInvisibleMessage(session));
|
||||
sendMessage(txn, m, ABORT, session.getPrivateGroupId(), false,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
return m;
|
||||
@@ -246,7 +256,7 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
PrivateGroup privateGroup = privateGroupFactory.createPrivateGroup(
|
||||
invite.getGroupName(), invite.getCreator(), invite.getSalt());
|
||||
long timestamp =
|
||||
Math.max(clock.currentTimeMillis(), invite.getTimestamp() + 1);
|
||||
max(clock.currentTimeMillis(), invite.getTimestamp() + 1);
|
||||
// TODO: Create the join message on the crypto executor
|
||||
LocalAuthor member = identityManager.getLocalAuthor(txn);
|
||||
GroupMessage joinMessage = groupMessageFactory.createJoinMessage(
|
||||
@@ -256,10 +266,34 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
.addPrivateGroup(txn, privateGroup, joinMessage, false);
|
||||
}
|
||||
|
||||
long getLocalTimestamp(S session) {
|
||||
return Math.max(clock.currentTimeMillis(),
|
||||
Math.max(session.getLocalTimestamp(),
|
||||
session.getInviteTimestamp()) + 1);
|
||||
/**
|
||||
* Returns a timestamp for a visible outgoing message. The timestamp is
|
||||
* later than the timestamp of any message sent or received so far in the
|
||||
* conversation, and later than the {@link #getSessionTimestamp(Session)
|
||||
* session timestamp}.
|
||||
*/
|
||||
long getTimestampForVisibleMessage(Transaction txn, S s)
|
||||
throws DbException {
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
long conversationTimestamp =
|
||||
conversationManager.getTimestampForOutgoingMessage(txn, c);
|
||||
return max(conversationTimestamp, getSessionTimestamp(s) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a timestamp for an invisible outgoing message. The timestamp is
|
||||
* later than the {@link #getSessionTimestamp(Session) session timestamp}.
|
||||
*/
|
||||
long getTimestampForInvisibleMessage(S s) {
|
||||
return max(clock.currentTimeMillis(), getSessionTimestamp(s) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest timestamp of any message sent so far in the session,
|
||||
* and any invite message sent or received so far in the session.
|
||||
*/
|
||||
private long getSessionTimestamp(S s) {
|
||||
return max(s.getLocalTimestamp(), s.getInviteTimestamp());
|
||||
}
|
||||
|
||||
private void sendMessage(Transaction txn, Message m, MessageType type,
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.ProtocolStateException;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
|
||||
@@ -24,6 +25,7 @@ import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRespons
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
import static org.briarproject.briar.privategroup.invitation.CreatorState.DISSOLVED;
|
||||
@@ -49,20 +51,22 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
|
||||
MessageEncoder messageEncoder,
|
||||
MessageTracker messageTracker,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker,
|
||||
autoDeleteManager, clock);
|
||||
autoDeleteManager, conversationManager, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreatorSession onInviteAction(Transaction txn, CreatorSession s,
|
||||
@Nullable String text, long timestamp, byte[] signature)
|
||||
throws DbException {
|
||||
@Nullable String text, long timestamp, byte[] signature,
|
||||
long autoDeleteTimer) throws DbException {
|
||||
switch (s.getState()) {
|
||||
case START:
|
||||
return onLocalInvite(txn, s, text, timestamp, signature);
|
||||
return onLocalInvite(txn, s, text, timestamp, signature,
|
||||
autoDeleteTimer);
|
||||
case INVITED:
|
||||
case JOINED:
|
||||
case LEFT:
|
||||
@@ -152,14 +156,16 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
|
||||
}
|
||||
|
||||
private CreatorSession onLocalInvite(Transaction txn, CreatorSession s,
|
||||
@Nullable String text, long timestamp, byte[] signature)
|
||||
throws DbException {
|
||||
@Nullable String text, long timestamp, byte[] signature,
|
||||
long autoDeleteTimer) throws DbException {
|
||||
// Send an INVITE message
|
||||
Message sent = sendInviteMessage(txn, s, text, timestamp, signature);
|
||||
Message sent = sendInviteMessage(txn, s, text, timestamp, signature,
|
||||
autoDeleteTimer);
|
||||
// Track the message
|
||||
messageTracker.trackOutgoingMessage(txn, sent);
|
||||
// Move to the INVITED state
|
||||
long localTimestamp = Math.max(timestamp, getLocalTimestamp(s));
|
||||
long localTimestamp =
|
||||
max(timestamp, getTimestampForVisibleMessage(txn, s));
|
||||
return new CreatorSession(s.getContactGroupId(), s.getPrivateGroupId(),
|
||||
sent.getId(), s.getLastRemoteMessageId(), localTimestamp,
|
||||
timestamp, INVITED);
|
||||
|
||||
@@ -257,8 +257,8 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
||||
|
||||
@Override
|
||||
public void sendInvitation(GroupId privateGroupId, ContactId c,
|
||||
@Nullable String text, long timestamp, byte[] signature)
|
||||
throws DbException {
|
||||
@Nullable String text, long timestamp, byte[] signature,
|
||||
long autoDeleteTimer) throws DbException {
|
||||
SessionId sessionId = getSessionId(privateGroupId);
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
@@ -281,7 +281,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
||||
}
|
||||
// Handle the invite action
|
||||
session = creatorEngine.onInviteAction(txn, session, text,
|
||||
timestamp, signature);
|
||||
timestamp, signature, autoDeleteTimer);
|
||||
// Store the updated session
|
||||
storeSession(txn, storageId, session);
|
||||
db.commitTransaction(txn);
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.ProtocolStateException;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
|
||||
@@ -42,7 +43,8 @@ import static org.briarproject.briar.privategroup.invitation.InviteeState.START;
|
||||
@NotNullByDefault
|
||||
class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
|
||||
|
||||
InviteeProtocolEngine(DatabaseComponent db,
|
||||
InviteeProtocolEngine(
|
||||
DatabaseComponent db,
|
||||
ClientHelper clientHelper,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
PrivateGroupManager privateGroupManager,
|
||||
@@ -53,16 +55,18 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
|
||||
MessageEncoder messageEncoder,
|
||||
MessageTracker messageTracker,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker,
|
||||
autoDeleteManager, clock);
|
||||
autoDeleteManager, conversationManager, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InviteeSession onInviteAction(Transaction txn, InviteeSession s,
|
||||
@Nullable String text, long timestamp, byte[] signature) {
|
||||
@Nullable String text, long timestamp, byte[] signature,
|
||||
long autoDeleteTimer) {
|
||||
throw new UnsupportedOperationException(); // Invalid in this role
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.ProtocolStateException;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
|
||||
@@ -49,16 +50,18 @@ class PeerProtocolEngine extends AbstractProtocolEngine<PeerSession> {
|
||||
MessageEncoder messageEncoder,
|
||||
MessageTracker messageTracker,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker,
|
||||
autoDeleteManager, clock);
|
||||
autoDeleteManager, conversationManager, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PeerSession onInviteAction(Transaction txn, PeerSession s,
|
||||
@Nullable String text, long timestamp, byte[] signature) {
|
||||
@Nullable String text, long timestamp, byte[] signature,
|
||||
long autoDeleteTimer) {
|
||||
throw new UnsupportedOperationException(); // Invalid in this role
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@NotNullByDefault
|
||||
interface ProtocolEngine<S extends Session> {
|
||||
interface ProtocolEngine<S extends Session<?>> {
|
||||
|
||||
S onInviteAction(Transaction txn, S session, @Nullable String text,
|
||||
long timestamp, byte[] signature) throws DbException;
|
||||
long timestamp, byte[] signature, long autoDeleteTimer)
|
||||
throws DbException;
|
||||
|
||||
S onJoinAction(Transaction txn, S session) throws DbException;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
|
||||
@@ -30,6 +31,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
private final MessageEncoder messageEncoder;
|
||||
private final MessageTracker messageTracker;
|
||||
private final AutoDeleteManager autoDeleteManager;
|
||||
private final ConversationManager conversationManager;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
@@ -45,6 +47,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
MessageEncoder messageEncoder,
|
||||
MessageTracker messageTracker,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock) {
|
||||
this.db = db;
|
||||
this.clientHelper = clientHelper;
|
||||
@@ -57,6 +60,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
this.messageEncoder = messageEncoder;
|
||||
this.messageTracker = messageTracker;
|
||||
this.autoDeleteManager = autoDeleteManager;
|
||||
this.conversationManager = conversationManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@@ -66,7 +70,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker,
|
||||
autoDeleteManager, clock);
|
||||
autoDeleteManager, conversationManager, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,7 +79,7 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker,
|
||||
autoDeleteManager, clock);
|
||||
autoDeleteManager, conversationManager, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,6 +88,6 @@ class ProtocolEngineFactoryImpl implements ProtocolEngineFactory {
|
||||
clientVersioningManager, privateGroupManager,
|
||||
privateGroupFactory, groupMessageFactory, identityManager,
|
||||
messageParser, messageEncoder, messageTracker,
|
||||
autoDeleteManager, clock);
|
||||
autoDeleteManager, conversationManager, clock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ 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;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationRequest;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
@@ -41,13 +42,15 @@ class BlogProtocolEngineImpl extends ProtocolEngineImpl<Blog> {
|
||||
MessageParser<Blog> messageParser,
|
||||
MessageTracker messageTracker,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock,
|
||||
BlogManager blogManager,
|
||||
InvitationFactory<Blog, BlogInvitationResponse> invitationFactory) {
|
||||
super(db, clientHelper, clientVersioningManager, messageEncoder,
|
||||
messageParser, messageTracker, autoDeleteManager, clock,
|
||||
BlogSharingManager.CLIENT_ID, BlogSharingManager.MAJOR_VERSION,
|
||||
BlogManager.CLIENT_ID, BlogManager.MAJOR_VERSION);
|
||||
messageParser, messageTracker, autoDeleteManager,
|
||||
conversationManager, clock, BlogSharingManager.CLIENT_ID,
|
||||
BlogSharingManager.MAJOR_VERSION, BlogManager.CLIENT_ID,
|
||||
BlogManager.MAJOR_VERSION);
|
||||
this.blogManager = blogManager;
|
||||
this.invitationFactory = invitationFactory;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationRequest;
|
||||
import org.briarproject.briar.api.forum.Forum;
|
||||
import org.briarproject.briar.api.forum.ForumInvitationResponse;
|
||||
@@ -41,14 +42,15 @@ class ForumProtocolEngineImpl extends ProtocolEngineImpl<Forum> {
|
||||
MessageParser<Forum> messageParser,
|
||||
MessageTracker messageTracker,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock,
|
||||
ForumManager forumManager,
|
||||
InvitationFactory<Forum, ForumInvitationResponse> invitationFactory) {
|
||||
super(db, clientHelper, clientVersioningManager, messageEncoder,
|
||||
messageParser, messageTracker, autoDeleteManager, clock,
|
||||
ForumSharingManager.CLIENT_ID,
|
||||
ForumSharingManager.MAJOR_VERSION,
|
||||
ForumManager.CLIENT_ID, ForumManager.MAJOR_VERSION);
|
||||
messageParser, messageTracker, autoDeleteManager,
|
||||
conversationManager, clock, ForumSharingManager.CLIENT_ID,
|
||||
ForumSharingManager.MAJOR_VERSION, ForumManager.CLIENT_ID,
|
||||
ForumManager.MAJOR_VERSION);
|
||||
this.forumManager = forumManager;
|
||||
this.invitationFactory = invitationFactory;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import javax.annotation.Nullable;
|
||||
interface ProtocolEngine<S extends Shareable> {
|
||||
|
||||
Session onInviteAction(Transaction txn, Session session,
|
||||
@Nullable String text, long timestamp) throws DbException;
|
||||
@Nullable String text) throws DbException;
|
||||
|
||||
Session onAcceptAction(Transaction txn, Session session) throws DbException;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.ProtocolStateException;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.sharing.Shareable;
|
||||
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
|
||||
|
||||
@@ -29,6 +30,7 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
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;
|
||||
@@ -58,6 +60,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
private final MessageEncoder messageEncoder;
|
||||
private final MessageTracker messageTracker;
|
||||
private final AutoDeleteManager autoDeleteManager;
|
||||
private final ConversationManager conversationManager;
|
||||
private final Clock clock;
|
||||
private final ClientId sharingClientId, shareableClientId;
|
||||
private final int sharingClientMajorVersion, shareableClientMajorVersion;
|
||||
@@ -70,6 +73,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
MessageParser<S> messageParser,
|
||||
MessageTracker messageTracker,
|
||||
AutoDeleteManager autoDeleteManager,
|
||||
ConversationManager conversationManager,
|
||||
Clock clock,
|
||||
ClientId sharingClientId,
|
||||
int sharingClientMajorVersion,
|
||||
@@ -82,6 +86,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
this.messageParser = messageParser;
|
||||
this.messageTracker = messageTracker;
|
||||
this.autoDeleteManager = autoDeleteManager;
|
||||
this.conversationManager = conversationManager;
|
||||
this.clock = clock;
|
||||
this.sharingClientId = sharingClientId;
|
||||
this.sharingClientMajorVersion = sharingClientMajorVersion;
|
||||
@@ -91,10 +96,10 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
|
||||
@Override
|
||||
public Session onInviteAction(Transaction txn, Session s,
|
||||
@Nullable String text, long timestamp) throws DbException {
|
||||
@Nullable String text) throws DbException {
|
||||
switch (s.getState()) {
|
||||
case START:
|
||||
return onLocalInvite(txn, s, text, timestamp);
|
||||
return onLocalInvite(txn, s, text);
|
||||
case LOCAL_INVITED:
|
||||
case REMOTE_INVITED:
|
||||
case SHARING:
|
||||
@@ -107,9 +112,9 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
}
|
||||
|
||||
private Session onLocalInvite(Transaction txn, Session s,
|
||||
@Nullable String text, long timestamp) throws DbException {
|
||||
@Nullable String text) throws DbException {
|
||||
// Send an INVITE message
|
||||
Message sent = sendInviteMessage(txn, s, text, timestamp);
|
||||
Message sent = sendInviteMessage(txn, s, text);
|
||||
// Track the message
|
||||
messageTracker.trackOutgoingMessage(txn, sent);
|
||||
// Make the shareable visible to the contact
|
||||
@@ -125,7 +130,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
}
|
||||
|
||||
private Message sendInviteMessage(Transaction txn, Session s,
|
||||
@Nullable String text, long timestamp) throws DbException {
|
||||
@Nullable String text) throws DbException {
|
||||
Group g = db.getGroup(txn, s.getShareableId());
|
||||
BdfList descriptor;
|
||||
try {
|
||||
@@ -133,8 +138,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e); // Invalid group descriptor
|
||||
}
|
||||
long localTimestamp = Math.max(timestamp, getLocalTimestamp(s));
|
||||
Message m;
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
@@ -201,16 +206,17 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
private Message sendAcceptMessage(Transaction txn, Session s)
|
||||
throws DbException {
|
||||
Message m;
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
||||
s.getShareableId(), getLocalTimestamp(s),
|
||||
s.getShareableId(), localTimestamp,
|
||||
s.getLastLocalMessageId(), timer);
|
||||
sendMessage(txn, m, ACCEPT, s.getShareableId(), true, timer);
|
||||
} else {
|
||||
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
||||
s.getShareableId(), getLocalTimestamp(s),
|
||||
s.getShareableId(), localTimestamp,
|
||||
s.getLastLocalMessageId());
|
||||
sendMessage(txn, m, ACCEPT, s.getShareableId(), true,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
@@ -254,16 +260,17 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
private Message sendDeclineMessage(Transaction txn, Session s)
|
||||
throws DbException {
|
||||
Message m;
|
||||
long localTimestamp = getTimestampForVisibleMessage(txn, s);
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
if (contactSupportsAutoDeletion(txn, c)) {
|
||||
long timer = autoDeleteManager.getAutoDeleteTimer(txn, c);
|
||||
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
||||
s.getShareableId(), getLocalTimestamp(s),
|
||||
s.getShareableId(), localTimestamp,
|
||||
s.getLastLocalMessageId(), timer);
|
||||
sendMessage(txn, m, DECLINE, s.getShareableId(), true, timer);
|
||||
} else {
|
||||
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
||||
s.getShareableId(), getLocalTimestamp(s),
|
||||
s.getShareableId(), localTimestamp,
|
||||
s.getLastLocalMessageId());
|
||||
sendMessage(txn, m, DECLINE, s.getShareableId(), true,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
@@ -307,9 +314,10 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
|
||||
private Message sendLeaveMessage(Transaction txn, Session session)
|
||||
throws DbException {
|
||||
long localTimestamp = getTimestampForInvisibleMessage(session);
|
||||
Message m = messageEncoder.encodeLeaveMessage(
|
||||
session.getContactGroupId(), session.getShareableId(),
|
||||
getLocalTimestamp(session), session.getLastLocalMessageId());
|
||||
localTimestamp, session.getLastLocalMessageId());
|
||||
sendMessage(txn, m, LEAVE, session.getShareableId(), false,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
return m;
|
||||
@@ -605,9 +613,10 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
|
||||
private Message sendAbortMessage(Transaction txn, Session session)
|
||||
throws DbException {
|
||||
long localTimestamp = getTimestampForInvisibleMessage(session);
|
||||
Message m = messageEncoder.encodeAbortMessage(
|
||||
session.getContactGroupId(), session.getShareableId(),
|
||||
getLocalTimestamp(session), session.getLastLocalMessageId());
|
||||
localTimestamp, session.getLastLocalMessageId());
|
||||
sendMessage(txn, m, ABORT, session.getShareableId(), false,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
return m;
|
||||
@@ -677,10 +686,34 @@ abstract class ProtocolEngineImpl<S extends Shareable>
|
||||
return !dependency.equals(expected);
|
||||
}
|
||||
|
||||
private long getLocalTimestamp(Session session) {
|
||||
return Math.max(clock.currentTimeMillis(),
|
||||
Math.max(session.getLocalTimestamp(),
|
||||
session.getInviteTimestamp()) + 1);
|
||||
/**
|
||||
* Returns a timestamp for a visible outgoing message. The timestamp is
|
||||
* later than the timestamp of any message sent or received so far in the
|
||||
* conversation, and later than the {@link #getSessionTimestamp(Session)
|
||||
* session timestamp}.
|
||||
*/
|
||||
private long getTimestampForVisibleMessage(Transaction txn, Session s)
|
||||
throws DbException {
|
||||
ContactId c = getContactId(txn, s.getContactGroupId());
|
||||
long conversationTimestamp =
|
||||
conversationManager.getTimestampForOutgoingMessage(txn, c);
|
||||
return max(conversationTimestamp, getSessionTimestamp(s) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a timestamp for an invisible outgoing message. The timestamp is
|
||||
* later than the {@link #getSessionTimestamp(Session) session timestamp}.
|
||||
*/
|
||||
private long getTimestampForInvisibleMessage(Session s) {
|
||||
return max(clock.currentTimeMillis(), getSessionTimestamp(s) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest timestamp of any message sent so far in the session,
|
||||
* and any invite message sent or received so far in the session.
|
||||
*/
|
||||
private long getSessionTimestamp(Session s) {
|
||||
return max(s.getLocalTimestamp(), s.getInviteTimestamp());
|
||||
}
|
||||
|
||||
private ContactId getContactId(Transaction txn, GroupId contactGroupId)
|
||||
|
||||
@@ -248,7 +248,7 @@ abstract class SharingManagerImpl<S extends Shareable>
|
||||
|
||||
@Override
|
||||
public void sendInvitation(GroupId shareableId, ContactId contactId,
|
||||
@Nullable String text, long timestamp) throws DbException {
|
||||
@Nullable String text) throws DbException {
|
||||
SessionId sessionId = getSessionId(shareableId);
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
@@ -273,7 +273,7 @@ abstract class SharingManagerImpl<S extends Shareable>
|
||||
storageId = ss.storageId;
|
||||
}
|
||||
// Handle the invite action
|
||||
session = engine.onInviteAction(txn, session, text, timestamp);
|
||||
session = engine.onInviteAction(txn, session, text);
|
||||
// Store the updated session
|
||||
storeSession(txn, storageId, session);
|
||||
db.commitTransaction(txn);
|
||||
|
||||
@@ -45,8 +45,7 @@ public class ForumManagerTest
|
||||
forum0 = forumManager0.addForum("Test Forum");
|
||||
groupId0 = forum0.getId();
|
||||
// share forum
|
||||
forumSharingManager0.sendInvitation(groupId0, contactId1From0, null,
|
||||
clock.currentTimeMillis());
|
||||
forumSharingManager0.sendInvitation(groupId0, contactId1From0, null);
|
||||
sync0To1(1, true);
|
||||
forumSharingManager1.respondToInvitation(forum0, contact0From1, true);
|
||||
sync1To0(1, true);
|
||||
@@ -194,8 +193,7 @@ public class ForumManagerTest
|
||||
// share a second forum
|
||||
Forum forum1 = forumManager0.addForum("Test Forum1");
|
||||
GroupId g1 = forum1.getId();
|
||||
forumSharingManager0.sendInvitation(g1, contactId1From0, null,
|
||||
clock.currentTimeMillis());
|
||||
forumSharingManager0.sendInvitation(g1, contactId1From0, null);
|
||||
sync0To1(1, true);
|
||||
forumSharingManager1.respondToInvitation(forum1, contact0From1, true);
|
||||
sync1To0(1, true);
|
||||
|
||||
@@ -140,11 +140,9 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
Contact introducee1 = contact1From0;
|
||||
Contact introducee2 = contact2From0;
|
||||
introductionManager0
|
||||
.makeIntroduction(introducee1, introducee2, "Hi!", time);
|
||||
introductionManager0.makeIntroduction(introducee1, introducee2, "Hi!");
|
||||
|
||||
// check that messages are tracked properly
|
||||
Group g1 = introductionManager0.getContactGroup(introducee1);
|
||||
@@ -264,11 +262,9 @@ public class IntroductionIntegrationTest
|
||||
addListeners(false, true);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
Contact introducee1 = contact1From0;
|
||||
Contact introducee2 = contact2From0;
|
||||
introductionManager0
|
||||
.makeIntroduction(introducee1, introducee2, null, time);
|
||||
introductionManager0.makeIntroduction(introducee1, introducee2, null);
|
||||
|
||||
// sync request messages
|
||||
sync0To1(1, true);
|
||||
@@ -356,9 +352,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, false);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// sync request messages
|
||||
sync0To1(1, true);
|
||||
@@ -412,9 +407,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(false, true);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// sync request messages
|
||||
sync0To1(1, true);
|
||||
@@ -438,9 +432,8 @@ public class IntroductionIntegrationTest
|
||||
assertFalse(listener1.aborted);
|
||||
assertFalse(listener2.aborted);
|
||||
|
||||
time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// sync request messages
|
||||
sync0To1(1, true);
|
||||
@@ -457,9 +450,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!");
|
||||
|
||||
// sync first request message
|
||||
sync0To1(1, true);
|
||||
@@ -482,7 +474,7 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// answer request manually
|
||||
introductionManager2.respondToIntroduction(contactId0From2,
|
||||
listener2.sessionId, time, true);
|
||||
listener2.sessionId, true);
|
||||
|
||||
// sync second response and AUTH
|
||||
sync2To0(2, true);
|
||||
@@ -518,11 +510,10 @@ public class IntroductionIntegrationTest
|
||||
listener2.answerRequests = false;
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
Contact introducee1 = contact1From0;
|
||||
Contact introducee2 = contact2From0;
|
||||
introductionManager0
|
||||
.makeIntroduction(introducee1, introducee2, null, time);
|
||||
.makeIntroduction(introducee1, introducee2, null);
|
||||
|
||||
// sync request messages
|
||||
sync0To1(1, true);
|
||||
@@ -564,7 +555,7 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// answer request manually
|
||||
introductionManager2.respondToIntroduction(contactId0From2,
|
||||
listener2.sessionId, time, false);
|
||||
listener2.sessionId, false);
|
||||
|
||||
// now introducee2 should have returned to the START state
|
||||
introduceeSession = getIntroduceeSession(c2);
|
||||
@@ -611,9 +602,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, false);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact1From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact1From0, null);
|
||||
|
||||
// sync request messages
|
||||
sync0To1(1, false);
|
||||
@@ -637,9 +627,8 @@ public class IntroductionIntegrationTest
|
||||
.canIntroduce(contact1From0, contact2From0));
|
||||
|
||||
// make the introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// no more introduction allowed while the existing one is in progress
|
||||
assertFalse(introductionManager0
|
||||
@@ -647,7 +636,7 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// try it anyway and fail
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -661,9 +650,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make the introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// sync REQUEST messages
|
||||
sync0To1(1, true);
|
||||
@@ -719,9 +707,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make the introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// sync REQUEST messages
|
||||
sync0To1(1, true);
|
||||
@@ -766,9 +753,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make the introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// sync REQUEST to introducee1
|
||||
sync0To1(1, true);
|
||||
@@ -803,9 +789,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make the introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// sync REQUEST to introducee1
|
||||
sync0To1(1, true);
|
||||
@@ -838,9 +823,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(false, true);
|
||||
|
||||
// make the introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// sync REQUEST to introducee1
|
||||
sync0To1(1, true);
|
||||
@@ -873,9 +857,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make the introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// sync REQUEST messages
|
||||
sync0To1(1, true);
|
||||
@@ -914,9 +897,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!");
|
||||
|
||||
// sync first request message
|
||||
sync0To1(1, true);
|
||||
@@ -943,9 +925,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!");
|
||||
|
||||
// sync first request message
|
||||
sync0To1(1, true);
|
||||
@@ -987,9 +968,8 @@ public class IntroductionIntegrationTest
|
||||
@Test
|
||||
public void testIntroductionAfterReAddingContacts() throws Exception {
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// 0 and 1 remove and re-add each other
|
||||
contactManager0.removeContact(contactId1From0);
|
||||
@@ -1016,9 +996,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make new introduction
|
||||
time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||
.makeIntroduction(contact1From0, contact2From0, null);
|
||||
|
||||
// introduction should sync and not be INVALID or PENDING
|
||||
sync0To1(1, true);
|
||||
@@ -1032,9 +1011,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!");
|
||||
|
||||
// sync request messages
|
||||
sync0To1(1, true);
|
||||
@@ -1147,9 +1125,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(true, true);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!");
|
||||
|
||||
// sync first REQUEST message
|
||||
sync0To1(1, true);
|
||||
@@ -1292,7 +1269,7 @@ public class IntroductionIntegrationTest
|
||||
assertTrue(introductionManager0
|
||||
.canIntroduce(contact1From0, contact2From0));
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Ho!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Ho!");
|
||||
sync0To1(1, true);
|
||||
sync0To2(1, true);
|
||||
|
||||
@@ -1332,9 +1309,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(false, false);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!");
|
||||
|
||||
// sync REQUEST messages
|
||||
sync0To1(1, true);
|
||||
@@ -1399,9 +1375,8 @@ public class IntroductionIntegrationTest
|
||||
// a new introduction is still possible
|
||||
assertTrue(introductionManager0
|
||||
.canIntroduce(contact1From0, contact2From0));
|
||||
time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Ho!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Ho!");
|
||||
sync0To1(1, true);
|
||||
sync0To2(1, true);
|
||||
|
||||
@@ -1428,9 +1403,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(false, false);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!");
|
||||
|
||||
// sync REQUEST messages
|
||||
sync0To1(1, true);
|
||||
@@ -1458,9 +1432,8 @@ public class IntroductionIntegrationTest
|
||||
// a new introduction is still possible
|
||||
assertTrue(introductionManager0
|
||||
.canIntroduce(contact1From0, contact2From0));
|
||||
time = clock.currentTimeMillis();
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Ho!", time);
|
||||
.makeIntroduction(contact1From0, contact2From0, "Ho!");
|
||||
sync0To1(1, true);
|
||||
sync0To2(1, true);
|
||||
|
||||
@@ -1496,9 +1469,8 @@ public class IntroductionIntegrationTest
|
||||
addListeners(false, false);
|
||||
|
||||
// make introduction
|
||||
long time = clock.currentTimeMillis();
|
||||
introductionManager0.makeIntroduction(contact1From0, contact2From0,
|
||||
"Hi!", time);
|
||||
introductionManager0
|
||||
.makeIntroduction(contact1From0, contact2From0, "Hi!");
|
||||
|
||||
// deleting the introduction for introducee1 will fail
|
||||
Collection<ConversationMessageHeader> m1From0 = getMessages1From0();
|
||||
@@ -1795,16 +1767,13 @@ public class IntroductionIntegrationTest
|
||||
IntroductionRequest ir = introEvent.getMessageHeader();
|
||||
ContactId contactId = introEvent.getContactId();
|
||||
sessionId = ir.getSessionId();
|
||||
long time = clock.currentTimeMillis();
|
||||
try {
|
||||
if (introducee == 1 && answerRequests) {
|
||||
introductionManager1
|
||||
.respondToIntroduction(contactId, sessionId,
|
||||
time, accept);
|
||||
introductionManager1.respondToIntroduction(contactId,
|
||||
sessionId, accept);
|
||||
} else if (introducee == 2 && answerRequests) {
|
||||
introductionManager2
|
||||
.respondToIntroduction(contactId, sessionId,
|
||||
time, accept);
|
||||
introductionManager2.respondToIntroduction(contactId,
|
||||
sessionId, accept);
|
||||
}
|
||||
} catch (DbException exception) {
|
||||
eventWaiter.rethrow(exception);
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.Collection;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
|
||||
import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_CONTACT;
|
||||
import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_US;
|
||||
@@ -220,8 +221,8 @@ public class PrivateGroupIntegrationTest
|
||||
byte[] signature = groupInvitationFactory
|
||||
.signInvitation(contact, groupId0, timestamp,
|
||||
author0.getPrivateKey());
|
||||
groupInvitationManager0
|
||||
.sendInvitation(groupId0, c, text, timestamp, signature);
|
||||
groupInvitationManager0.sendInvitation(groupId0, c, text, timestamp,
|
||||
signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
private GroupMember getGroupMember(PrivateGroupManager groupManager,
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
|
||||
@@ -62,6 +63,8 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
final MessageTracker messageTracker = context.mock(MessageTracker.class);
|
||||
final AutoDeleteManager autoDeleteManager =
|
||||
context.mock(AutoDeleteManager.class);
|
||||
final ConversationManager conversationManager =
|
||||
context.mock(ConversationManager.class);
|
||||
final Clock clock = context.mock(Clock.class);
|
||||
|
||||
final Transaction txn = new Transaction(null, false);
|
||||
@@ -115,16 +118,26 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
assertEquals(inviteTimestamp, s.getInviteTimestamp());
|
||||
}
|
||||
|
||||
void expectGetLocalTimestamp(long time) {
|
||||
void expectGetTimestampForInvisibleMessage(long time) {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(time));
|
||||
}});
|
||||
}
|
||||
|
||||
void expectGetTimestampForVisibleMessage(long time) throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getContactId(txn, contactGroupId);
|
||||
will(returnValue(contactId));
|
||||
oneOf(conversationManager)
|
||||
.getTimestampForOutgoingMessage(txn, contactId);
|
||||
will(returnValue(time));
|
||||
}});
|
||||
}
|
||||
|
||||
void expectSendInviteMessage(String text) throws Exception {
|
||||
expectCheckWhetherContactSupportsAutoDeletion(true);
|
||||
expectGetLocalTimestamp(messageTimestamp);
|
||||
expectGetTimestampForVisibleMessage(messageTimestamp);
|
||||
expectCheckWhetherContactSupportsAutoDeletion();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageEncoder).encodeInviteMessage(contactGroupId,
|
||||
privateGroupId, inviteTimestamp, privateGroup.getName(),
|
||||
@@ -137,8 +150,10 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
|
||||
void expectSendJoinMessage(JoinMessage m, boolean visible)
|
||||
throws Exception {
|
||||
expectCheckWhetherContactSupportsAutoDeletion(visible);
|
||||
expectGetLocalTimestamp(messageTimestamp);
|
||||
if (visible) expectGetTimestampForVisibleMessage(messageTimestamp);
|
||||
else expectGetTimestampForInvisibleMessage(messageTimestamp);
|
||||
expectCheckWhetherContactSupportsAutoDeletion();
|
||||
if (visible) expectGetAutoDeleteTimer();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageEncoder).encodeJoinMessage(m.getContactGroupId(),
|
||||
m.getPrivateGroupId(), m.getTimestamp(),
|
||||
@@ -149,8 +164,10 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
}
|
||||
|
||||
void expectSendLeaveMessage(boolean visible) throws Exception {
|
||||
expectCheckWhetherContactSupportsAutoDeletion(visible);
|
||||
expectGetLocalTimestamp(messageTimestamp);
|
||||
if (visible) expectGetTimestampForVisibleMessage(messageTimestamp);
|
||||
else expectGetTimestampForInvisibleMessage(messageTimestamp);
|
||||
expectCheckWhetherContactSupportsAutoDeletion();
|
||||
if (visible) expectGetAutoDeleteTimer();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageEncoder).encodeLeaveMessage(contactGroupId,
|
||||
privateGroupId, messageTimestamp, lastLocalMessageId,
|
||||
@@ -161,7 +178,7 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
}
|
||||
|
||||
void expectSendAbortMessage() throws Exception {
|
||||
expectGetLocalTimestamp(messageTimestamp);
|
||||
expectGetTimestampForInvisibleMessage(messageTimestamp);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageEncoder)
|
||||
.encodeAbortMessage(contactGroupId, privateGroupId,
|
||||
@@ -226,8 +243,7 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
}});
|
||||
}
|
||||
|
||||
void expectCheckWhetherContactSupportsAutoDeletion(boolean visible)
|
||||
throws Exception {
|
||||
void expectCheckWhetherContactSupportsAutoDeletion() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getContactId(txn, contactGroupId);
|
||||
will(returnValue(contactId));
|
||||
@@ -235,10 +251,13 @@ abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
|
||||
GroupInvitationManager.CLIENT_ID,
|
||||
GroupInvitationManager.MAJOR_VERSION);
|
||||
will(returnValue(GroupInvitationManager.MINOR_VERSION));
|
||||
if (visible) {
|
||||
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId);
|
||||
will(returnValue(NO_AUTO_DELETE_TIMER));
|
||||
}
|
||||
}});
|
||||
}
|
||||
|
||||
void expectGetAutoDeleteTimer() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(autoDeleteManager).getAutoDeleteTimer(txn, contactId);
|
||||
will(returnValue(NO_AUTO_DELETE_TIMER));
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
new CreatorProtocolEngine(db, clientHelper, clientVersioningManager,
|
||||
privateGroupManager, privateGroupFactory,
|
||||
groupMessageFactory, identityManager, messageParser,
|
||||
messageEncoder, messageTracker, autoDeleteManager, clock);
|
||||
messageEncoder, messageTracker, autoDeleteManager,
|
||||
conversationManager, clock);
|
||||
|
||||
private CreatorSession getDefaultSession(CreatorState state) {
|
||||
return new CreatorSession(contactGroupId, privateGroupId,
|
||||
@@ -43,7 +44,7 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
expectOnLocalInvite(text);
|
||||
CreatorSession newSession =
|
||||
engine.onInviteAction(txn, session, text, inviteTimestamp,
|
||||
signature);
|
||||
signature, NO_AUTO_DELETE_TIMER);
|
||||
assertEquals(INVITED, newSession.getState());
|
||||
assertEquals(messageId, newSession.getLastLocalMessageId());
|
||||
assertNull(newSession.getLastRemoteMessageId());
|
||||
@@ -60,7 +61,7 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
expectOnLocalInvite(null);
|
||||
CreatorSession newSession =
|
||||
engine.onInviteAction(txn, session, null, inviteTimestamp,
|
||||
signature);
|
||||
signature, NO_AUTO_DELETE_TIMER);
|
||||
assertEquals(INVITED, newSession.getState());
|
||||
assertEquals(messageId, newSession.getLastLocalMessageId());
|
||||
assertNull(newSession.getLastRemoteMessageId());
|
||||
@@ -83,31 +84,31 @@ public class CreatorProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
@Test(expected = ProtocolStateException.class)
|
||||
public void testOnInviteActionFromInvited() throws Exception {
|
||||
engine.onInviteAction(txn, getDefaultSession(INVITED), null,
|
||||
inviteTimestamp, signature);
|
||||
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = ProtocolStateException.class)
|
||||
public void testOnInviteActionFromJoined() throws Exception {
|
||||
engine.onInviteAction(txn, getDefaultSession(JOINED), null,
|
||||
inviteTimestamp, signature);
|
||||
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = ProtocolStateException.class)
|
||||
public void testOnInviteActionFromLeft() throws Exception {
|
||||
engine.onInviteAction(txn, getDefaultSession(LEFT), null,
|
||||
inviteTimestamp, signature);
|
||||
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = ProtocolStateException.class)
|
||||
public void testOnInviteActionFromDissolved() throws Exception {
|
||||
engine.onInviteAction(txn, getDefaultSession(DISSOLVED), null,
|
||||
inviteTimestamp, signature);
|
||||
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = ProtocolStateException.class)
|
||||
public void testOnInviteActionFromError() throws Exception {
|
||||
engine.onInviteAction(txn, getDefaultSession(ERROR), null,
|
||||
inviteTimestamp, signature);
|
||||
inviteTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
// onJoinAction
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -687,7 +688,8 @@ public class GroupInvitationIntegrationTest
|
||||
byte[] signature = groupInvitationFactory.signInvitation(contact1From0,
|
||||
privateGroup.getId(), timestamp, author0.getPrivateKey());
|
||||
groupInvitationManager0.sendInvitation(privateGroup.getId(),
|
||||
contactId1From0, text, timestamp, signature);
|
||||
contactId1From0, text, timestamp, signature,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(creatorEngine).onInviteAction(with(txn),
|
||||
with(any(CreatorSession.class)), with(text), with(time),
|
||||
with(signature));
|
||||
with(signature), with(NO_AUTO_DELETE_TIMER));
|
||||
will(returnValue(creatorSession));
|
||||
}});
|
||||
expectStoreSession(creatorSession, storageMessage.getId());
|
||||
@@ -491,7 +491,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
groupInvitationManager.sendInvitation(privateGroup.getId(), contactId,
|
||||
text, time, signature);
|
||||
text, time, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -514,7 +514,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(creatorSession));
|
||||
oneOf(creatorEngine).onInviteAction(with(txn),
|
||||
with(any(CreatorSession.class)), with(text), with(time),
|
||||
with(signature));
|
||||
with(signature), with(NO_AUTO_DELETE_TIMER));
|
||||
will(returnValue(creatorSession));
|
||||
}});
|
||||
expectStoreSession(creatorSession, storageMessage.getId());
|
||||
@@ -523,7 +523,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
groupInvitationManager.sendInvitation(privateGroup.getId(), contactId,
|
||||
text, time, signature);
|
||||
text, time, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
|
||||
@@ -43,7 +43,8 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
new InviteeProtocolEngine(db, clientHelper, clientVersioningManager,
|
||||
privateGroupManager, privateGroupFactory,
|
||||
groupMessageFactory, identityManager, messageParser,
|
||||
messageEncoder, messageTracker, autoDeleteManager, clock);
|
||||
messageEncoder, messageTracker, autoDeleteManager,
|
||||
conversationManager, clock);
|
||||
private final LocalAuthor localAuthor = getLocalAuthor();
|
||||
|
||||
private InviteeSession getDefaultSession(InviteeState state) {
|
||||
@@ -57,43 +58,43 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromStart() {
|
||||
engine.onInviteAction(txn, getDefaultSession(START), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromLeft() {
|
||||
engine.onInviteAction(txn, getDefaultSession(ACCEPTED), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromInvited() {
|
||||
engine.onInviteAction(txn, getDefaultSession(INVITED), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromDissolved() {
|
||||
engine.onInviteAction(txn, getDefaultSession(DISSOLVED), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromAccepted() {
|
||||
engine.onInviteAction(txn, getDefaultSession(ACCEPTED), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromJoined() {
|
||||
engine.onInviteAction(txn, getDefaultSession(JOINED), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromError() {
|
||||
engine.onInviteAction(txn, getDefaultSession(ERROR), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
// onJoinAction
|
||||
|
||||
@@ -27,7 +27,8 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
new PeerProtocolEngine(db, clientHelper, clientVersioningManager,
|
||||
privateGroupManager, privateGroupFactory,
|
||||
groupMessageFactory, identityManager, messageParser,
|
||||
messageEncoder, messageTracker, autoDeleteManager, clock);
|
||||
messageEncoder, messageTracker, autoDeleteManager,
|
||||
conversationManager, clock);
|
||||
|
||||
private PeerSession getDefaultSession(PeerState state) {
|
||||
return new PeerSession(contactGroupId, privateGroupId,
|
||||
@@ -39,43 +40,43 @@ public class PeerProtocolEngineTest extends AbstractProtocolEngineTest {
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromStart() {
|
||||
engine.onInviteAction(txn, getDefaultSession(START), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromAwaitMember() {
|
||||
engine.onInviteAction(txn, getDefaultSession(AWAIT_MEMBER), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromNeitherJoined() {
|
||||
engine.onInviteAction(txn, getDefaultSession(NEITHER_JOINED), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromLocalJoined() {
|
||||
engine.onInviteAction(txn, getDefaultSession(LOCAL_JOINED), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromBothJoined() {
|
||||
engine.onInviteAction(txn, getDefaultSession(BOTH_JOINED), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromLocalLeft() {
|
||||
engine.onInviteAction(txn, getDefaultSession(LOCAL_LEFT), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testOnInviteActionFromError() {
|
||||
engine.onInviteAction(txn, getDefaultSession(ERROR), null,
|
||||
messageTimestamp, signature);
|
||||
messageTimestamp, signature, NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
|
||||
// onJoinAction
|
||||
|
||||
@@ -122,8 +122,7 @@ public class BlogSharingIntegrationTest
|
||||
|
||||
// send invitation
|
||||
blogSharingManager0
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// invitee has own blog and that of the sharer
|
||||
assertEquals(2, blogManager1.getBlogs().size());
|
||||
@@ -213,8 +212,8 @@ public class BlogSharingIntegrationTest
|
||||
blogManager0.addBlog(rssBlog);
|
||||
|
||||
// send invitation
|
||||
blogSharingManager0.sendInvitation(rssBlog.getId(), contactId1From0,
|
||||
"Hi!", clock.currentTimeMillis());
|
||||
blogSharingManager0
|
||||
.sendInvitation(rssBlog.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// invitee has own blog and that of the sharer
|
||||
assertEquals(2, blogManager1.getBlogs().size());
|
||||
@@ -285,8 +284,7 @@ public class BlogSharingIntegrationTest
|
||||
|
||||
// send invitation
|
||||
blogSharingManager0
|
||||
.sendInvitation(blog2.getId(), contactId1From0, null,
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(blog2.getId(), contactId1From0, null);
|
||||
|
||||
// sync first request message
|
||||
sync0To1(1, true);
|
||||
@@ -341,8 +339,7 @@ public class BlogSharingIntegrationTest
|
||||
|
||||
// send invitation
|
||||
blogSharingManager0
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync first request message
|
||||
sync0To1(1, true);
|
||||
@@ -398,8 +395,7 @@ public class BlogSharingIntegrationTest
|
||||
|
||||
// sharer sends invitation for 2's blog to 1
|
||||
blogSharingManager0
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync first request message
|
||||
sync0To1(1, true);
|
||||
@@ -436,8 +432,7 @@ public class BlogSharingIntegrationTest
|
||||
|
||||
// send invitation
|
||||
blogSharingManager0
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync first request message
|
||||
sync0To1(1, true);
|
||||
@@ -515,8 +510,7 @@ public class BlogSharingIntegrationTest
|
||||
|
||||
// sharer sends invitation for 2's blog to 1
|
||||
blogSharingManager0
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync first request message
|
||||
sync0To1(1, true);
|
||||
|
||||
@@ -126,8 +126,7 @@ public class ForumSharingIntegrationTest
|
||||
public void testSuccessfulSharing() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// check that request message state is correct
|
||||
Collection<ConversationMessageHeader> messages = getMessages1From0();
|
||||
@@ -191,8 +190,8 @@ public class ForumSharingIntegrationTest
|
||||
@Test
|
||||
public void testDeclinedSharing() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -243,8 +242,8 @@ public class ForumSharingIntegrationTest
|
||||
|
||||
// send a new invitation again after re-adding the forum
|
||||
db0.transaction(false, txn -> forumManager0.addForum(txn, forum));
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
|
||||
// reset listener state for new request
|
||||
listener1.requestReceived = false;
|
||||
@@ -259,8 +258,8 @@ public class ForumSharingIntegrationTest
|
||||
@Test
|
||||
public void testInviteeLeavesAfterFinished() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
"Hi!", clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -322,8 +321,8 @@ public class ForumSharingIntegrationTest
|
||||
@Test
|
||||
public void testSharerLeavesAfterFinished() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -383,8 +382,8 @@ public class ForumSharingIntegrationTest
|
||||
|
||||
// send a new invitation again after re-adding the forum
|
||||
db0.transaction(false, txn -> forumManager0.addForum(txn, forum));
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
|
||||
// reset listener state for new request
|
||||
listener1.requestReceived = false;
|
||||
@@ -399,8 +398,8 @@ public class ForumSharingIntegrationTest
|
||||
@Test
|
||||
public void testSharerLeavesBeforeResponse() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
|
||||
// sharer un-subscribes from forum
|
||||
forumManager0.removeForum(forum);
|
||||
@@ -420,8 +419,7 @@ public class ForumSharingIntegrationTest
|
||||
|
||||
// send invitation
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null,
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -445,8 +443,8 @@ public class ForumSharingIntegrationTest
|
||||
@Test
|
||||
public void testSharingSameForumWithEachOther() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
"Hi!", clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -471,10 +469,9 @@ public class ForumSharingIntegrationTest
|
||||
assertEquals(1, forumManager1.getForums().size());
|
||||
|
||||
// invitee now shares same forum back
|
||||
forumSharingManager1.sendInvitation(forum.getId(),
|
||||
contactId0From1,
|
||||
"I am re-sharing this forum with you.",
|
||||
clock.currentTimeMillis());
|
||||
forumSharingManager1
|
||||
.sendInvitation(forum.getId(), contactId0From1,
|
||||
"I am re-sharing this forum with you.");
|
||||
|
||||
// assert that the last invitation wasn't send
|
||||
assertEquals(2, c1.getMessageTracker().getGroupCount(group.getId())
|
||||
@@ -485,8 +482,8 @@ public class ForumSharingIntegrationTest
|
||||
public void testSharingSameForumWithEachOtherBeforeAccept()
|
||||
throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
"Hi!", clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
sync0To1(1, true);
|
||||
eventWaiter.await(TIMEOUT, 1);
|
||||
assertRequestReceived(listener1, contactId0From1);
|
||||
@@ -501,10 +498,9 @@ public class ForumSharingIntegrationTest
|
||||
.getMsgCount());
|
||||
|
||||
// invitee now shares same forum back
|
||||
forumSharingManager1.sendInvitation(forum.getId(),
|
||||
contactId0From1,
|
||||
"I am re-sharing this forum with you.",
|
||||
clock.currentTimeMillis());
|
||||
forumSharingManager1
|
||||
.sendInvitation(forum.getId(), contactId0From1,
|
||||
"I am re-sharing this forum with you.");
|
||||
|
||||
// assert that the last invitation wasn't send
|
||||
assertEquals(1, c1.getMessageTracker().getGroupCount(group.getId())
|
||||
@@ -518,13 +514,12 @@ public class ForumSharingIntegrationTest
|
||||
|
||||
// send invitation
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// invitee now shares same forum back
|
||||
forumSharingManager1.sendInvitation(forum.getId(),
|
||||
contactId0From1, "I am re-sharing this forum with you.",
|
||||
clock.currentTimeMillis());
|
||||
forumSharingManager1
|
||||
.sendInvitation(forum.getId(), contactId0From1,
|
||||
"I am re-sharing this forum with you.");
|
||||
|
||||
// only now sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -554,8 +549,8 @@ public class ForumSharingIntegrationTest
|
||||
@Test
|
||||
public void testContactRemoved() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
"Hi!", clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -597,8 +592,7 @@ public class ForumSharingIntegrationTest
|
||||
|
||||
// send invitation
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -626,8 +620,7 @@ public class ForumSharingIntegrationTest
|
||||
|
||||
// send invitation
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -637,8 +630,7 @@ public class ForumSharingIntegrationTest
|
||||
// second sharer sends invitation for same forum
|
||||
assertNotNull(contactId1From2);
|
||||
forumSharingManager2
|
||||
.sendInvitation(forum.getId(), contactId1From2, null,
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(forum.getId(), contactId1From2, null);
|
||||
|
||||
// sync second request message
|
||||
sync2To1(1, true);
|
||||
@@ -680,8 +672,8 @@ public class ForumSharingIntegrationTest
|
||||
@Test
|
||||
public void testSyncAfterReSharing() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
"Hi!", clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -745,8 +737,7 @@ public class ForumSharingIntegrationTest
|
||||
|
||||
// send invitation again
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!",
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -787,8 +778,8 @@ public class ForumSharingIntegrationTest
|
||||
@Test
|
||||
public void testSessionResetAfterAbort() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
"Hi!", clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, "Hi!");
|
||||
|
||||
// sync request message
|
||||
sync0To1(1, true);
|
||||
@@ -836,8 +827,7 @@ public class ForumSharingIntegrationTest
|
||||
|
||||
// new invitation is possible now
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null,
|
||||
clock.currentTimeMillis());
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
sync0To1(1, true);
|
||||
eventWaiter.await(TIMEOUT, 1);
|
||||
assertRequestReceived(listener1, contactId0From1);
|
||||
@@ -859,8 +849,8 @@ public class ForumSharingIntegrationTest
|
||||
public void testDeletingAllMessagesWhenCompletingSession()
|
||||
throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
sync0To1(1, true);
|
||||
eventWaiter.await(TIMEOUT, 1);
|
||||
|
||||
@@ -909,8 +899,8 @@ public class ForumSharingIntegrationTest
|
||||
sync1To0(1, true);
|
||||
|
||||
// sending invitation is possible again
|
||||
forumSharingManager1.sendInvitation(forum.getId(), contactId0From1,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager1
|
||||
.sendInvitation(forum.getId(), contactId0From1, null);
|
||||
sync1To0(1, true);
|
||||
eventWaiter.await(TIMEOUT, 1);
|
||||
|
||||
@@ -944,8 +934,8 @@ public class ForumSharingIntegrationTest
|
||||
public void testDeletingAllMessagesAfterDecline()
|
||||
throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
sync0To1(1, true);
|
||||
eventWaiter.await(TIMEOUT, 1);
|
||||
|
||||
@@ -969,8 +959,8 @@ public class ForumSharingIntegrationTest
|
||||
assertEquals(0, getMessages0From1().size());
|
||||
|
||||
// re-sending invitation is possible
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
sync0To1(1, true);
|
||||
eventWaiter.await(TIMEOUT, 1);
|
||||
|
||||
@@ -984,8 +974,8 @@ public class ForumSharingIntegrationTest
|
||||
@Test
|
||||
public void testDeletingSomeMessages() throws Exception {
|
||||
// send invitation
|
||||
forumSharingManager0.sendInvitation(forum.getId(), contactId1From0,
|
||||
null, clock.currentTimeMillis());
|
||||
forumSharingManager0
|
||||
.sendInvitation(forum.getId(), contactId1From0, null);
|
||||
sync0To1(1, true);
|
||||
eventWaiter.await(TIMEOUT, 1);
|
||||
|
||||
@@ -996,7 +986,8 @@ public class ForumSharingIntegrationTest
|
||||
Set<MessageId> toDelete = new HashSet<>();
|
||||
toDelete.add(messageId);
|
||||
assertFalse(deleteMessages1From0(toDelete).allDeleted());
|
||||
assertTrue(deleteMessages1From0(toDelete).hasInvitationSessionInProgress());
|
||||
assertTrue(deleteMessages1From0(toDelete)
|
||||
.hasInvitationSessionInProgress());
|
||||
|
||||
// decline invitation
|
||||
respondToRequest(contactId0From1, true);
|
||||
@@ -1006,9 +997,11 @@ public class ForumSharingIntegrationTest
|
||||
// both can still not delete the invitation,
|
||||
// because the response was not selected for deletion as well
|
||||
assertFalse(deleteMessages1From0(toDelete).allDeleted());
|
||||
assertTrue(deleteMessages1From0(toDelete).hasNotAllInvitationSelected());
|
||||
assertTrue(
|
||||
deleteMessages1From0(toDelete).hasNotAllInvitationSelected());
|
||||
assertFalse(deleteMessages0From1(toDelete).allDeleted());
|
||||
assertTrue(deleteMessages0From1(toDelete).hasNotAllInvitationSelected());
|
||||
assertTrue(
|
||||
deleteMessages0From1(toDelete).hasNotAllInvitationSelected());
|
||||
|
||||
// after selecting response, both messages can be deleted
|
||||
m0 = getMessages1From0();
|
||||
@@ -1023,8 +1016,10 @@ public class ForumSharingIntegrationTest
|
||||
|
||||
// 1 can still not delete the messages, as last one has not been ACKed
|
||||
assertFalse(deleteMessages0From1(toDelete).allDeleted());
|
||||
assertFalse(deleteMessages0From1(toDelete).hasNotAllInvitationSelected());
|
||||
assertTrue(deleteMessages0From1(toDelete).hasInvitationSessionInProgress());
|
||||
assertFalse(
|
||||
deleteMessages0From1(toDelete).hasNotAllInvitationSelected());
|
||||
assertTrue(deleteMessages0From1(toDelete)
|
||||
.hasInvitationSessionInProgress());
|
||||
|
||||
// 0 sends an ACK to their last message
|
||||
sendAcks(c0, c1, contactId1From0, 1);
|
||||
|
||||
Reference in New Issue
Block a user