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