mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 05:09:53 +01:00
Ensure that incoming messages are expected in the current state
Previously, the introducer would process and forward invalid messages by the introducees. This commit adds the necessary checks and tests.
This commit is contained in:
@@ -200,21 +200,21 @@ class IntroducerProtocolEngine
|
|||||||
@Nullable String message, long timestamp) throws DbException {
|
@Nullable String message, long timestamp) throws DbException {
|
||||||
// Send REQUEST messages
|
// Send REQUEST messages
|
||||||
long localTimestamp =
|
long localTimestamp =
|
||||||
Math.max(timestamp, getLocalTimestamp(s, s.getIntroducee1()));
|
Math.max(timestamp, getLocalTimestamp(s, s.getIntroduceeA()));
|
||||||
Message sent1 = sendRequestMessage(txn, s.getIntroducee1(),
|
Message sentA = sendRequestMessage(txn, s.getIntroduceeA(),
|
||||||
localTimestamp, s.getIntroducee2().author, message
|
localTimestamp, s.getIntroduceeB().author, message
|
||||||
);
|
);
|
||||||
Message sent2 = sendRequestMessage(txn, s.getIntroducee2(),
|
Message sentB = sendRequestMessage(txn, s.getIntroduceeB(),
|
||||||
localTimestamp, s.getIntroducee1().author, message
|
localTimestamp, s.getIntroduceeA().author, message
|
||||||
);
|
);
|
||||||
// Track the messages
|
// Track the messages
|
||||||
messageTracker.trackOutgoingMessage(txn, sent1);
|
messageTracker.trackOutgoingMessage(txn, sentA);
|
||||||
messageTracker.trackOutgoingMessage(txn, sent2);
|
messageTracker.trackOutgoingMessage(txn, sentB);
|
||||||
// Move to the AWAIT_RESPONSES state
|
// Move to the AWAIT_RESPONSES state
|
||||||
Introducee introducee1 = new Introducee(s.getIntroducee1(), sent1);
|
Introducee introduceeA = new Introducee(s.getIntroduceeA(), sentA);
|
||||||
Introducee introducee2 = new Introducee(s.getIntroducee2(), sent2);
|
Introducee introduceeB = new Introducee(s.getIntroduceeB(), sentB);
|
||||||
return new IntroducerSession(s.getSessionId(), AWAIT_RESPONSES,
|
return new IntroducerSession(s.getSessionId(), AWAIT_RESPONSES,
|
||||||
localTimestamp, introducee1, introducee2);
|
localTimestamp, introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession onRemoteAccept(Transaction txn,
|
private IntroducerSession onRemoteAccept(Transaction txn,
|
||||||
@@ -225,6 +225,14 @@ class IntroducerProtocolEngine
|
|||||||
// 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);
|
||||||
|
// The message must be expected in the current state
|
||||||
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
|
if (s.getState() != AWAIT_RESPONSES) {
|
||||||
|
if (senderIsAlice && s.getState() != AWAIT_RESPONSE_A)
|
||||||
|
return abort(txn, s);
|
||||||
|
else if (!senderIsAlice && s.getState() != AWAIT_RESPONSE_B)
|
||||||
|
return abort(txn, s);
|
||||||
|
}
|
||||||
|
|
||||||
// Mark the response visible in the UI
|
// Mark the response visible in the UI
|
||||||
markMessageVisibleInUi(txn, m.getMessageId());
|
markMessageVisibleInUi(txn, m.getMessageId());
|
||||||
@@ -240,27 +248,24 @@ class IntroducerProtocolEngine
|
|||||||
m.getAcceptTimestamp(), m.getTransportProperties(),
|
m.getAcceptTimestamp(), m.getTransportProperties(),
|
||||||
false);
|
false);
|
||||||
|
|
||||||
// Move to the next state
|
// Create the next state
|
||||||
IntroducerState state = AWAIT_AUTHS;
|
IntroducerState state = AWAIT_AUTHS;
|
||||||
Introducee introducee1, introducee2;
|
Introducee introduceeA, introduceeB;
|
||||||
Contact c;
|
if (senderIsAlice) {
|
||||||
if (i.equals(s.getIntroducee1())) {
|
|
||||||
if (s.getState() == AWAIT_RESPONSES) state = AWAIT_RESPONSE_A;
|
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), sent);
|
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), m.getMessageId());
|
|
||||||
c = contactManager
|
|
||||||
.getContact(txn, s.getIntroducee2().author.getId(),
|
|
||||||
identityManager.getLocalAuthor(txn).getId());
|
|
||||||
} else if (i.equals(s.getIntroducee2())) {
|
|
||||||
if (s.getState() == AWAIT_RESPONSES) state = AWAIT_RESPONSE_B;
|
if (s.getState() == AWAIT_RESPONSES) state = AWAIT_RESPONSE_B;
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), m.getMessageId());
|
introduceeA = new Introducee(s.getIntroduceeA(), m.getMessageId());
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), sent);
|
introduceeB = new Introducee(s.getIntroduceeB(), sent);
|
||||||
c = contactManager
|
} else {
|
||||||
.getContact(txn, s.getIntroducee1().author.getId(),
|
if (s.getState() == AWAIT_RESPONSES) state = AWAIT_RESPONSE_A;
|
||||||
identityManager.getLocalAuthor(txn).getId());
|
introduceeA = new Introducee(s.getIntroduceeA(), sent);
|
||||||
} else throw new AssertionError();
|
introduceeB = new Introducee(s.getIntroduceeB(), m.getMessageId());
|
||||||
|
}
|
||||||
|
|
||||||
// Broadcast IntroductionResponseReceivedEvent
|
// Broadcast IntroductionResponseReceivedEvent
|
||||||
|
AuthorId localAuthorId = identityManager.getLocalAuthor(txn).getId();
|
||||||
|
Contact c = contactManager.getContact(txn,
|
||||||
|
senderIsAlice ? introduceeA.author.getId() :
|
||||||
|
introduceeB.author.getId(), localAuthorId);
|
||||||
IntroductionResponse request =
|
IntroductionResponse request =
|
||||||
new IntroductionResponse(s.getSessionId(), m.getMessageId(),
|
new IntroductionResponse(s.getSessionId(), m.getMessageId(),
|
||||||
m.getGroupId(), INTRODUCER, m.getTimestamp(), false,
|
m.getGroupId(), INTRODUCER, m.getTimestamp(), false,
|
||||||
@@ -269,8 +274,14 @@ class IntroducerProtocolEngine
|
|||||||
new IntroductionResponseReceivedEvent(c.getId(), request);
|
new IntroductionResponseReceivedEvent(c.getId(), request);
|
||||||
txn.attach(e);
|
txn.attach(e);
|
||||||
|
|
||||||
|
// Move to the next state
|
||||||
return new IntroducerSession(s.getSessionId(), state,
|
return new IntroducerSession(s.getSessionId(), state,
|
||||||
s.getRequestTimestamp(), introducee1, introducee2);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean senderIsAlice(IntroducerSession s,
|
||||||
|
AbstractIntroductionMessage m) {
|
||||||
|
return m.getGroupId().equals(s.getIntroduceeA().groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession onRemoteDecline(Transaction txn,
|
private IntroducerSession onRemoteDecline(Transaction txn,
|
||||||
@@ -281,6 +292,14 @@ class IntroducerProtocolEngine
|
|||||||
// 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);
|
||||||
|
// The message must be expected in the current state
|
||||||
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
|
if (s.getState() != AWAIT_RESPONSES) {
|
||||||
|
if (senderIsAlice && s.getState() != AWAIT_RESPONSE_A)
|
||||||
|
return abort(txn, s);
|
||||||
|
else if (!senderIsAlice && s.getState() != AWAIT_RESPONSE_B)
|
||||||
|
return abort(txn, s);
|
||||||
|
}
|
||||||
|
|
||||||
// Mark the response visible in the UI
|
// Mark the response visible in the UI
|
||||||
markMessageVisibleInUi(txn, m.getMessageId());
|
markMessageVisibleInUi(txn, m.getMessageId());
|
||||||
@@ -293,25 +312,21 @@ class IntroducerProtocolEngine
|
|||||||
long timestamp = getLocalTimestamp(s, i);
|
long timestamp = getLocalTimestamp(s, i);
|
||||||
Message sent = sendDeclineMessage(txn, i, timestamp, false);
|
Message sent = sendDeclineMessage(txn, i, timestamp, false);
|
||||||
|
|
||||||
// Move to the START state
|
// Update introducee state
|
||||||
Introducee introducee1, introducee2;
|
Introducee introduceeA, introduceeB;
|
||||||
AuthorId localAuthorId =identityManager.getLocalAuthor(txn).getId();
|
if (senderIsAlice) {
|
||||||
Contact c;
|
introduceeA = new Introducee(s.getIntroduceeA(), m.getMessageId());
|
||||||
if (i.equals(s.getIntroducee1())) {
|
introduceeB = new Introducee(s.getIntroduceeB(), sent);
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), sent);
|
} else {
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), m.getMessageId());
|
introduceeA = new Introducee(s.getIntroduceeA(), sent);
|
||||||
c = contactManager
|
introduceeB = new Introducee(s.getIntroduceeB(), m.getMessageId());
|
||||||
.getContact(txn, s.getIntroducee2().author.getId(),
|
}
|
||||||
localAuthorId);
|
|
||||||
} else if (i.equals(s.getIntroducee2())) {
|
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), m.getMessageId());
|
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), sent);
|
|
||||||
c = contactManager
|
|
||||||
.getContact(txn, s.getIntroducee1().author.getId(),
|
|
||||||
localAuthorId);
|
|
||||||
} else throw new AssertionError();
|
|
||||||
|
|
||||||
// Broadcast IntroductionResponseReceivedEvent
|
// Broadcast IntroductionResponseReceivedEvent
|
||||||
|
AuthorId localAuthorId = identityManager.getLocalAuthor(txn).getId();
|
||||||
|
Contact c = contactManager.getContact(txn,
|
||||||
|
senderIsAlice ? introduceeA.author.getId() :
|
||||||
|
introduceeB.author.getId(), localAuthorId);
|
||||||
IntroductionResponse request =
|
IntroductionResponse request =
|
||||||
new IntroductionResponse(s.getSessionId(), m.getMessageId(),
|
new IntroductionResponse(s.getSessionId(), m.getMessageId(),
|
||||||
m.getGroupId(), INTRODUCER, m.getTimestamp(), false,
|
m.getGroupId(), INTRODUCER, m.getTimestamp(), false,
|
||||||
@@ -321,7 +336,7 @@ class IntroducerProtocolEngine
|
|||||||
txn.attach(e);
|
txn.attach(e);
|
||||||
|
|
||||||
return new IntroducerSession(s.getSessionId(), START,
|
return new IntroducerSession(s.getSessionId(), START,
|
||||||
s.getRequestTimestamp(), introducee1, introducee2);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession onRemoteResponseInStart(Transaction txn,
|
private IntroducerSession onRemoteResponseInStart(Transaction txn,
|
||||||
@@ -341,20 +356,20 @@ class IntroducerProtocolEngine
|
|||||||
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
|
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
|
||||||
|
|
||||||
Introducee i = getIntroducee(s, m.getGroupId());
|
Introducee i = getIntroducee(s, m.getGroupId());
|
||||||
Introducee introducee1, introducee2;
|
Introducee introduceeA, introduceeB;
|
||||||
AuthorId localAuthorId = identityManager.getLocalAuthor(txn).getId();
|
AuthorId localAuthorId = identityManager.getLocalAuthor(txn).getId();
|
||||||
Contact c;
|
Contact c;
|
||||||
if (i.equals(s.getIntroducee1())) {
|
if (i.equals(s.getIntroduceeA())) {
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), m.getMessageId());
|
introduceeA = new Introducee(s.getIntroduceeA(), m.getMessageId());
|
||||||
introducee2 = s.getIntroducee2();
|
introduceeB = s.getIntroduceeB();
|
||||||
c = contactManager
|
c = contactManager
|
||||||
.getContact(txn, s.getIntroducee1().author.getId(),
|
.getContact(txn, s.getIntroduceeA().author.getId(),
|
||||||
localAuthorId);
|
localAuthorId);
|
||||||
} else if (i.equals(s.getIntroducee2())) {
|
} else if (i.equals(s.getIntroduceeB())) {
|
||||||
introducee1 = s.getIntroducee1();
|
introduceeA = s.getIntroduceeA();
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), m.getMessageId());
|
introduceeB = new Introducee(s.getIntroduceeB(), m.getMessageId());
|
||||||
c = contactManager
|
c = contactManager
|
||||||
.getContact(txn, s.getIntroducee2().author.getId(),
|
.getContact(txn, s.getIntroduceeB().author.getId(),
|
||||||
localAuthorId);
|
localAuthorId);
|
||||||
} else throw new AssertionError();
|
} else throw new AssertionError();
|
||||||
|
|
||||||
@@ -369,7 +384,7 @@ class IntroducerProtocolEngine
|
|||||||
txn.attach(e);
|
txn.attach(e);
|
||||||
|
|
||||||
return new IntroducerSession(s.getSessionId(), START,
|
return new IntroducerSession(s.getSessionId(), START,
|
||||||
s.getRequestTimestamp(), introducee1, introducee2);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession onRemoteAuth(Transaction txn,
|
private IntroducerSession onRemoteAuth(Transaction txn,
|
||||||
@@ -377,6 +392,14 @@ class IntroducerProtocolEngine
|
|||||||
// 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);
|
||||||
|
// The message must be expected in the current state
|
||||||
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
|
if (s.getState() != AWAIT_AUTHS) {
|
||||||
|
if (senderIsAlice && s.getState() != AWAIT_AUTH_A)
|
||||||
|
return abort(txn, s);
|
||||||
|
else if (!senderIsAlice && s.getState() != AWAIT_AUTH_B)
|
||||||
|
return abort(txn, s);
|
||||||
|
}
|
||||||
|
|
||||||
// Forward AUTH message
|
// Forward AUTH message
|
||||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||||
@@ -386,18 +409,18 @@ class IntroducerProtocolEngine
|
|||||||
|
|
||||||
// Move to the next state
|
// Move to the next state
|
||||||
IntroducerState state = AWAIT_ACTIVATES;
|
IntroducerState state = AWAIT_ACTIVATES;
|
||||||
Introducee introducee1, introducee2;
|
Introducee introduceeA, introduceeB;
|
||||||
if (i.equals(s.getIntroducee1())) {
|
if (senderIsAlice) {
|
||||||
if (s.getState() == AWAIT_AUTHS) state = AWAIT_AUTH_A;
|
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), sent);
|
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), m.getMessageId());
|
|
||||||
} else if (i.equals(s.getIntroducee2())) {
|
|
||||||
if (s.getState() == AWAIT_AUTHS) state = AWAIT_AUTH_B;
|
if (s.getState() == AWAIT_AUTHS) state = AWAIT_AUTH_B;
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), m.getMessageId());
|
introduceeA = new Introducee(s.getIntroduceeA(), m.getMessageId());
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), sent);
|
introduceeB = new Introducee(s.getIntroduceeB(), sent);
|
||||||
} else throw new AssertionError();
|
} else {
|
||||||
|
if (s.getState() == AWAIT_AUTHS) state = AWAIT_AUTH_A;
|
||||||
|
introduceeA = new Introducee(s.getIntroduceeA(), sent);
|
||||||
|
introduceeB = new Introducee(s.getIntroduceeB(), m.getMessageId());
|
||||||
|
}
|
||||||
return new IntroducerSession(s.getSessionId(), state,
|
return new IntroducerSession(s.getSessionId(), state,
|
||||||
s.getRequestTimestamp(), introducee1, introducee2);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession onRemoteActivate(Transaction txn,
|
private IntroducerSession onRemoteActivate(Transaction txn,
|
||||||
@@ -405,26 +428,34 @@ class IntroducerProtocolEngine
|
|||||||
// 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);
|
||||||
|
// The message must be expected in the current state
|
||||||
|
boolean senderIsAlice = senderIsAlice(s, m);
|
||||||
|
if (s.getState() != AWAIT_ACTIVATES) {
|
||||||
|
if (senderIsAlice && s.getState() != AWAIT_ACTIVATE_A)
|
||||||
|
return abort(txn, s);
|
||||||
|
else if (!senderIsAlice && s.getState() != AWAIT_ACTIVATE_B)
|
||||||
|
return abort(txn, s);
|
||||||
|
}
|
||||||
|
|
||||||
// Forward AUTH message
|
// Forward ACTIVATE message
|
||||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||||
long timestamp = getLocalTimestamp(s, i);
|
long timestamp = getLocalTimestamp(s, i);
|
||||||
Message sent = sendActivateMessage(txn, i, timestamp);
|
Message sent = sendActivateMessage(txn, i, timestamp);
|
||||||
|
|
||||||
// Move to the next state
|
// Move to the next state
|
||||||
IntroducerState state = START;
|
IntroducerState state = START;
|
||||||
Introducee introducee1, introducee2;
|
Introducee introduceeA, introduceeB;
|
||||||
if (i.equals(s.getIntroducee1())) {
|
if (senderIsAlice) {
|
||||||
if (s.getState() == AWAIT_ACTIVATES) state = AWAIT_ACTIVATE_A;
|
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), sent);
|
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), m.getMessageId());
|
|
||||||
} else if (i.equals(s.getIntroducee2())) {
|
|
||||||
if (s.getState() == AWAIT_ACTIVATES) state = AWAIT_ACTIVATE_B;
|
if (s.getState() == AWAIT_ACTIVATES) state = AWAIT_ACTIVATE_B;
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), m.getMessageId());
|
introduceeA = new Introducee(s.getIntroduceeA(), m.getMessageId());
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), sent);
|
introduceeB = new Introducee(s.getIntroduceeB(), sent);
|
||||||
} else throw new AssertionError();
|
} else {
|
||||||
|
if (s.getState() == AWAIT_ACTIVATES) state = AWAIT_ACTIVATE_A;
|
||||||
|
introduceeA = new Introducee(s.getIntroduceeA(), sent);
|
||||||
|
introduceeB = new Introducee(s.getIntroduceeB(), m.getMessageId());
|
||||||
|
}
|
||||||
return new IntroducerSession(s.getSessionId(), state,
|
return new IntroducerSession(s.getSessionId(), state,
|
||||||
s.getRequestTimestamp(), introducee1, introducee2);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession onRemoteAbort(Transaction txn,
|
private IntroducerSession onRemoteAbort(Transaction txn,
|
||||||
@@ -438,16 +469,16 @@ class IntroducerProtocolEngine
|
|||||||
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
||||||
|
|
||||||
// Reset the session back to initial state
|
// Reset the session back to initial state
|
||||||
Introducee introducee1, introducee2;
|
Introducee introduceeA, introduceeB;
|
||||||
if (i.equals(s.getIntroducee1())) {
|
if (i.equals(s.getIntroduceeA())) {
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), sent);
|
introduceeA = new Introducee(s.getIntroduceeA(), sent);
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), m.getMessageId());
|
introduceeB = new Introducee(s.getIntroduceeB(), m.getMessageId());
|
||||||
} else if (i.equals(s.getIntroducee2())) {
|
} else if (i.equals(s.getIntroduceeB())) {
|
||||||
introducee1 = new Introducee(s.getIntroducee1(), m.getMessageId());
|
introduceeA = new Introducee(s.getIntroduceeA(), m.getMessageId());
|
||||||
introducee2 = new Introducee(s.getIntroducee2(), sent);
|
introduceeB = new Introducee(s.getIntroduceeB(), sent);
|
||||||
} else throw new AssertionError();
|
} else throw new AssertionError();
|
||||||
return new IntroducerSession(s.getSessionId(), START,
|
return new IntroducerSession(s.getSessionId(), START,
|
||||||
s.getRequestTimestamp(), introducee1, introducee2);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroducerSession abort(Transaction txn,
|
private IntroducerSession abort(Transaction txn,
|
||||||
@@ -456,28 +487,28 @@ class IntroducerProtocolEngine
|
|||||||
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 timestamp1 = getLocalTimestamp(s, s.getIntroducee1());
|
long timestampA = getLocalTimestamp(s, s.getIntroduceeA());
|
||||||
Message sent1 = sendAbortMessage(txn, s.getIntroducee1(), timestamp1);
|
Message sentA = sendAbortMessage(txn, s.getIntroduceeA(), timestampA);
|
||||||
long timestamp2 = getLocalTimestamp(s, s.getIntroducee2());
|
long timestampB = getLocalTimestamp(s, s.getIntroduceeB());
|
||||||
Message sent2 = sendAbortMessage(txn, s.getIntroducee2(), timestamp2);
|
Message sentB = sendAbortMessage(txn, s.getIntroduceeB(), timestampB);
|
||||||
// Reset the session back to initial state
|
// Reset the session back to initial state
|
||||||
Introducee introducee1 = new Introducee(s.getIntroducee1(), sent1);
|
Introducee introduceeA = new Introducee(s.getIntroduceeA(), sentA);
|
||||||
Introducee introducee2 = new Introducee(s.getIntroducee2(), sent2);
|
Introducee introduceeB = new Introducee(s.getIntroduceeB(), sentB);
|
||||||
return new IntroducerSession(s.getSessionId(), START,
|
return new IntroducerSession(s.getSessionId(), START,
|
||||||
s.getRequestTimestamp(), introducee1, introducee2);
|
s.getRequestTimestamp(), introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Introducee getIntroducee(IntroducerSession s, GroupId g) {
|
private Introducee getIntroducee(IntroducerSession s, GroupId g) {
|
||||||
if (s.getIntroducee1().groupId.equals(g)) return s.getIntroducee1();
|
if (s.getIntroduceeA().groupId.equals(g)) return s.getIntroduceeA();
|
||||||
else if (s.getIntroducee2().groupId.equals(g))
|
else if (s.getIntroduceeB().groupId.equals(g))
|
||||||
return s.getIntroducee2();
|
return s.getIntroduceeB();
|
||||||
else throw new AssertionError();
|
else throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Introducee getOtherIntroducee(IntroducerSession s, GroupId g) {
|
private Introducee getOtherIntroducee(IntroducerSession s, GroupId g) {
|
||||||
if (s.getIntroducee1().groupId.equals(g)) return s.getIntroducee2();
|
if (s.getIntroduceeA().groupId.equals(g)) return s.getIntroduceeB();
|
||||||
else if (s.getIntroducee2().groupId.equals(g))
|
else if (s.getIntroduceeB().groupId.equals(g))
|
||||||
return s.getIntroducee1();
|
return s.getIntroduceeA();
|
||||||
else throw new AssertionError();
|
else throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,21 +17,21 @@ import static org.briarproject.briar.api.introduction.Role.INTRODUCER;
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class IntroducerSession extends Session<IntroducerState> {
|
class IntroducerSession extends Session<IntroducerState> {
|
||||||
|
|
||||||
private final Introducee introducee1, introducee2;
|
private final Introducee introduceeA, introduceeB;
|
||||||
|
|
||||||
IntroducerSession(SessionId sessionId, IntroducerState state,
|
IntroducerSession(SessionId sessionId, IntroducerState state,
|
||||||
long requestTimestamp, Introducee introducee1,
|
long requestTimestamp, Introducee introduceeA,
|
||||||
Introducee introducee2) {
|
Introducee introduceeB) {
|
||||||
super(sessionId, state, requestTimestamp);
|
super(sessionId, state, requestTimestamp);
|
||||||
this.introducee1 = introducee1;
|
this.introduceeA = introduceeA;
|
||||||
this.introducee2 = introducee2;
|
this.introduceeB = introduceeB;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntroducerSession(SessionId sessionId, GroupId groupId1, Author author1,
|
IntroducerSession(SessionId sessionId, GroupId groupIdA, Author authorA,
|
||||||
GroupId groupId2, Author author2) {
|
GroupId groupIdB, Author authorB) {
|
||||||
this(sessionId, IntroducerState.START, -1,
|
this(sessionId, IntroducerState.START, -1,
|
||||||
new Introducee(sessionId, groupId1, author1),
|
new Introducee(sessionId, groupIdA, authorA),
|
||||||
new Introducee(sessionId, groupId2, author2));
|
new Introducee(sessionId, groupIdB, authorB));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -39,12 +39,12 @@ class IntroducerSession extends Session<IntroducerState> {
|
|||||||
return INTRODUCER;
|
return INTRODUCER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Introducee getIntroducee1() {
|
Introducee getIntroduceeA() {
|
||||||
return introducee1;
|
return introduceeA;
|
||||||
}
|
}
|
||||||
|
|
||||||
Introducee getIntroducee2() {
|
Introducee getIntroduceeB() {
|
||||||
return introducee2;
|
return introduceeB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ interface IntroductionConstants {
|
|||||||
String SESSION_KEY_LAST_REMOTE_MESSAGE_ID = "lastRemoteMessageId";
|
String SESSION_KEY_LAST_REMOTE_MESSAGE_ID = "lastRemoteMessageId";
|
||||||
|
|
||||||
// Session Keys Introducer
|
// Session Keys Introducer
|
||||||
String SESSION_KEY_INTRODUCEE_1 = "introducee1";
|
String SESSION_KEY_INTRODUCEE_A = "introduceeA";
|
||||||
String SESSION_KEY_INTRODUCEE_2 = "introducee2";
|
String SESSION_KEY_INTRODUCEE_B = "introduceeB";
|
||||||
String SESSION_KEY_GROUP_ID = "groupId";
|
String SESSION_KEY_GROUP_ID = "groupId";
|
||||||
String SESSION_KEY_AUTHOR = "author";
|
String SESSION_KEY_AUTHOR = "author";
|
||||||
|
|
||||||
|
|||||||
@@ -308,8 +308,15 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
// This is the first request - create a new session
|
// This is the first request - create a new session
|
||||||
GroupId groupId1 = getContactGroup(c1).getId();
|
GroupId groupId1 = getContactGroup(c1).getId();
|
||||||
GroupId groupId2 = getContactGroup(c2).getId();
|
GroupId groupId2 = getContactGroup(c2).getId();
|
||||||
session = new IntroducerSession(sessionId, groupId1,
|
boolean alice = crypto.isAlice(c1.getAuthor().getId(),
|
||||||
c1.getAuthor(), groupId2, c2.getAuthor());
|
c2.getAuthor().getId());
|
||||||
|
// use fixed deterministic roles for the introducees
|
||||||
|
session = new IntroducerSession(sessionId,
|
||||||
|
alice ? groupId1 : groupId2,
|
||||||
|
alice ? c1.getAuthor() : c2.getAuthor(),
|
||||||
|
alice ? groupId2 : groupId1,
|
||||||
|
alice ? c2.getAuthor() : c1.getAuthor()
|
||||||
|
);
|
||||||
storageId = createStorageId(txn);
|
storageId = createStorageId(txn);
|
||||||
} else {
|
} else {
|
||||||
// An earlier request exists, so we already have a session
|
// An earlier request exists, so we already have a session
|
||||||
@@ -425,10 +432,10 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
IntroducerSession session =
|
IntroducerSession session =
|
||||||
sessionParser.parseIntroducerSession(bdfSession);
|
sessionParser.parseIntroducerSession(bdfSession);
|
||||||
sessionId = session.getSessionId();
|
sessionId = session.getSessionId();
|
||||||
if (contactGroupId.equals(session.getIntroducee1().groupId)) {
|
if (contactGroupId.equals(session.getIntroduceeA().groupId)) {
|
||||||
author = session.getIntroducee2().author;
|
author = session.getIntroduceeB().author;
|
||||||
} else {
|
} else {
|
||||||
author = session.getIntroducee1().author;
|
author = session.getIntroduceeA().author;
|
||||||
}
|
}
|
||||||
} else if (role == INTRODUCEE) {
|
} else if (role == INTRODUCEE) {
|
||||||
IntroduceeSession session = sessionParser
|
IntroduceeSession session = sessionParser
|
||||||
@@ -465,10 +472,10 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
sessionParser.parseIntroducerSession(bdfSession);
|
sessionParser.parseIntroducerSession(bdfSession);
|
||||||
sessionId = session.getSessionId();
|
sessionId = session.getSessionId();
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||||
if (localAuthor.equals(session.getIntroducee1().author)) {
|
if (localAuthor.equals(session.getIntroduceeA().author)) {
|
||||||
author = session.getIntroducee2().author;
|
author = session.getIntroduceeB().author;
|
||||||
} else {
|
} else {
|
||||||
author = session.getIntroducee1().author;
|
author = session.getIntroduceeA().author;
|
||||||
}
|
}
|
||||||
} else if (role == INTRODUCEE) {
|
} else if (role == INTRODUCEE) {
|
||||||
IntroduceeSession session = sessionParser
|
IntroduceeSession session = sessionParser
|
||||||
@@ -516,12 +523,12 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
|||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
if (s.getIntroducee1().author.equals(c.getAuthor())) {
|
if (s.getIntroduceeA().author.equals(c.getAuthor())) {
|
||||||
abortOrRemoveSessionWithIntroducee(txn, s, session.getKey(),
|
abortOrRemoveSessionWithIntroducee(txn, s, session.getKey(),
|
||||||
s.getIntroducee2(), localAuthor);
|
s.getIntroduceeB(), localAuthor);
|
||||||
} else if (s.getIntroducee2().author.equals(c.getAuthor())) {
|
} else if (s.getIntroduceeB().author.equals(c.getAuthor())) {
|
||||||
abortOrRemoveSessionWithIntroducee(txn, s, session.getKey(),
|
abortOrRemoveSessionWithIntroducee(txn, s, session.getKey(),
|
||||||
s.getIntroducee1(), localAuthor);
|
s.getIntroduceeA(), localAuthor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_
|
|||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PRIVATE_KEY;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PRIVATE_KEY;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PUBLIC_KEY;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PUBLIC_KEY;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_GROUP_ID;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_GROUP_ID;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_1;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_A;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_2;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_B;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCER;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCER;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
|
||||||
@@ -72,8 +72,8 @@ class SessionEncoderImpl implements SessionEncoder {
|
|||||||
@Override
|
@Override
|
||||||
public BdfDictionary encodeIntroducerSession(IntroducerSession s) {
|
public BdfDictionary encodeIntroducerSession(IntroducerSession s) {
|
||||||
BdfDictionary d = encodeSession(s);
|
BdfDictionary d = encodeSession(s);
|
||||||
d.put(SESSION_KEY_INTRODUCEE_1, encodeIntroducee(s.getIntroducee1()));
|
d.put(SESSION_KEY_INTRODUCEE_A, encodeIntroducee(s.getIntroduceeA()));
|
||||||
d.put(SESSION_KEY_INTRODUCEE_2, encodeIntroducee(s.getIntroducee2()));
|
d.put(SESSION_KEY_INTRODUCEE_B, encodeIntroducee(s.getIntroduceeB()));
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_
|
|||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PRIVATE_KEY;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PRIVATE_KEY;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PUBLIC_KEY;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_EPHEMERAL_PUBLIC_KEY;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_GROUP_ID;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_GROUP_ID;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_1;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_A;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_2;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_B;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCER;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCER;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_REMOTE_MESSAGE_ID;
|
||||||
@@ -75,12 +75,12 @@ class SessionParserImpl implements SessionParser {
|
|||||||
SessionId sessionId = getSessionId(d);
|
SessionId sessionId = getSessionId(d);
|
||||||
IntroducerState state = IntroducerState.fromValue(getState(d));
|
IntroducerState state = IntroducerState.fromValue(getState(d));
|
||||||
long requestTimestamp = d.getLong(SESSION_KEY_REQUEST_TIMESTAMP);
|
long requestTimestamp = d.getLong(SESSION_KEY_REQUEST_TIMESTAMP);
|
||||||
Introducee introducee1 = parseIntroducee(sessionId,
|
Introducee introduceeA = parseIntroducee(sessionId,
|
||||||
d.getDictionary(SESSION_KEY_INTRODUCEE_1));
|
d.getDictionary(SESSION_KEY_INTRODUCEE_A));
|
||||||
Introducee introducee2 = parseIntroducee(sessionId,
|
Introducee introduceeB = parseIntroducee(sessionId,
|
||||||
d.getDictionary(SESSION_KEY_INTRODUCEE_2));
|
d.getDictionary(SESSION_KEY_INTRODUCEE_B));
|
||||||
return new IntroducerSession(sessionId, state, requestTimestamp,
|
return new IntroducerSession(sessionId, state, requestTimestamp,
|
||||||
introducee1, introducee2);
|
introduceeA, introduceeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Introducee parseIntroducee(SessionId sessionId, BdfDictionary d)
|
private Introducee parseIntroducee(SessionId sessionId, BdfDictionary d)
|
||||||
|
|||||||
@@ -54,11 +54,12 @@ import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT
|
|||||||
import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_VERSION;
|
import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_VERSION;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_MESSAGE_TYPE;
|
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_MESSAGE_TYPE;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_AUTHOR;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_AUTHOR;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_1;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_A;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_2;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_INTRODUCEE_B;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_LAST_LOCAL_MESSAGE_ID;
|
||||||
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_SESSION_ID;
|
import static org.briarproject.briar.introduction.IntroductionConstants.SESSION_KEY_SESSION_ID;
|
||||||
import static org.briarproject.briar.introduction.MessageType.ACCEPT;
|
import static org.briarproject.briar.introduction.MessageType.ACCEPT;
|
||||||
|
import static org.briarproject.briar.introduction.MessageType.AUTH;
|
||||||
import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount;
|
import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@@ -610,6 +611,123 @@ public class IntroductionIntegrationTest
|
|||||||
assertFalse(listener2.aborted);
|
assertFalse(listener2.aborted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One introducee illegally sends two ACCEPT messages in a row.
|
||||||
|
* The introducer should notice this and ABORT the session.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDoubleAccept() throws Exception {
|
||||||
|
addListeners(true, true);
|
||||||
|
|
||||||
|
// make the introduction
|
||||||
|
long time = clock.currentTimeMillis();
|
||||||
|
introductionManager0
|
||||||
|
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||||
|
|
||||||
|
// sync REQUEST to introducee1
|
||||||
|
sync0To1(1, true);
|
||||||
|
|
||||||
|
// save ACCEPT from introducee1
|
||||||
|
AcceptMessage m = (AcceptMessage) getMessageFor(c1.getClientHelper(),
|
||||||
|
contact0From1, ACCEPT);
|
||||||
|
|
||||||
|
// sync ACCEPT back to introducer
|
||||||
|
sync1To0(1, true);
|
||||||
|
|
||||||
|
// fake a second ACCEPT message from introducee1
|
||||||
|
Message msg = c1.getMessageEncoder()
|
||||||
|
.encodeAcceptMessage(m.getGroupId(), clock.currentTimeMillis(),
|
||||||
|
m.getMessageId(), m.getSessionId(),
|
||||||
|
m.getEphemeralPublicKey(), m.getAcceptTimestamp(),
|
||||||
|
m.getTransportProperties());
|
||||||
|
c1.getClientHelper().addLocalMessage(msg, new BdfDictionary(), true);
|
||||||
|
|
||||||
|
// sync fake ACCEPT back to introducer
|
||||||
|
sync1To0(1, true);
|
||||||
|
|
||||||
|
assertTrue(listener0.aborted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One introducee sends an ACCEPT and then another DECLINE message.
|
||||||
|
* The introducer should notice this and ABORT the session.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAcceptAndDecline() throws Exception {
|
||||||
|
addListeners(true, true);
|
||||||
|
|
||||||
|
// make the introduction
|
||||||
|
long time = clock.currentTimeMillis();
|
||||||
|
introductionManager0
|
||||||
|
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||||
|
|
||||||
|
// sync REQUEST to introducee1
|
||||||
|
sync0To1(1, true);
|
||||||
|
|
||||||
|
// save ACCEPT from introducee1
|
||||||
|
AcceptMessage m = (AcceptMessage) getMessageFor(c1.getClientHelper(),
|
||||||
|
contact0From1, ACCEPT);
|
||||||
|
|
||||||
|
// sync ACCEPT back to introducer
|
||||||
|
sync1To0(1, true);
|
||||||
|
|
||||||
|
// fake a second DECLINE message also from introducee1
|
||||||
|
Message msg = c1.getMessageEncoder()
|
||||||
|
.encodeDeclineMessage(m.getGroupId(), clock.currentTimeMillis(),
|
||||||
|
m.getMessageId(), m.getSessionId());
|
||||||
|
c1.getClientHelper().addLocalMessage(msg, new BdfDictionary(), true);
|
||||||
|
|
||||||
|
// sync fake DECLINE back to introducer
|
||||||
|
sync1To0(1, true);
|
||||||
|
|
||||||
|
assertTrue(listener0.aborted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One introducee sends two AUTH messages.
|
||||||
|
* The introducer should notice this and ABORT the session.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDoubleAuth() throws Exception {
|
||||||
|
addListeners(true, true);
|
||||||
|
|
||||||
|
// make the introduction
|
||||||
|
long time = clock.currentTimeMillis();
|
||||||
|
introductionManager0
|
||||||
|
.makeIntroduction(contact1From0, contact2From0, null, time);
|
||||||
|
|
||||||
|
// sync REQUEST messages
|
||||||
|
sync0To1(1, true);
|
||||||
|
sync0To2(1, true);
|
||||||
|
|
||||||
|
// sync ACCEPT messages
|
||||||
|
sync1To0(1, true);
|
||||||
|
sync2To0(1, true);
|
||||||
|
|
||||||
|
// sync forwarded ACCEPT messages to introducees
|
||||||
|
sync0To1(1, true);
|
||||||
|
sync0To2(1, true);
|
||||||
|
|
||||||
|
// save AUTH from introducee1
|
||||||
|
AuthMessage m = (AuthMessage) getMessageFor(c1.getClientHelper(),
|
||||||
|
contact0From1, AUTH);
|
||||||
|
|
||||||
|
// sync first AUTH message
|
||||||
|
sync1To0(1, true);
|
||||||
|
|
||||||
|
// fake a second AUTH message also from introducee1
|
||||||
|
Message msg = c1.getMessageEncoder()
|
||||||
|
.encodeAuthMessage(m.getGroupId(), clock.currentTimeMillis(),
|
||||||
|
m.getMessageId(), m.getSessionId(), m.getMac(),
|
||||||
|
m.getSignature());
|
||||||
|
c1.getClientHelper().addLocalMessage(msg, new BdfDictionary(), true);
|
||||||
|
|
||||||
|
// sync second AUTH message
|
||||||
|
sync1To0(1, true);
|
||||||
|
|
||||||
|
assertTrue(listener0.aborted);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIntroducerRemovedCleanup() throws Exception {
|
public void testIntroducerRemovedCleanup() throws Exception {
|
||||||
addListeners(true, true);
|
addListeners(true, true);
|
||||||
@@ -955,8 +1073,8 @@ public class IntroductionIntegrationTest
|
|||||||
|
|
||||||
private void replacePreviousLocalMessageId(Author author,
|
private void replacePreviousLocalMessageId(Author author,
|
||||||
BdfDictionary d, MessageId id) throws FormatException {
|
BdfDictionary d, MessageId id) throws FormatException {
|
||||||
BdfDictionary i1 = d.getDictionary(SESSION_KEY_INTRODUCEE_1);
|
BdfDictionary i1 = d.getDictionary(SESSION_KEY_INTRODUCEE_A);
|
||||||
BdfDictionary i2 = d.getDictionary(SESSION_KEY_INTRODUCEE_2);
|
BdfDictionary i2 = d.getDictionary(SESSION_KEY_INTRODUCEE_B);
|
||||||
Author a1 = clientHelper
|
Author a1 = clientHelper
|
||||||
.parseAndValidateAuthor(i1.getList(SESSION_KEY_AUTHOR));
|
.parseAndValidateAuthor(i1.getList(SESSION_KEY_AUTHOR));
|
||||||
Author a2 = clientHelper
|
Author a2 = clientHelper
|
||||||
@@ -964,10 +1082,10 @@ public class IntroductionIntegrationTest
|
|||||||
|
|
||||||
if (a1.equals(author)) {
|
if (a1.equals(author)) {
|
||||||
i1.put(SESSION_KEY_LAST_LOCAL_MESSAGE_ID, id);
|
i1.put(SESSION_KEY_LAST_LOCAL_MESSAGE_ID, id);
|
||||||
d.put(SESSION_KEY_INTRODUCEE_1, i1);
|
d.put(SESSION_KEY_INTRODUCEE_A, i1);
|
||||||
} else if (a2.equals(author)) {
|
} else if (a2.equals(author)) {
|
||||||
i2.put(SESSION_KEY_LAST_LOCAL_MESSAGE_ID, id);
|
i2.put(SESSION_KEY_LAST_LOCAL_MESSAGE_ID, id);
|
||||||
d.put(SESSION_KEY_INTRODUCEE_2, i2);
|
d.put(SESSION_KEY_INTRODUCEE_B, i2);
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -986,8 +1104,13 @@ public class IntroductionIntegrationTest
|
|||||||
MessageId id = map.entrySet().iterator().next().getKey();
|
MessageId id = map.entrySet().iterator().next().getKey();
|
||||||
Message m = ch.getMessage(id);
|
Message m = ch.getMessage(id);
|
||||||
BdfList body = ch.getMessageAsList(id);
|
BdfList body = ch.getMessageAsList(id);
|
||||||
//noinspection ConstantConditions
|
if (type == ACCEPT) {
|
||||||
return c0.getMessageParser().parseAcceptMessage(m, body);
|
//noinspection ConstantConditions
|
||||||
|
return c0.getMessageParser().parseAcceptMessage(m, body);
|
||||||
|
} else if (type == AUTH) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return c0.getMessageParser().parseAuthMessage(m, body);
|
||||||
|
} else throw new AssertionError("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntroductionRequest getIntroductionRequest(
|
private IntroductionRequest getIntroductionRequest(
|
||||||
@@ -1002,6 +1125,15 @@ public class IntroductionIntegrationTest
|
|||||||
throw new AssertionError("No IntroductionRequest found");
|
throw new AssertionError("No IntroductionRequest found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IntroducerSession getIntroducerSession()
|
||||||
|
throws DbException, FormatException {
|
||||||
|
Map<MessageId, BdfDictionary> dicts = c0.getClientHelper()
|
||||||
|
.getMessageMetadataAsDictionary(getLocalGroup().getId());
|
||||||
|
assertEquals(1, dicts.size());
|
||||||
|
BdfDictionary d = dicts.values().iterator().next();
|
||||||
|
return c0.getSessionParser().parseIntroducerSession(d);
|
||||||
|
}
|
||||||
|
|
||||||
private IntroduceeSession getIntroduceeSession(ClientHelper ch,
|
private IntroduceeSession getIntroduceeSession(ClientHelper ch,
|
||||||
GroupId introducerGroup) throws DbException, FormatException {
|
GroupId introducerGroup) throws DbException, FormatException {
|
||||||
Map<MessageId, BdfDictionary> dicts =
|
Map<MessageId, BdfDictionary> dicts =
|
||||||
|
|||||||
@@ -102,8 +102,8 @@ public class SessionEncoderParserIntegrationTest extends BrambleTestCase {
|
|||||||
assertEquals(s1.getSessionId(), s2.getSessionId());
|
assertEquals(s1.getSessionId(), s2.getSessionId());
|
||||||
assertEquals(AWAIT_AUTHS, s1.getState());
|
assertEquals(AWAIT_AUTHS, s1.getState());
|
||||||
assertEquals(s1.getState(), s2.getState());
|
assertEquals(s1.getState(), s2.getState());
|
||||||
assertIntroduceeEquals(s1.getIntroducee1(), s2.getIntroducee1());
|
assertIntroduceeEquals(s1.getIntroduceeA(), s2.getIntroduceeA());
|
||||||
assertIntroduceeEquals(s1.getIntroducee2(), s2.getIntroducee2());
|
assertIntroduceeEquals(s1.getIntroduceeB(), s2.getIntroduceeB());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -121,19 +121,19 @@ public class SessionEncoderParserIntegrationTest extends BrambleTestCase {
|
|||||||
BdfDictionary d = sessionEncoder.encodeIntroducerSession(s1);
|
BdfDictionary d = sessionEncoder.encodeIntroducerSession(s1);
|
||||||
IntroducerSession s2 = sessionParser.parseIntroducerSession(d);
|
IntroducerSession s2 = sessionParser.parseIntroducerSession(d);
|
||||||
|
|
||||||
assertNull(s1.getIntroducee1().lastLocalMessageId);
|
assertNull(s1.getIntroduceeA().lastLocalMessageId);
|
||||||
assertEquals(s1.getIntroducee1().lastLocalMessageId,
|
assertEquals(s1.getIntroduceeA().lastLocalMessageId,
|
||||||
s2.getIntroducee1().lastLocalMessageId);
|
s2.getIntroduceeA().lastLocalMessageId);
|
||||||
assertNull(s1.getIntroducee1().lastRemoteMessageId);
|
assertNull(s1.getIntroduceeA().lastRemoteMessageId);
|
||||||
assertEquals(s1.getIntroducee1().lastRemoteMessageId,
|
assertEquals(s1.getIntroduceeA().lastRemoteMessageId,
|
||||||
s2.getIntroducee1().lastRemoteMessageId);
|
s2.getIntroduceeA().lastRemoteMessageId);
|
||||||
|
|
||||||
assertNull(s1.getIntroducee2().lastLocalMessageId);
|
assertNull(s1.getIntroduceeB().lastLocalMessageId);
|
||||||
assertEquals(s1.getIntroducee2().lastLocalMessageId,
|
assertEquals(s1.getIntroduceeB().lastLocalMessageId,
|
||||||
s2.getIntroducee2().lastLocalMessageId);
|
s2.getIntroduceeB().lastLocalMessageId);
|
||||||
assertNull(s1.getIntroducee2().lastRemoteMessageId);
|
assertNull(s1.getIntroduceeB().lastRemoteMessageId);
|
||||||
assertEquals(s1.getIntroducee2().lastRemoteMessageId,
|
assertEquals(s1.getIntroduceeB().lastRemoteMessageId,
|
||||||
s2.getIntroducee2().lastRemoteMessageId);
|
s2.getIntroduceeB().lastRemoteMessageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user