mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 20:59:54 +01:00
Merge branch '2084-aborted-introduction-sessions' into '1802-sync-via-removable-storage'
Allow aborted introduction sessions to be retried See merge request briar/briar!1490
This commit is contained in:
@@ -154,7 +154,8 @@ class IntroduceeProtocolEngine
|
|||||||
case REMOTE_ACCEPTED:
|
case REMOTE_ACCEPTED:
|
||||||
case AWAIT_AUTH:
|
case AWAIT_AUTH:
|
||||||
case AWAIT_ACTIVATE:
|
case AWAIT_ACTIVATE:
|
||||||
return abort(txn, session); // Invalid in these states
|
// Invalid in these states
|
||||||
|
return abort(txn, session, m.getMessageId());
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -174,7 +175,8 @@ class IntroduceeProtocolEngine
|
|||||||
case REMOTE_ACCEPTED:
|
case REMOTE_ACCEPTED:
|
||||||
case AWAIT_AUTH:
|
case AWAIT_AUTH:
|
||||||
case AWAIT_ACTIVATE:
|
case AWAIT_ACTIVATE:
|
||||||
return abort(txn, session); // Invalid in these states
|
// Invalid in these states
|
||||||
|
return abort(txn, session, m.getMessageId());
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -194,7 +196,8 @@ class IntroduceeProtocolEngine
|
|||||||
case REMOTE_ACCEPTED:
|
case REMOTE_ACCEPTED:
|
||||||
case AWAIT_AUTH:
|
case AWAIT_AUTH:
|
||||||
case AWAIT_ACTIVATE:
|
case AWAIT_ACTIVATE:
|
||||||
return abort(txn, session); // Invalid in these states
|
// Invalid in these states
|
||||||
|
return abort(txn, session, m.getMessageId());
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -213,7 +216,8 @@ class IntroduceeProtocolEngine
|
|||||||
case LOCAL_ACCEPTED:
|
case LOCAL_ACCEPTED:
|
||||||
case REMOTE_ACCEPTED:
|
case REMOTE_ACCEPTED:
|
||||||
case AWAIT_ACTIVATE:
|
case AWAIT_ACTIVATE:
|
||||||
return abort(txn, session); // Invalid in these states
|
// Invalid in these states
|
||||||
|
return abort(txn, session, m.getMessageId());
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -232,7 +236,8 @@ class IntroduceeProtocolEngine
|
|||||||
case LOCAL_ACCEPTED:
|
case LOCAL_ACCEPTED:
|
||||||
case REMOTE_ACCEPTED:
|
case REMOTE_ACCEPTED:
|
||||||
case AWAIT_AUTH:
|
case AWAIT_AUTH:
|
||||||
return abort(txn, session); // Invalid in these states
|
// Invalid in these states
|
||||||
|
return abort(txn, session, m.getMessageId());
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -248,7 +253,7 @@ class IntroduceeProtocolEngine
|
|||||||
IntroduceeSession s, RequestMessage m) throws DbException {
|
IntroduceeSession s, RequestMessage m) throws DbException {
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m.getMessageId());
|
||||||
|
|
||||||
// Mark the request visible in the UI and available to answer
|
// Mark the request visible in the UI and available to answer
|
||||||
markMessageVisibleInUi(txn, m.getMessageId());
|
markMessageVisibleInUi(txn, m.getMessageId());
|
||||||
@@ -343,10 +348,10 @@ class IntroduceeProtocolEngine
|
|||||||
IntroduceeSession s, AcceptMessage m) throws DbException {
|
IntroduceeSession s, AcceptMessage m) 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, m.getMessageId());
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m.getMessageId());
|
||||||
|
|
||||||
// Determine next state
|
// Determine next state
|
||||||
IntroduceeState state =
|
IntroduceeState state =
|
||||||
@@ -365,10 +370,10 @@ class IntroduceeProtocolEngine
|
|||||||
IntroduceeSession s, DeclineMessage m) throws DbException {
|
IntroduceeSession 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
|
||||||
if (m.getTimestamp() <= s.getRequestTimestamp())
|
if (m.getTimestamp() <= s.getRequestTimestamp())
|
||||||
return abort(txn, s);
|
return abort(txn, s, m.getMessageId());
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m.getMessageId());
|
||||||
|
|
||||||
// Mark the response visible in the UI
|
// Mark the response visible in the UI
|
||||||
markMessageVisibleInUi(txn, m.getMessageId());
|
markMessageVisibleInUi(txn, m.getMessageId());
|
||||||
@@ -398,10 +403,10 @@ class IntroduceeProtocolEngine
|
|||||||
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, m.getMessageId());
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m.getMessageId());
|
||||||
|
|
||||||
// Move to START state
|
// Move to START state
|
||||||
return IntroduceeSession.clear(s, START, s.getLastLocalMessageId(),
|
return IntroduceeSession.clear(s, START, s.getLastLocalMessageId(),
|
||||||
@@ -423,7 +428,7 @@ class IntroduceeProtocolEngine
|
|||||||
signature = crypto.sign(ourMacKey, localAuthor.getPrivateKey());
|
signature = crypto.sign(ourMacKey, localAuthor.getPrivateKey());
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
return abort(txn, s);
|
return abort(txn, s, s.getLastRemoteMessageId());
|
||||||
}
|
}
|
||||||
if (s.getState() != AWAIT_AUTH) throw new AssertionError();
|
if (s.getState() != AWAIT_AUTH) throw new AssertionError();
|
||||||
long localTimestamp = getTimestampForInvisibleMessage(s);
|
long localTimestamp = getTimestampForInvisibleMessage(s);
|
||||||
@@ -436,14 +441,14 @@ class IntroduceeProtocolEngine
|
|||||||
IntroduceeSession s, AuthMessage m) throws DbException {
|
IntroduceeSession s, AuthMessage m) throws DbException {
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m.getMessageId());
|
||||||
|
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||||
try {
|
try {
|
||||||
crypto.verifyAuthMac(m.getMac(), s, localAuthor.getId());
|
crypto.verifyAuthMac(m.getMac(), s, localAuthor.getId());
|
||||||
crypto.verifySignature(m.getSignature(), s);
|
crypto.verifySignature(m.getSignature(), s);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
return abort(txn, s);
|
return abort(txn, s, m.getMessageId());
|
||||||
}
|
}
|
||||||
long timestamp = Math.min(s.getLocal().acceptTimestamp,
|
long timestamp = Math.min(s.getLocal().acceptTimestamp,
|
||||||
s.getRemote().acceptTimestamp);
|
s.getRemote().acceptTimestamp);
|
||||||
@@ -487,13 +492,13 @@ class IntroduceeProtocolEngine
|
|||||||
IntroduceeSession s, ActivateMessage m) throws DbException {
|
IntroduceeSession s, ActivateMessage m) throws DbException {
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m.getMessageId());
|
||||||
|
|
||||||
// Validate MAC
|
// Validate MAC
|
||||||
try {
|
try {
|
||||||
crypto.verifyActivateMac(m.getMac(), s);
|
crypto.verifyActivateMac(m.getMac(), s);
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
return abort(txn, s);
|
return abort(txn, s, m.getMessageId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// We might not have added transport keys
|
// We might not have added transport keys
|
||||||
@@ -522,8 +527,8 @@ class IntroduceeProtocolEngine
|
|||||||
s.getLocalTimestamp(), m.getMessageId());
|
s.getLocalTimestamp(), m.getMessageId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroduceeSession abort(Transaction txn, IntroduceeSession s)
|
private IntroduceeSession abort(Transaction txn, IntroduceeSession s,
|
||||||
throws DbException {
|
@Nullable MessageId lastRemoteMessageId) throws DbException {
|
||||||
// Mark the request message unavailable to answer
|
// Mark the request message unavailable to answer
|
||||||
markRequestsUnavailableToAnswer(txn, s);
|
markRequestsUnavailableToAnswer(txn, s);
|
||||||
|
|
||||||
@@ -536,7 +541,7 @@ class IntroduceeProtocolEngine
|
|||||||
|
|
||||||
// Reset the session back to initial state
|
// Reset the session back to initial state
|
||||||
return IntroduceeSession.clear(s, START, sent.getId(),
|
return IntroduceeSession.clear(s, START, sent.getId(),
|
||||||
sent.getTimestamp(), s.getLastRemoteMessageId());
|
sent.getTimestamp(), lastRemoteMessageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInvalidDependency(IntroduceeSession s,
|
private boolean isInvalidDependency(IntroduceeSession s,
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class IntroducerProtocolEngine
|
|||||||
@Override
|
@Override
|
||||||
public IntroducerSession onRequestMessage(Transaction txn,
|
public IntroducerSession onRequestMessage(Transaction txn,
|
||||||
IntroducerSession s, RequestMessage m) throws DbException {
|
IntroducerSession s, RequestMessage m) throws DbException {
|
||||||
return abort(txn, s); // Invalid in this role
|
return abort(txn, s, m); // Invalid in this role
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -136,7 +136,7 @@ class IntroducerProtocolEngine
|
|||||||
case AWAIT_ACTIVATES:
|
case AWAIT_ACTIVATES:
|
||||||
case AWAIT_ACTIVATE_A:
|
case AWAIT_ACTIVATE_A:
|
||||||
case AWAIT_ACTIVATE_B:
|
case AWAIT_ACTIVATE_B:
|
||||||
return abort(txn, s); // Invalid in these states
|
return abort(txn, s, m); // Invalid in these states
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ class IntroducerProtocolEngine
|
|||||||
case AWAIT_ACTIVATES:
|
case AWAIT_ACTIVATES:
|
||||||
case AWAIT_ACTIVATE_A:
|
case AWAIT_ACTIVATE_A:
|
||||||
case AWAIT_ACTIVATE_B:
|
case AWAIT_ACTIVATE_B:
|
||||||
return abort(txn, s); // Invalid in these states
|
return abort(txn, s, m); // Invalid in these states
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ class IntroducerProtocolEngine
|
|||||||
case AWAIT_ACTIVATES:
|
case AWAIT_ACTIVATES:
|
||||||
case AWAIT_ACTIVATE_A:
|
case AWAIT_ACTIVATE_A:
|
||||||
case AWAIT_ACTIVATE_B:
|
case AWAIT_ACTIVATE_B:
|
||||||
return abort(txn, s); // Invalid in these states
|
return abort(txn, s, m); // Invalid in these states
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ class IntroducerProtocolEngine
|
|||||||
case AWAIT_AUTHS:
|
case AWAIT_AUTHS:
|
||||||
case AWAIT_AUTH_A:
|
case AWAIT_AUTH_A:
|
||||||
case AWAIT_AUTH_B:
|
case AWAIT_AUTH_B:
|
||||||
return abort(txn, s); // Invalid in these states
|
return abort(txn, s, m); // Invalid in these states
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -244,17 +244,17 @@ class IntroducerProtocolEngine
|
|||||||
IntroducerSession s, AcceptMessage m) throws DbException {
|
IntroducerSession s, AcceptMessage m) 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, m);
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
// The message must be expected in the current state
|
// The message must be expected in the current state
|
||||||
boolean senderIsAlice = senderIsAlice(s, m);
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
if (s.getState() != AWAIT_RESPONSES) {
|
if (s.getState() != AWAIT_RESPONSES) {
|
||||||
if (senderIsAlice && s.getState() != AWAIT_RESPONSE_A)
|
if (senderIsAlice && s.getState() != AWAIT_RESPONSE_A)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
else if (!senderIsAlice && s.getState() != AWAIT_RESPONSE_B)
|
else if (!senderIsAlice && s.getState() != AWAIT_RESPONSE_B)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the response visible in the UI
|
// Mark the response visible in the UI
|
||||||
@@ -309,16 +309,16 @@ class IntroducerProtocolEngine
|
|||||||
IntroducerSession s, AcceptMessage m) throws DbException {
|
IntroducerSession s, AcceptMessage m) 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, m);
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
// The message must be expected in the current state
|
// The message must be expected in the current state
|
||||||
boolean senderIsAlice = senderIsAlice(s, m);
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
if (senderIsAlice && s.getState() != B_DECLINED)
|
if (senderIsAlice && s.getState() != B_DECLINED)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
else if (!senderIsAlice && s.getState() != A_DECLINED)
|
else if (!senderIsAlice && s.getState() != A_DECLINED)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
|
|
||||||
// Mark the response visible in the UI
|
// Mark the response visible in the UI
|
||||||
markMessageVisibleInUi(txn, m.getMessageId());
|
markMessageVisibleInUi(txn, m.getMessageId());
|
||||||
@@ -362,17 +362,17 @@ class IntroducerProtocolEngine
|
|||||||
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
|
||||||
if (m.getTimestamp() <= s.getRequestTimestamp())
|
if (m.getTimestamp() <= s.getRequestTimestamp())
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
// The message must be expected in the current state
|
// The message must be expected in the current state
|
||||||
boolean senderIsAlice = senderIsAlice(s, m);
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
if (s.getState() != AWAIT_RESPONSES) {
|
if (s.getState() != AWAIT_RESPONSES) {
|
||||||
if (senderIsAlice && s.getState() != AWAIT_RESPONSE_A)
|
if (senderIsAlice && s.getState() != AWAIT_RESPONSE_A)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
else if (!senderIsAlice && s.getState() != AWAIT_RESPONSE_B)
|
else if (!senderIsAlice && s.getState() != AWAIT_RESPONSE_B)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the response visible in the UI
|
// Mark the response visible in the UI
|
||||||
@@ -419,16 +419,16 @@ class IntroducerProtocolEngine
|
|||||||
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
|
||||||
if (m.getTimestamp() <= s.getRequestTimestamp())
|
if (m.getTimestamp() <= s.getRequestTimestamp())
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
// The message must be expected in the current state
|
// The message must be expected in the current state
|
||||||
boolean senderIsAlice = senderIsAlice(s, m);
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
if (senderIsAlice && s.getState() != B_DECLINED)
|
if (senderIsAlice && s.getState() != B_DECLINED)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
else if (!senderIsAlice && s.getState() != A_DECLINED)
|
else if (!senderIsAlice && s.getState() != A_DECLINED)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
|
|
||||||
// Mark the response visible in the UI
|
// Mark the response visible in the UI
|
||||||
markMessageVisibleInUi(txn, m.getMessageId());
|
markMessageVisibleInUi(txn, m.getMessageId());
|
||||||
@@ -470,14 +470,14 @@ class IntroducerProtocolEngine
|
|||||||
IntroducerSession s, AuthMessage m) throws DbException {
|
IntroducerSession s, AuthMessage m) throws DbException {
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
// The message must be expected in the current state
|
// The message must be expected in the current state
|
||||||
boolean senderIsAlice = senderIsAlice(s, m);
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
if (s.getState() != AWAIT_AUTHS) {
|
if (s.getState() != AWAIT_AUTHS) {
|
||||||
if (senderIsAlice && s.getState() != AWAIT_AUTH_A)
|
if (senderIsAlice && s.getState() != AWAIT_AUTH_A)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
else if (!senderIsAlice && s.getState() != AWAIT_AUTH_B)
|
else if (!senderIsAlice && s.getState() != AWAIT_AUTH_B)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward AUTH message
|
// Forward AUTH message
|
||||||
@@ -506,14 +506,14 @@ class IntroducerProtocolEngine
|
|||||||
IntroducerSession s, ActivateMessage m) throws DbException {
|
IntroducerSession s, ActivateMessage m) throws DbException {
|
||||||
// The dependency, if any, must be the last remote message
|
// The dependency, if any, must be the last remote message
|
||||||
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
// The message must be expected in the current state
|
// The message must be expected in the current state
|
||||||
boolean senderIsAlice = senderIsAlice(s, m);
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
if (s.getState() != AWAIT_ACTIVATES) {
|
if (s.getState() != AWAIT_ACTIVATES) {
|
||||||
if (senderIsAlice && s.getState() != AWAIT_ACTIVATE_A)
|
if (senderIsAlice && s.getState() != AWAIT_ACTIVATE_A)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
else if (!senderIsAlice && s.getState() != AWAIT_ACTIVATE_B)
|
else if (!senderIsAlice && s.getState() != AWAIT_ACTIVATE_B)
|
||||||
return abort(txn, s);
|
return abort(txn, s, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward ACTIVATE message
|
// Forward ACTIVATE message
|
||||||
@@ -588,21 +588,31 @@ class IntroducerProtocolEngine
|
|||||||
s.getRequestTimestamp(), introduceeA, introduceeB);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession abort(Transaction txn, IntroducerSession s)
|
private IntroducerSession abort(Transaction txn, IntroducerSession s,
|
||||||
throws DbException {
|
AbstractIntroductionMessage lastRemoteMessage) throws DbException {
|
||||||
// Broadcast abort event for testing
|
// Broadcast abort event for testing
|
||||||
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
||||||
|
|
||||||
|
// Record the message that triggered the abort
|
||||||
|
Introducee introduceeA = s.getIntroduceeA();
|
||||||
|
Introducee introduceeB = s.getIntroduceeB();
|
||||||
|
if (senderIsAlice(s, lastRemoteMessage)) {
|
||||||
|
introduceeA = new Introducee(introduceeA,
|
||||||
|
lastRemoteMessage.getMessageId());
|
||||||
|
} else {
|
||||||
|
introduceeB = new Introducee(introduceeB,
|
||||||
|
lastRemoteMessage.getMessageId());
|
||||||
|
}
|
||||||
|
|
||||||
// Send an ABORT message to both introducees
|
// Send an ABORT message to both introducees
|
||||||
long timestampA =
|
long timestampA = getTimestampForInvisibleMessage(s, introduceeA);
|
||||||
getTimestampForInvisibleMessage(s, s.getIntroduceeA());
|
Message sentA = sendAbortMessage(txn, introduceeA, timestampA);
|
||||||
Message sentA = sendAbortMessage(txn, s.getIntroduceeA(), timestampA);
|
long timestampB = getTimestampForInvisibleMessage(s, introduceeB);
|
||||||
long timestampB =
|
Message sentB = sendAbortMessage(txn, introduceeB, timestampB);
|
||||||
getTimestampForInvisibleMessage(s, s.getIntroduceeB());
|
|
||||||
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);
|
introduceeA = new Introducee(introduceeA, sentA);
|
||||||
Introducee introduceeB = new Introducee(s.getIntroduceeB(), sentB);
|
introduceeB = new Introducee(introduceeB, sentB);
|
||||||
return new IntroducerSession(s.getSessionId(), START,
|
return new IntroducerSession(s.getSessionId(), START,
|
||||||
s.getRequestTimestamp(), introduceeA, introduceeB);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user