mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 13:49:53 +01:00
Sent automatic decline when other introducee declines.
This commit is contained in:
@@ -575,6 +575,10 @@ public class ConversationActivity extends BriarActivity
|
|||||||
@Override
|
@Override
|
||||||
public void onSuccess(String contactName) {
|
public void onSuccess(String contactName) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
|
// If the other introducee declined, we can no longer
|
||||||
|
// respond to the request
|
||||||
|
if (!m.isIntroducer() && !m.wasAccepted())
|
||||||
|
markRequestAnswered(m.getSessionId());
|
||||||
ConversationItem item = ConversationItem
|
ConversationItem item = ConversationItem
|
||||||
.from(ConversationActivity.this, contactName, m);
|
.from(ConversationActivity.this, contactName, m);
|
||||||
addConversationItem(item);
|
addConversationItem(item);
|
||||||
@@ -627,6 +631,26 @@ public class ConversationActivity extends BriarActivity
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void markRequestAnswered(SessionId sessionId) {
|
||||||
|
int size = adapter.getItemCount();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
ConversationItem item = adapter.getItemAt(i);
|
||||||
|
if (item instanceof ConversationRequestItem) {
|
||||||
|
ConversationRequestItem req = (ConversationRequestItem) item;
|
||||||
|
if (req.getSessionId().equals(sessionId)
|
||||||
|
&& !req.wasAnswered()) {
|
||||||
|
LOG.info("Marking request answered");
|
||||||
|
req.setAnswered(true);
|
||||||
|
int position = adapter.findItemPosition(req);
|
||||||
|
if (position != INVALID_POSITION)
|
||||||
|
adapter.notifyItemChanged(position, req);
|
||||||
|
// There shouldn't be more than one unanswered request
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void markMessages(Collection<MessageId> messageIds,
|
private void markMessages(Collection<MessageId> messageIds,
|
||||||
boolean sent, boolean seen) {
|
boolean sent, boolean seen) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
@@ -781,25 +805,18 @@ public class ConversationActivity extends BriarActivity
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PromptStateChangeListener listener = new PromptStateChangeListener() {
|
PromptStateChangeListener listener = (prompt, state) -> {
|
||||||
@Override
|
if (state == STATE_DISMISSED || state == STATE_FINISHED) {
|
||||||
public void onPromptStateChanged(
|
introductionOnboardingSeen();
|
||||||
MaterialTapTargetPrompt prompt, int state) {
|
}
|
||||||
if (state == STATE_DISMISSED ||
|
};
|
||||||
state == STATE_FINISHED) {
|
new MaterialTapTargetPrompt.Builder(ConversationActivity.this,
|
||||||
introductionOnboardingSeen();
|
R.style.OnboardingDialogTheme).setTarget(target)
|
||||||
}
|
.setPrimaryText(R.string.introduction_onboarding_title)
|
||||||
}
|
.setSecondaryText(R.string.introduction_onboarding_text)
|
||||||
|
.setIcon(R.drawable.ic_more_vert_accent)
|
||||||
};
|
.setPromptStateChangeListener(listener)
|
||||||
new MaterialTapTargetPrompt.Builder(ConversationActivity.this,
|
.show();
|
||||||
R.style.OnboardingDialogTheme).setTarget(target)
|
|
||||||
.setPrimaryText(R.string.introduction_onboarding_title)
|
|
||||||
.setSecondaryText(R.string.introduction_onboarding_text)
|
|
||||||
.setIcon(R.drawable.ic_more_vert_accent)
|
|
||||||
.setPromptStateChangeListener(listener)
|
|
||||||
.show();
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -865,11 +882,12 @@ introductionOnboardingSeen();
|
|||||||
"Unknown Request Type");
|
"Unknown Request Type");
|
||||||
}
|
}
|
||||||
loadMessages();
|
loadMessages();
|
||||||
|
} catch (ProtocolStateException e) {
|
||||||
|
// Action is no longer valid - reloading should solve the issue
|
||||||
|
if (LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
// TODO use more generic error message
|
// TODO show an error message
|
||||||
introductionResponseError();
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
if (LOG.isLoggable(WARNING))
|
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -900,14 +918,8 @@ introductionOnboardingSeen();
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void respondToIntroductionRequest(SessionId sessionId,
|
private void respondToIntroductionRequest(SessionId sessionId,
|
||||||
boolean accept, long time) throws DbException {
|
boolean accept, long time) throws DbException {
|
||||||
try {
|
introductionManager.respondToIntroduction(contactId, sessionId, time,
|
||||||
introductionManager
|
accept);
|
||||||
.respondToIntroduction(contactId, sessionId, time, accept);
|
|
||||||
} catch (ProtocolStateException e) {
|
|
||||||
if (LOG.isLoggable(WARNING))
|
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
introductionResponseError();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@@ -925,18 +937,7 @@ introductionOnboardingSeen();
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void respondToGroupRequest(SessionId id, boolean accept)
|
private void respondToGroupRequest(SessionId id, boolean accept)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
try {
|
groupInvitationManager.respondToInvitation(contactId, id, accept);
|
||||||
groupInvitationManager.respondToInvitation(contactId, id, accept);
|
|
||||||
} catch (ProtocolStateException e) {
|
|
||||||
// this action is no longer possible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void introductionResponseError() {
|
|
||||||
runOnUiThreadUnlessDestroyed(() ->
|
|
||||||
Toast.makeText(ConversationActivity.this,
|
|
||||||
R.string.introduction_response_error,
|
|
||||||
Toast.LENGTH_SHORT).show());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListenableFutureTask<String> getContactNameTask() {
|
private ListenableFutureTask<String> getContactNameTask() {
|
||||||
|
|||||||
@@ -84,8 +84,7 @@ abstract class AbstractProtocolEngine<S extends Session>
|
|||||||
Message sendAcceptMessage(Transaction txn, PeerSession s, long timestamp,
|
Message sendAcceptMessage(Transaction txn, PeerSession s, long timestamp,
|
||||||
byte[] ephemeralPublicKey, long acceptTimestamp,
|
byte[] ephemeralPublicKey, long acceptTimestamp,
|
||||||
Map<TransportId, TransportProperties> transportProperties,
|
Map<TransportId, TransportProperties> transportProperties,
|
||||||
boolean visible)
|
boolean visible) throws DbException {
|
||||||
throws DbException {
|
|
||||||
Message m = messageEncoder
|
Message m = messageEncoder
|
||||||
.encodeAcceptMessage(s.getContactGroupId(), timestamp,
|
.encodeAcceptMessage(s.getContactGroupId(), timestamp,
|
||||||
s.getLastLocalMessageId(), s.getSessionId(),
|
s.getLastLocalMessageId(), s.getSessionId(),
|
||||||
|
|||||||
@@ -357,9 +357,25 @@ class IntroduceeProtocolEngine
|
|||||||
broadcastIntroductionResponseReceivedEvent(txn, s,
|
broadcastIntroductionResponseReceivedEvent(txn, s,
|
||||||
s.getIntroducer().getId(), m);
|
s.getIntroducer().getId(), m);
|
||||||
|
|
||||||
// Move back to START state
|
if (s.getState() == AWAIT_RESPONSES) {
|
||||||
return IntroduceeSession.clear(s, START, s.getLastLocalMessageId(),
|
// Mark the request message unavailable to answer
|
||||||
s.getLocalTimestamp(), m.getMessageId());
|
markRequestsUnavailableToAnswer(txn, s);
|
||||||
|
|
||||||
|
// Send a DECLINE message
|
||||||
|
Message sent =
|
||||||
|
sendDeclineMessage(txn, s, getLocalTimestamp(s), false);
|
||||||
|
|
||||||
|
// Track the message
|
||||||
|
messageTracker.trackOutgoingMessage(txn, sent);
|
||||||
|
|
||||||
|
// Move back to START state
|
||||||
|
return IntroduceeSession.clear(s, START, sent.getId(),
|
||||||
|
sent.getTimestamp(), m.getMessageId());
|
||||||
|
} else {
|
||||||
|
// Move back to START state
|
||||||
|
return IntroduceeSession.clear(s, START, s.getLastLocalMessageId(),
|
||||||
|
s.getLocalTimestamp(), m.getMessageId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroduceeSession onRemoteResponseWhenDeclined(Transaction txn,
|
private IntroduceeSession onRemoteResponseWhenDeclined(Transaction txn,
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ class IntroducerProtocolEngine
|
|||||||
return onRemoteAccept(txn, s, m);
|
return onRemoteAccept(txn, s, m);
|
||||||
case A_DECLINED:
|
case A_DECLINED:
|
||||||
case B_DECLINED:
|
case B_DECLINED:
|
||||||
return onRemoteResponseWhenDeclined(txn, s, m);
|
return onRemoteAcceptWhenDeclined(txn, s, m);
|
||||||
case START:
|
case START:
|
||||||
case AWAIT_AUTHS:
|
case AWAIT_AUTHS:
|
||||||
case AWAIT_AUTH_A:
|
case AWAIT_AUTH_A:
|
||||||
@@ -137,7 +137,7 @@ class IntroducerProtocolEngine
|
|||||||
return onRemoteDecline(txn, s, m);
|
return onRemoteDecline(txn, s, m);
|
||||||
case A_DECLINED:
|
case A_DECLINED:
|
||||||
case B_DECLINED:
|
case B_DECLINED:
|
||||||
return onRemoteResponseWhenDeclined(txn, s, m);
|
return onRemoteDeclineWhenDeclined(txn, s, m);
|
||||||
case START:
|
case START:
|
||||||
case AWAIT_AUTHS:
|
case AWAIT_AUTHS:
|
||||||
case AWAIT_AUTH_A:
|
case AWAIT_AUTH_A:
|
||||||
@@ -204,8 +204,8 @@ class IntroducerProtocolEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession onLocalRequest(Transaction txn,
|
private IntroducerSession onLocalRequest(Transaction txn,
|
||||||
IntroducerSession s,
|
IntroducerSession s, @Nullable String message, long timestamp)
|
||||||
@Nullable String message, long timestamp) throws DbException {
|
throws DbException {
|
||||||
// Send REQUEST messages
|
// Send REQUEST messages
|
||||||
long maxIntroduceeTimestamp =
|
long maxIntroduceeTimestamp =
|
||||||
Math.max(getLocalTimestamp(s, s.getIntroduceeA()),
|
Math.max(getLocalTimestamp(s, s.getIntroduceeA()),
|
||||||
@@ -285,6 +285,50 @@ class IntroducerProtocolEngine
|
|||||||
return m.getGroupId().equals(s.getIntroduceeA().groupId);
|
return m.getGroupId().equals(s.getIntroduceeA().groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IntroducerSession onRemoteAcceptWhenDeclined(Transaction txn,
|
||||||
|
IntroducerSession s, AcceptMessage m) throws DbException {
|
||||||
|
// The timestamp must be higher than the last request message
|
||||||
|
if (m.getTimestamp() <= s.getRequestTimestamp())
|
||||||
|
return abort(txn, s);
|
||||||
|
// The dependency, if any, must be the last remote message
|
||||||
|
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
||||||
|
return abort(txn, s);
|
||||||
|
// The message must be expected in the current state
|
||||||
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
|
if (senderIsAlice && s.getState() != B_DECLINED)
|
||||||
|
return abort(txn, s);
|
||||||
|
else if (!senderIsAlice && s.getState() != A_DECLINED)
|
||||||
|
return abort(txn, s);
|
||||||
|
|
||||||
|
// Mark the response visible in the UI
|
||||||
|
markMessageVisibleInUi(txn, m.getMessageId());
|
||||||
|
// Track the incoming message
|
||||||
|
messageTracker
|
||||||
|
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
|
||||||
|
|
||||||
|
// Forward ACCEPT message
|
||||||
|
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||||
|
Message sent = sendAcceptMessage(txn, i, getLocalTimestamp(s, i),
|
||||||
|
m.getEphemeralPublicKey(), m.getAcceptTimestamp(),
|
||||||
|
m.getTransportProperties(), false);
|
||||||
|
|
||||||
|
Introducee introduceeA, introduceeB;
|
||||||
|
if (senderIsAlice) {
|
||||||
|
introduceeA = new Introducee(s.getIntroduceeA(), m.getMessageId());
|
||||||
|
introduceeB = new Introducee(s.getIntroduceeB(), sent);
|
||||||
|
} else {
|
||||||
|
introduceeA = new Introducee(s.getIntroduceeA(), sent);
|
||||||
|
introduceeB = new Introducee(s.getIntroduceeB(), m.getMessageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast IntroductionResponseReceivedEvent
|
||||||
|
Author sender = senderIsAlice ? introduceeA.author : introduceeB.author;
|
||||||
|
broadcastIntroductionResponseReceivedEvent(txn, s, sender.getId(), m);
|
||||||
|
|
||||||
|
return new IntroducerSession(s.getSessionId(), START,
|
||||||
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
|
}
|
||||||
|
|
||||||
private IntroducerSession onRemoteDecline(Transaction txn,
|
private IntroducerSession onRemoteDecline(Transaction txn,
|
||||||
IntroducerSession s, DeclineMessage m) throws DbException {
|
IntroducerSession s, DeclineMessage m) throws DbException {
|
||||||
// The timestamp must be higher than the last request message
|
// The timestamp must be higher than the last request message
|
||||||
@@ -334,9 +378,8 @@ class IntroducerProtocolEngine
|
|||||||
s.getRequestTimestamp(), introduceeA, introduceeB);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession onRemoteResponseWhenDeclined(Transaction txn,
|
private IntroducerSession onRemoteDeclineWhenDeclined(Transaction txn,
|
||||||
IntroducerSession s, AbstractIntroductionMessage m)
|
IntroducerSession s, DeclineMessage m) throws DbException {
|
||||||
throws DbException {
|
|
||||||
// The timestamp must be higher than the last request message
|
// The timestamp must be higher than the last request message
|
||||||
if (m.getTimestamp() <= s.getRequestTimestamp())
|
if (m.getTimestamp() <= s.getRequestTimestamp())
|
||||||
return abort(txn, s);
|
return abort(txn, s);
|
||||||
@@ -356,12 +399,17 @@ class IntroducerProtocolEngine
|
|||||||
messageTracker
|
messageTracker
|
||||||
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
|
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
|
||||||
|
|
||||||
|
// Forward DECLINE message
|
||||||
|
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||||
|
long timestamp = getLocalTimestamp(s, i);
|
||||||
|
Message sent = sendDeclineMessage(txn, i, timestamp, false);
|
||||||
|
|
||||||
Introducee introduceeA, introduceeB;
|
Introducee introduceeA, introduceeB;
|
||||||
if (senderIsAlice) {
|
if (senderIsAlice) {
|
||||||
introduceeA = new Introducee(s.getIntroduceeA(), m.getMessageId());
|
introduceeA = new Introducee(s.getIntroduceeA(), m.getMessageId());
|
||||||
introduceeB = s.getIntroduceeB();
|
introduceeB = new Introducee(s.getIntroduceeB(), sent);
|
||||||
} else {
|
} else {
|
||||||
introduceeA = s.getIntroduceeA();
|
introduceeA = new Introducee(s.getIntroduceeA(), sent);
|
||||||
introduceeB = new Introducee(s.getIntroduceeB(), m.getMessageId());
|
introduceeB = new Introducee(s.getIntroduceeB(), m.getMessageId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user