mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 12:19:54 +01:00
Move lookup of latest conversation timestamp to core.
This commit is contained in:
@@ -736,18 +736,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));
|
||||||
@@ -955,13 +947,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);
|
||||||
@@ -1037,9 +1027,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
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
|||||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||||
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
|
||||||
import org.briarproject.briar.api.avatar.event.AvatarUpdatedEvent;
|
import org.briarproject.briar.api.avatar.event.AvatarUpdatedEvent;
|
||||||
|
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||||
import org.briarproject.briar.api.identity.AuthorManager;
|
import org.briarproject.briar.api.identity.AuthorManager;
|
||||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||||
@@ -90,6 +91,7 @@ public class ConversationViewModel extends DbViewModel
|
|||||||
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;
|
||||||
@@ -125,7 +127,8 @@ public class ConversationViewModel extends DbViewModel
|
|||||||
PrivateMessageFactory privateMessageFactory,
|
PrivateMessageFactory privateMessageFactory,
|
||||||
AttachmentRetriever attachmentRetriever,
|
AttachmentRetriever attachmentRetriever,
|
||||||
AttachmentCreator attachmentCreator,
|
AttachmentCreator attachmentCreator,
|
||||||
AutoDeleteManager autoDeleteManager) {
|
AutoDeleteManager autoDeleteManager,
|
||||||
|
ConversationManager conversationManager) {
|
||||||
super(application, dbExecutor, lifecycleManager, db, androidExecutor);
|
super(application, dbExecutor, lifecycleManager, db, androidExecutor);
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
@@ -137,6 +140,7 @@ public class ConversationViewModel extends DbViewModel
|
|||||||
this.attachmentRetriever = attachmentRetriever;
|
this.attachmentRetriever = attachmentRetriever;
|
||||||
this.attachmentCreator = attachmentCreator;
|
this.attachmentCreator = attachmentCreator;
|
||||||
this.autoDeleteManager = autoDeleteManager;
|
this.autoDeleteManager = autoDeleteManager;
|
||||||
|
this.conversationManager = conversationManager;
|
||||||
messagingGroupId = map(contactItem, c ->
|
messagingGroupId = map(contactItem, c ->
|
||||||
messagingManager.getContactGroup(c.getContact()).getId());
|
messagingManager.getContactGroup(c.getContact()).getId());
|
||||||
contactDeleted.setValue(false);
|
contactDeleted.setValue(false);
|
||||||
@@ -244,14 +248,13 @@ public class ConversationViewModel extends DbViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
@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));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,8 +316,10 @@ public class ConversationViewModel extends DbViewModel
|
|||||||
|
|
||||||
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(
|
||||||
@@ -335,13 +340,13 @@ public class ConversationViewModel extends DbViewModel
|
|||||||
@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) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
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();
|
||||||
|
|||||||
@@ -219,8 +219,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();
|
||||||
|
|||||||
@@ -48,6 +48,13 @@ public interface ConversationManager {
|
|||||||
*/
|
*/
|
||||||
GroupCount getGroupCount(Transaction txn, ContactId c) throws DbException;
|
GroupCount getGroupCount(Transaction txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a timestamp for an outgoing message, which is later than the
|
||||||
|
* timestamp of any visible message sent or received so far.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ import org.briarproject.bramble.api.properties.TransportProperties;
|
|||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
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.client.SessionId;
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
|
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||||
import org.briarproject.briar.api.identity.AuthorManager;
|
import org.briarproject.briar.api.identity.AuthorManager;
|
||||||
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||||
@@ -61,7 +61,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 Clock clock;
|
protected final ConversationManager conversationManager;
|
||||||
|
|
||||||
AbstractProtocolEngine(
|
AbstractProtocolEngine(
|
||||||
DatabaseComponent db,
|
DatabaseComponent db,
|
||||||
@@ -75,7 +75,7 @@ abstract class AbstractProtocolEngine<S extends Session<?>>
|
|||||||
MessageEncoder messageEncoder,
|
MessageEncoder messageEncoder,
|
||||||
ClientVersioningManager clientVersioningManager,
|
ClientVersioningManager clientVersioningManager,
|
||||||
AutoDeleteManager autoDeleteManager,
|
AutoDeleteManager autoDeleteManager,
|
||||||
Clock clock) {
|
ConversationManager conversationManager) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.clientHelper = clientHelper;
|
this.clientHelper = clientHelper;
|
||||||
this.contactManager = contactManager;
|
this.contactManager = contactManager;
|
||||||
@@ -87,7 +87,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.clock = clock;
|
this.conversationManager = conversationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message sendRequestMessage(Transaction txn, PeerSession s,
|
Message sendRequestMessage(Transaction txn, PeerSession s,
|
||||||
@@ -231,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)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import org.briarproject.bramble.api.properties.TransportProperties;
|
|||||||
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
|
||||||
import org.briarproject.bramble.api.transport.KeyManager;
|
import org.briarproject.bramble.api.transport.KeyManager;
|
||||||
import org.briarproject.bramble.api.transport.KeySetId;
|
import org.briarproject.bramble.api.transport.KeySetId;
|
||||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||||
@@ -30,6 +29,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.identity.AuthorInfo;
|
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||||
import org.briarproject.briar.api.identity.AuthorManager;
|
import org.briarproject.briar.api.identity.AuthorManager;
|
||||||
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
||||||
@@ -44,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;
|
||||||
@@ -77,16 +78,16 @@ class IntroduceeProtocolEngine
|
|||||||
AuthorManager authorManager,
|
AuthorManager authorManager,
|
||||||
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) {
|
||||||
super(db, clientHelper, contactManager, contactGroupFactory,
|
super(db, clientHelper, contactManager, contactGroupFactory,
|
||||||
messageTracker, identityManager, authorManager, messageParser,
|
messageTracker, identityManager, authorManager, messageParser,
|
||||||
messageEncoder, clientVersioningManager, autoDeleteManager,
|
messageEncoder, clientVersioningManager, autoDeleteManager,
|
||||||
clock);
|
conversationManager);
|
||||||
this.crypto = crypto;
|
this.crypto = crypto;
|
||||||
this.keyManager = keyManager;
|
this.keyManager = keyManager;
|
||||||
this.transportPropertyManager = transportPropertyManager;
|
this.transportPropertyManager = transportPropertyManager;
|
||||||
@@ -94,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:
|
||||||
@@ -119,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:
|
||||||
@@ -275,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);
|
||||||
|
|
||||||
@@ -287,7 +288,7 @@ class IntroduceeProtocolEngine
|
|||||||
transportPropertyManager.getLocalProperties(txn);
|
transportPropertyManager.getLocalProperties(txn);
|
||||||
|
|
||||||
// Send a ACCEPT message
|
// Send a ACCEPT message
|
||||||
long localTimestamp = Math.max(timestamp + 1, getLocalTimestamp(s));
|
long localTimestamp = getLocalTimestamp(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
|
||||||
@@ -312,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 = getLocalTimestamp(txn, s);
|
||||||
Message sent = sendDeclineMessage(txn, s, localTimestamp, true);
|
Message sent = sendDeclineMessage(txn, s, localTimestamp, true);
|
||||||
|
|
||||||
// Track the message
|
// Track the message
|
||||||
@@ -415,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 = getLocalTimestamp(txn, 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);
|
||||||
}
|
}
|
||||||
@@ -465,7 +466,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 = getLocalTimestamp(txn, 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);
|
||||||
@@ -516,7 +518,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 = getLocalTimestamp(txn, 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()));
|
||||||
@@ -531,9 +534,18 @@ 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 an outgoing message, which is later than the
|
||||||
s.getRequestTimestamp());
|
* timestamp of any message sent or received so far in the conversation
|
||||||
|
* or the session.
|
||||||
|
*/
|
||||||
|
private long getLocalTimestamp(Transaction txn, IntroduceeSession s)
|
||||||
|
throws DbException {
|
||||||
|
long conversationTimestamp =
|
||||||
|
getTimestampForOutgoingMessage(txn, s.getContactGroupId());
|
||||||
|
long sessionTimestamp =
|
||||||
|
max(s.getLocalTimestamp(), s.getRequestTimestamp()) + 1;
|
||||||
|
return max(conversationTimestamp, sessionTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSessionId(Transaction txn, MessageId m, SessionId sessionId)
|
private void addSessionId(Transaction txn, MessageId m, SessionId sessionId)
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ 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.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
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.client.ProtocolStateException;
|
import org.briarproject.briar.api.client.ProtocolStateException;
|
||||||
|
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||||
import org.briarproject.briar.api.identity.AuthorManager;
|
import org.briarproject.briar.api.identity.AuthorManager;
|
||||||
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;
|
||||||
@@ -25,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;
|
||||||
@@ -56,20 +57,20 @@ class IntroducerProtocolEngine
|
|||||||
MessageEncoder messageEncoder,
|
MessageEncoder messageEncoder,
|
||||||
ClientVersioningManager clientVersioningManager,
|
ClientVersioningManager clientVersioningManager,
|
||||||
AutoDeleteManager autoDeleteManager,
|
AutoDeleteManager autoDeleteManager,
|
||||||
Clock clock) {
|
ConversationManager conversationManager) {
|
||||||
super(db, clientHelper, contactManager, contactGroupFactory,
|
super(db, clientHelper, contactManager, contactGroupFactory,
|
||||||
messageTracker, identityManager, authorManager, messageParser,
|
messageTracker, identityManager, authorManager, messageParser,
|
||||||
messageEncoder, clientVersioningManager, autoDeleteManager,
|
messageEncoder, clientVersioningManager, autoDeleteManager,
|
||||||
clock);
|
conversationManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@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:
|
||||||
@@ -89,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
|
||||||
@@ -229,13 +217,11 @@ 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 = getLocalTimestamp(txn, s, s.getIntroduceeA());
|
||||||
Math.max(getLocalTimestamp(s, s.getIntroduceeA()),
|
long timestampB = getLocalTimestamp(txn, s, s.getIntroduceeB());
|
||||||
getLocalTimestamp(s, s.getIntroduceeB()));
|
long localTimestamp = max(timestampA, timestampB);
|
||||||
long localTimestamp = Math.max(timestamp, maxIntroduceeTimestamp);
|
|
||||||
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(),
|
||||||
@@ -275,11 +261,10 @@ 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);
|
long localTimestamp = getLocalTimestamp(txn, s, i);
|
||||||
Message sent =
|
Message sent = sendAcceptMessage(txn, i, localTimestamp,
|
||||||
sendAcceptMessage(txn, i, timestamp, m.getEphemeralPublicKey(),
|
m.getEphemeralPublicKey(), m.getAcceptTimestamp(),
|
||||||
m.getAcceptTimestamp(), m.getTransportProperties(),
|
m.getTransportProperties(), false);
|
||||||
false);
|
|
||||||
|
|
||||||
// Create the next state
|
// Create the next state
|
||||||
IntroducerState state = AWAIT_AUTHS;
|
IntroducerState state = AWAIT_AUTHS;
|
||||||
@@ -336,7 +321,8 @@ 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),
|
long localTimestamp = getLocalTimestamp(txn, s, i);
|
||||||
|
Message sent = sendAcceptMessage(txn, i, localTimestamp,
|
||||||
m.getEphemeralPublicKey(), m.getAcceptTimestamp(),
|
m.getEphemeralPublicKey(), m.getAcceptTimestamp(),
|
||||||
m.getTransportProperties(), false);
|
m.getTransportProperties(), false);
|
||||||
|
|
||||||
@@ -387,8 +373,8 @@ 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);
|
long localTimestamp = getLocalTimestamp(txn, s, i);
|
||||||
Message sent = sendDeclineMessage(txn, i, timestamp, false);
|
Message sent = sendDeclineMessage(txn, i, localTimestamp, false);
|
||||||
|
|
||||||
// Create the next state
|
// Create the next state
|
||||||
IntroducerState state = START;
|
IntroducerState state = START;
|
||||||
@@ -439,8 +425,8 @@ 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);
|
long localTimestamp = getLocalTimestamp(txn, s, i);
|
||||||
Message sent = sendDeclineMessage(txn, i, timestamp, false);
|
Message sent = sendDeclineMessage(txn, i, localTimestamp, false);
|
||||||
|
|
||||||
Introducee introduceeA, introduceeB;
|
Introducee introduceeA, introduceeB;
|
||||||
Author sender, other;
|
Author sender, other;
|
||||||
@@ -480,8 +466,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 = getLocalTimestamp(txn, 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
|
||||||
@@ -516,8 +502,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 = getLocalTimestamp(txn, 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;
|
||||||
@@ -539,8 +525,9 @@ 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 = max(i.getLocalTimestamp(),
|
||||||
Message sent = sendAbortMessage(txn, i, timestamp);
|
s.getRequestTimestamp()) + 1;
|
||||||
|
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()));
|
||||||
@@ -558,15 +545,42 @@ 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 = getLocalTimestamp(txn, 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 = getLocalTimestamp(txn, 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 = getLocalTimestamp(txn, 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);
|
||||||
@@ -596,9 +610,17 @@ 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 an outgoing message, which is later than the
|
||||||
s.getRequestTimestamp());
|
* timestamp of any message sent or received so far in the conversation
|
||||||
|
* or the session.
|
||||||
|
*/
|
||||||
|
private long getLocalTimestamp(Transaction txn, IntroducerSession s,
|
||||||
|
PeerSession p) throws DbException {
|
||||||
|
long conversationTimestamp =
|
||||||
|
getTimestampForOutgoingMessage(txn, p.getContactGroupId());
|
||||||
|
long sessionTimestamp =
|
||||||
|
max(p.getLocalTimestamp(), s.getRequestTimestamp()) + 1;
|
||||||
|
return max(conversationTimestamp, sessionTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,8 +315,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
|
||||||
@@ -348,8 +348,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);
|
||||||
@@ -362,7 +361,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
|
||||||
@@ -380,11 +379,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<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +81,14 @@ class ConversationManagerImpl implements ConversationManager {
|
|||||||
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 -> {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user