mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Address first round of review comments for new IntroductionClient
This commit is contained in:
@@ -8,7 +8,6 @@ import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
// TODO still needed?
|
||||
public class IntroductionSucceededEvent extends Event {
|
||||
|
||||
private final Contact contact;
|
||||
|
||||
@@ -57,19 +57,14 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
|
||||
public boolean incomingMessage(Transaction txn, Message m, Metadata meta)
|
||||
throws DbException, InvalidMessageException {
|
||||
try {
|
||||
return incomingMessage(txn, m, meta, MESSAGE_HEADER_LENGTH);
|
||||
byte[] raw = m.getRaw();
|
||||
BdfList body = clientHelper.toList(raw, MESSAGE_HEADER_LENGTH,
|
||||
raw.length - MESSAGE_HEADER_LENGTH);
|
||||
BdfDictionary metaDictionary = metadataParser.parse(meta);
|
||||
return incomingMessage(txn, m, body, metaDictionary);
|
||||
} catch (FormatException e) {
|
||||
throw new InvalidMessageException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean incomingMessage(Transaction txn, Message m, Metadata meta,
|
||||
int headerLength) throws DbException, FormatException {
|
||||
byte[] raw = m.getRaw();
|
||||
BdfList body = clientHelper.toList(raw, headerLength,
|
||||
raw.length - headerLength);
|
||||
BdfDictionary metaDictionary = metadataParser.parse(meta);
|
||||
return incomingMessage(txn, m, body, metaDictionary);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
@@ -25,8 +24,6 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_ID;
|
||||
import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_VERSION;
|
||||
import static org.briarproject.briar.introduction.MessageType.ABORT;
|
||||
import static org.briarproject.briar.introduction.MessageType.ACCEPT;
|
||||
import static org.briarproject.briar.introduction.MessageType.ACTIVATE;
|
||||
@@ -155,28 +152,6 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
}
|
||||
}
|
||||
|
||||
void markRequestUnavailableToAnswer(Transaction txn, MessageId m)
|
||||
throws DbException {
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
messageEncoder.setAvailableToAnswer(meta, false);
|
||||
try {
|
||||
clientHelper.mergeMessageMetadata(txn, m, meta);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
Map<MessageId, BdfDictionary> getSessions(Transaction txn,
|
||||
BdfDictionary query) throws DbException, FormatException {
|
||||
return clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, getLocalGroup().getId(),
|
||||
query);
|
||||
}
|
||||
|
||||
private Group getLocalGroup() {
|
||||
return contactGroupFactory.createLocalGroup(CLIENT_ID, CLIENT_VERSION);
|
||||
}
|
||||
|
||||
boolean isInvalidDependency(@Nullable MessageId lastRemoteMessageId,
|
||||
@Nullable MessageId dependency) {
|
||||
if (dependency == null) return lastRemoteMessageId != null;
|
||||
|
||||
@@ -124,8 +124,7 @@ class IntroduceeProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroduceeSession onRequestMessage(Transaction txn,
|
||||
IntroduceeSession session, RequestMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroduceeSession session, RequestMessage m) throws DbException {
|
||||
switch (session.getState()) {
|
||||
case START:
|
||||
return onRemoteRequest(txn, session, m);
|
||||
@@ -143,8 +142,7 @@ class IntroduceeProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroduceeSession onAcceptMessage(Transaction txn,
|
||||
IntroduceeSession session, AcceptMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroduceeSession session, AcceptMessage m) throws DbException {
|
||||
switch (session.getState()) {
|
||||
case START:
|
||||
return onRemoteResponseInStart(txn, session, m);
|
||||
@@ -163,8 +161,7 @@ class IntroduceeProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroduceeSession onDeclineMessage(Transaction txn,
|
||||
IntroduceeSession session, DeclineMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroduceeSession session, DeclineMessage m) throws DbException {
|
||||
switch (session.getState()) {
|
||||
case START:
|
||||
return onRemoteResponseInStart(txn, session, m);
|
||||
@@ -183,8 +180,7 @@ class IntroduceeProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroduceeSession onAuthMessage(Transaction txn,
|
||||
IntroduceeSession session, AuthMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroduceeSession session, AuthMessage m) throws DbException {
|
||||
switch (session.getState()) {
|
||||
case AWAIT_AUTH:
|
||||
return onRemoteAuth(txn, session, m);
|
||||
@@ -202,8 +198,7 @@ class IntroduceeProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroduceeSession onActivateMessage(Transaction txn,
|
||||
IntroduceeSession session, ActivateMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroduceeSession session, ActivateMessage m) throws DbException {
|
||||
switch (session.getState()) {
|
||||
case AWAIT_ACTIVATE:
|
||||
return onRemoteActivate(txn, session, m);
|
||||
@@ -221,8 +216,7 @@ class IntroduceeProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroduceeSession onAbortMessage(Transaction txn,
|
||||
IntroduceeSession session, AbortMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroduceeSession session, AbortMessage m) throws DbException {
|
||||
return onRemoteAbort(txn, session, m);
|
||||
}
|
||||
|
||||
@@ -232,8 +226,9 @@ class IntroduceeProtocolEngine
|
||||
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
||||
return abort(txn, s);
|
||||
|
||||
// Mark the request visible in the UI
|
||||
// Mark the request visible in the UI and available to answer
|
||||
markMessageVisibleInUi(txn, m.getMessageId());
|
||||
markRequestAvailableToAnswer(txn, m.getMessageId(), true);
|
||||
|
||||
// Add SessionId to message metadata
|
||||
addSessionId(txn, m.getMessageId(), s.getSessionId());
|
||||
@@ -243,9 +238,11 @@ class IntroduceeProtocolEngine
|
||||
.trackMessage(txn, m.getGroupId(), m.getTimestamp(), false);
|
||||
|
||||
// Broadcast IntroductionRequestReceivedEvent
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||
Contact c = contactManager.getContact(txn, s.getIntroducer().getId(),
|
||||
identityManager.getLocalAuthor(txn).getId());
|
||||
boolean contactExists = false; // TODO
|
||||
localAuthor.getId());
|
||||
boolean contactExists = contactManager
|
||||
.contactExists(txn, m.getAuthor().getId(), localAuthor.getId());
|
||||
IntroductionRequest request =
|
||||
new IntroductionRequest(s.getSessionId(), m.getMessageId(),
|
||||
m.getGroupId(), INTRODUCEE, m.getTimestamp(), false,
|
||||
@@ -260,11 +257,10 @@ class IntroduceeProtocolEngine
|
||||
}
|
||||
|
||||
private IntroduceeSession onLocalAccept(Transaction txn,
|
||||
IntroduceeSession s, long timestamp) throws DbException {
|
||||
IntroduceeSession s, long timestamp)
|
||||
throws DbException {
|
||||
// Mark the request message unavailable to answer
|
||||
MessageId requestId = s.getLastRemoteMessageId();
|
||||
if (requestId == null) throw new IllegalStateException();
|
||||
markRequestUnavailableToAnswer(txn, requestId);
|
||||
markRequestsUnavailableToAnswer(txn, s);
|
||||
|
||||
// Create ephemeral key pair and get local transport properties
|
||||
KeyPair keyPair = crypto.generateKeyPair();
|
||||
@@ -275,7 +271,7 @@ class IntroduceeProtocolEngine
|
||||
|
||||
// Send a ACCEPT message
|
||||
long localTimestamp =
|
||||
Math.max(timestamp, getLocalTimestamp(s));
|
||||
Math.max(timestamp + 1, getLocalTimestamp(s));
|
||||
Message sent = sendAcceptMessage(txn, s, localTimestamp, publicKey,
|
||||
localTimestamp, transportProperties, true);
|
||||
// Track the message
|
||||
@@ -297,14 +293,13 @@ class IntroduceeProtocolEngine
|
||||
}
|
||||
|
||||
private IntroduceeSession onLocalDecline(Transaction txn,
|
||||
IntroduceeSession s, long timestamp) throws DbException {
|
||||
IntroduceeSession s, long timestamp)
|
||||
throws DbException {
|
||||
// Mark the request message unavailable to answer
|
||||
MessageId requestId = s.getLastRemoteMessageId();
|
||||
if (requestId == null) throw new IllegalStateException();
|
||||
markRequestUnavailableToAnswer(txn, requestId);
|
||||
markRequestsUnavailableToAnswer(txn, s);
|
||||
|
||||
// Send a DECLINE message
|
||||
long localTimestamp = Math.max(timestamp, getLocalTimestamp(s));
|
||||
long localTimestamp = Math.max(timestamp + 1, getLocalTimestamp(s));
|
||||
Message sent = sendDeclineMessage(txn, s, localTimestamp, true);
|
||||
// Track the message
|
||||
messageTracker.trackOutgoingMessage(txn, sent);
|
||||
@@ -316,7 +311,7 @@ class IntroduceeProtocolEngine
|
||||
|
||||
private IntroduceeSession onRemoteAccept(Transaction txn,
|
||||
IntroduceeSession s, AcceptMessage m)
|
||||
throws DbException, FormatException {
|
||||
throws DbException {
|
||||
// The timestamp must be higher than the last request message
|
||||
if (m.getTimestamp() <= s.getRequestTimestamp())
|
||||
return abort(txn, s);
|
||||
@@ -346,7 +341,7 @@ class IntroduceeProtocolEngine
|
||||
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
||||
return abort(txn, s);
|
||||
|
||||
// Mark the request visible in the UI
|
||||
// Mark the response visible in the UI
|
||||
markMessageVisibleInUi(txn, m.getMessageId());
|
||||
|
||||
// Track the incoming message
|
||||
@@ -401,8 +396,6 @@ class IntroduceeProtocolEngine
|
||||
} catch (GeneralSecurityException e) {
|
||||
// TODO
|
||||
return abort(txn, s);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
if (s.getState() != AWAIT_AUTH) throw new AssertionError();
|
||||
Message sent = sendAuthMessage(txn, s, getLocalTimestamp(s), mac,
|
||||
@@ -411,8 +404,7 @@ class IntroduceeProtocolEngine
|
||||
}
|
||||
|
||||
private IntroduceeSession onRemoteAuth(Transaction txn,
|
||||
IntroduceeSession s, AuthMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroduceeSession s, AuthMessage m) throws DbException {
|
||||
// The dependency, if any, must be the last remote message
|
||||
if (isInvalidDependency(s, m.getPreviousMessageId()))
|
||||
return abort(txn, s);
|
||||
@@ -479,9 +471,7 @@ class IntroduceeProtocolEngine
|
||||
IntroduceeSession s, AbortMessage m)
|
||||
throws DbException {
|
||||
// Mark the request message unavailable to answer
|
||||
MessageId requestId = s.getLastRemoteMessageId();
|
||||
if (requestId == null) throw new IllegalStateException();
|
||||
markRequestUnavailableToAnswer(txn, requestId);
|
||||
markRequestsUnavailableToAnswer(txn, s);
|
||||
|
||||
// Broadcast abort event for testing
|
||||
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
||||
@@ -495,9 +485,7 @@ class IntroduceeProtocolEngine
|
||||
private IntroduceeSession abort(Transaction txn, IntroduceeSession s)
|
||||
throws DbException {
|
||||
// Mark the request message unavailable to answer
|
||||
MessageId requestId = s.getLastRemoteMessageId();
|
||||
if (requestId == null) throw new IllegalStateException();
|
||||
markRequestUnavailableToAnswer(txn, requestId);
|
||||
markRequestsUnavailableToAnswer(txn, s);
|
||||
|
||||
// Send an ABORT message
|
||||
Message sent = sendAbortMessage(txn, s, getLocalTimestamp(s));
|
||||
@@ -537,4 +525,30 @@ class IntroduceeProtocolEngine
|
||||
}
|
||||
}
|
||||
|
||||
private void markRequestsUnavailableToAnswer(Transaction txn,
|
||||
IntroduceeSession s) throws DbException {
|
||||
BdfDictionary query = messageParser
|
||||
.getRequestsAvailableToAnswerQuery(s.getSessionId());
|
||||
try {
|
||||
Map<MessageId, BdfDictionary> results =
|
||||
clientHelper.getMessageMetadataAsDictionary(txn,
|
||||
s.getContactGroupId(), query);
|
||||
for (MessageId m : results.keySet())
|
||||
markRequestAvailableToAnswer(txn, m, false);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void markRequestAvailableToAnswer(Transaction txn, MessageId m,
|
||||
boolean available) throws DbException {
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
messageEncoder.setAvailableToAnswer(meta, available);
|
||||
try {
|
||||
clientHelper.mergeMessageMetadata(txn, m, meta);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package org.briarproject.briar.introduction;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
@@ -23,8 +21,6 @@ import org.briarproject.briar.api.introduction.event.IntroductionAbortedEvent;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
|
||||
import org.briarproject.briar.introduction.IntroducerSession.Introducee;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
@@ -97,21 +93,19 @@ class IntroducerProtocolEngine
|
||||
}
|
||||
|
||||
IntroducerSession onAbortAction(Transaction txn, IntroducerSession s)
|
||||
throws DbException, FormatException {
|
||||
throws DbException {
|
||||
return abort(txn, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntroducerSession onRequestMessage(Transaction txn,
|
||||
IntroducerSession s, RequestMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroducerSession s, RequestMessage m) throws DbException {
|
||||
return abort(txn, s); // Invalid in this role
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntroducerSession onAcceptMessage(Transaction txn,
|
||||
IntroducerSession s, AcceptMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroducerSession s, AcceptMessage m) throws DbException {
|
||||
switch (s.getState()) {
|
||||
case AWAIT_RESPONSES:
|
||||
case AWAIT_RESPONSE_A:
|
||||
@@ -133,8 +127,7 @@ class IntroducerProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroducerSession onDeclineMessage(Transaction txn,
|
||||
IntroducerSession s, DeclineMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroducerSession s, DeclineMessage m) throws DbException {
|
||||
switch (s.getState()) {
|
||||
case AWAIT_RESPONSES:
|
||||
case AWAIT_RESPONSE_A:
|
||||
@@ -156,7 +149,7 @@ class IntroducerProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroducerSession onAuthMessage(Transaction txn, IntroducerSession s,
|
||||
AuthMessage m) throws DbException, FormatException {
|
||||
AuthMessage m) throws DbException {
|
||||
switch (s.getState()) {
|
||||
case AWAIT_AUTHS:
|
||||
case AWAIT_AUTH_A:
|
||||
@@ -177,8 +170,7 @@ class IntroducerProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroducerSession onActivateMessage(Transaction txn,
|
||||
IntroducerSession s, ActivateMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroducerSession s, ActivateMessage m) throws DbException {
|
||||
switch (s.getState()) {
|
||||
case AWAIT_ACTIVATES:
|
||||
case AWAIT_ACTIVATE_A:
|
||||
@@ -199,8 +191,7 @@ class IntroducerProtocolEngine
|
||||
|
||||
@Override
|
||||
public IntroducerSession onAbortMessage(Transaction txn,
|
||||
IntroducerSession s, AbortMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroducerSession s, AbortMessage m) throws DbException {
|
||||
return onRemoteAbort(txn, s, m);
|
||||
}
|
||||
|
||||
@@ -227,8 +218,7 @@ class IntroducerProtocolEngine
|
||||
}
|
||||
|
||||
private IntroducerSession onRemoteAccept(Transaction txn,
|
||||
IntroducerSession s, AcceptMessage m)
|
||||
throws DbException, FormatException {
|
||||
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);
|
||||
@@ -284,8 +274,7 @@ class IntroducerProtocolEngine
|
||||
}
|
||||
|
||||
private IntroducerSession onRemoteDecline(Transaction txn,
|
||||
IntroducerSession s, DeclineMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroducerSession s, DeclineMessage m) throws DbException {
|
||||
// The timestamp must be higher than the last request message
|
||||
if (m.getTimestamp() <= s.getRequestTimestamp())
|
||||
return abort(txn, s);
|
||||
@@ -337,7 +326,7 @@ class IntroducerProtocolEngine
|
||||
|
||||
private IntroducerSession onRemoteResponseInStart(Transaction txn,
|
||||
IntroducerSession s, AbstractIntroductionMessage m)
|
||||
throws DbException, FormatException {
|
||||
throws DbException {
|
||||
// The timestamp must be higher than the last request message
|
||||
if (m.getTimestamp() <= s.getRequestTimestamp())
|
||||
return abort(txn, s);
|
||||
@@ -384,8 +373,7 @@ class IntroducerProtocolEngine
|
||||
}
|
||||
|
||||
private IntroducerSession onRemoteAuth(Transaction txn,
|
||||
IntroducerSession s, AuthMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroducerSession s, AuthMessage m) throws DbException {
|
||||
// The dependency, if any, must be the last remote message
|
||||
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
||||
return abort(txn, s);
|
||||
@@ -413,8 +401,7 @@ class IntroducerProtocolEngine
|
||||
}
|
||||
|
||||
private IntroducerSession onRemoteActivate(Transaction txn,
|
||||
IntroducerSession s, ActivateMessage m)
|
||||
throws DbException, FormatException {
|
||||
IntroducerSession s, ActivateMessage m) throws DbException {
|
||||
// The dependency, if any, must be the last remote message
|
||||
if (isInvalidDependency(s, m.getGroupId(), m.getPreviousMessageId()))
|
||||
return abort(txn, s);
|
||||
@@ -441,11 +428,7 @@ class IntroducerProtocolEngine
|
||||
}
|
||||
|
||||
private IntroducerSession onRemoteAbort(Transaction txn,
|
||||
IntroducerSession s, AbortMessage m)
|
||||
throws DbException, FormatException {
|
||||
// Mark any REQUEST messages in the session unavailable to answer
|
||||
markRequestsUnavailableToAnswer(txn, s);
|
||||
|
||||
IntroducerSession s, AbortMessage m) throws DbException {
|
||||
// Forward ABORT message
|
||||
Introducee i = getOtherIntroducee(s, m.getGroupId());
|
||||
long timestamp = getLocalTimestamp(s, i);
|
||||
@@ -468,10 +451,7 @@ class IntroducerProtocolEngine
|
||||
}
|
||||
|
||||
private IntroducerSession abort(Transaction txn,
|
||||
IntroducerSession s) throws DbException, FormatException {
|
||||
// Mark any REQUEST messages in the session unavailable to answer
|
||||
markRequestsUnavailableToAnswer(txn, s);
|
||||
|
||||
IntroducerSession s) throws DbException {
|
||||
// Broadcast abort event for testing
|
||||
txn.attach(new IntroductionAbortedEvent(s.getSessionId()));
|
||||
|
||||
@@ -487,15 +467,6 @@ class IntroducerProtocolEngine
|
||||
s.getRequestTimestamp(), introducee1, introducee2);
|
||||
}
|
||||
|
||||
private void markRequestsUnavailableToAnswer(Transaction txn, Session s)
|
||||
throws DbException, FormatException {
|
||||
BdfDictionary query = messageParser
|
||||
.getInvitesAvailableToAnswerQuery(s.getSessionId());
|
||||
Map<MessageId, BdfDictionary> results = getSessions(txn, query);
|
||||
for (MessageId m : results.keySet())
|
||||
markRequestUnavailableToAnswer(txn, m);
|
||||
}
|
||||
|
||||
private Introducee getIntroducee(IntroducerSession s, GroupId g) {
|
||||
if (s.getIntroducee1().groupId.equals(g)) return s.getIntroducee1();
|
||||
else if (s.getIntroducee2().groupId.equals(g))
|
||||
|
||||
@@ -12,7 +12,6 @@ interface IntroductionConstants {
|
||||
String MSG_KEY_LOCAL = "local";
|
||||
String MSG_KEY_VISIBLE_IN_UI = "visibleInUi";
|
||||
String MSG_KEY_AVAILABLE_TO_ANSWER = "availableToAnswer";
|
||||
String MSG_KEY_INVITATION_ACCEPTED = "invitationAccepted";
|
||||
|
||||
// Session Keys
|
||||
String SESSION_KEY_SESSION_ID = "sessionId";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.briar.introduction;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
@@ -15,15 +14,13 @@ interface IntroductionCrypto {
|
||||
/**
|
||||
* Returns the {@link SessionId} based on the introducer
|
||||
* and the two introducees.
|
||||
*
|
||||
* Note: The roles of Alice and Bob can be switched.
|
||||
*/
|
||||
SessionId getSessionId(Author introducer, Author alice, Author bob);
|
||||
SessionId getSessionId(Author introducer, Author local, Author remote);
|
||||
|
||||
/**
|
||||
* Returns true if the first author is indeed alice
|
||||
* Returns true if the local author is alice
|
||||
*/
|
||||
boolean isAlice(AuthorId alice, AuthorId bob);
|
||||
boolean isAlice(AuthorId local, AuthorId remote);
|
||||
|
||||
/**
|
||||
* Generates an agreement key pair.
|
||||
@@ -49,11 +46,11 @@ interface IntroductionCrypto {
|
||||
SecretKey deriveMacKey(SecretKey masterKey, boolean alice);
|
||||
|
||||
/**
|
||||
* Generates a MAC that covers both introducee's ephemeral public keys and
|
||||
* transport properties.
|
||||
* Generates a MAC that covers both introducee's ephemeral public keys,
|
||||
* transport properties, Author IDs and timestamps of the accept message.
|
||||
*/
|
||||
byte[] mac(SecretKey macKey, IntroduceeSession s, AuthorId localAuthorId,
|
||||
boolean alice) throws FormatException;
|
||||
boolean alice);
|
||||
|
||||
/**
|
||||
* Verifies a received MAC
|
||||
@@ -63,7 +60,7 @@ interface IntroductionCrypto {
|
||||
* @throws GeneralSecurityException if the verification fails
|
||||
*/
|
||||
void verifyMac(byte[] mac, IntroduceeSession s, AuthorId localAuthorId)
|
||||
throws GeneralSecurityException, FormatException;
|
||||
throws GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Signs a nonce derived from the macKey
|
||||
|
||||
@@ -18,7 +18,6 @@ import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
@@ -49,14 +48,14 @@ class IntroductionCryptoImpl implements IntroductionCrypto {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionId getSessionId(Author introducer, Author alice,
|
||||
Author bob) {
|
||||
boolean isAlice = isAlice(alice.getId(), bob.getId());
|
||||
public SessionId getSessionId(Author introducer, Author local,
|
||||
Author remote) {
|
||||
boolean isAlice = isAlice(local.getId(), remote.getId());
|
||||
byte[] hash = crypto.hash(
|
||||
LABEL_SESSION_ID,
|
||||
introducer.getId().getBytes(),
|
||||
isAlice ? alice.getId().getBytes() : bob.getId().getBytes(),
|
||||
isAlice ? bob.getId().getBytes() : alice.getId().getBytes()
|
||||
isAlice ? local.getId().getBytes() : remote.getId().getBytes(),
|
||||
isAlice ? remote.getId().getBytes() : local.getId().getBytes()
|
||||
);
|
||||
return new SessionId(hash);
|
||||
}
|
||||
@@ -67,9 +66,9 @@ class IntroductionCryptoImpl implements IntroductionCrypto {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlice(AuthorId alice, AuthorId bob) {
|
||||
byte[] a = alice.getBytes();
|
||||
byte[] b = bob.getBytes();
|
||||
public boolean isAlice(AuthorId local, AuthorId remote) {
|
||||
byte[] a = local.getBytes();
|
||||
byte[] b = remote.getBytes();
|
||||
return Bytes.COMPARATOR.compare(new Bytes(a), new Bytes(b)) < 0;
|
||||
}
|
||||
|
||||
@@ -110,7 +109,7 @@ class IntroductionCryptoImpl implements IntroductionCrypto {
|
||||
@Override
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public byte[] mac(SecretKey macKey, IntroduceeSession s,
|
||||
AuthorId localAuthorId, boolean alice) throws FormatException {
|
||||
AuthorId localAuthorId, boolean alice) {
|
||||
return mac(macKey, s.getIntroducer().getId(), localAuthorId,
|
||||
s.getRemoteAuthor().getId(), s.getAcceptTimestamp(),
|
||||
s.getRemoteAcceptTimestamp(), s.getEphemeralPublicKey(),
|
||||
@@ -124,7 +123,59 @@ class IntroductionCryptoImpl implements IntroductionCrypto {
|
||||
byte[] ephemeralPublicKey, byte[] remoteEphemeralPublicKey,
|
||||
Map<TransportId, TransportProperties> transportProperties,
|
||||
Map<TransportId, TransportProperties> remoteTransportProperties,
|
||||
boolean alice) throws FormatException {
|
||||
boolean alice) {
|
||||
byte[] inputs =
|
||||
getMacInputs(introducerId, localAuthorId, remoteAuthorId,
|
||||
acceptTimestamp, remoteAcceptTimestamp,
|
||||
ephemeralPublicKey, remoteEphemeralPublicKey,
|
||||
transportProperties, remoteTransportProperties, alice);
|
||||
return crypto.mac(
|
||||
LABEL_AUTH_MAC,
|
||||
macKey,
|
||||
inputs
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void verifyMac(byte[] mac, IntroduceeSession s,
|
||||
AuthorId localAuthorId)
|
||||
throws GeneralSecurityException {
|
||||
boolean alice = isAlice(localAuthorId, s.getRemoteAuthor().getId());
|
||||
verifyMac(mac, new SecretKey(s.getMasterKey()),
|
||||
s.getIntroducer().getId(), localAuthorId,
|
||||
s.getRemoteAuthor().getId(), s.getAcceptTimestamp(),
|
||||
s.getRemoteAcceptTimestamp(), s.getEphemeralPublicKey(),
|
||||
s.getRemotePublicKey(), s.getTransportProperties(),
|
||||
s.getRemoteTransportProperties(), !alice);
|
||||
}
|
||||
|
||||
void verifyMac(byte[] mac, SecretKey masterKey,
|
||||
AuthorId introducerId, AuthorId localAuthorId,
|
||||
AuthorId remoteAuthorId, long acceptTimestamp,
|
||||
long remoteAcceptTimestamp, byte[] ephemeralPublicKey,
|
||||
byte[] remoteEphemeralPublicKey,
|
||||
Map<TransportId, TransportProperties> transportProperties,
|
||||
Map<TransportId, TransportProperties> remoteTransportProperties,
|
||||
boolean alice) throws GeneralSecurityException {
|
||||
SecretKey macKey = deriveMacKey(masterKey, alice);
|
||||
byte[] inputs =
|
||||
getMacInputs(introducerId, localAuthorId, remoteAuthorId,
|
||||
acceptTimestamp, remoteAcceptTimestamp,
|
||||
ephemeralPublicKey, remoteEphemeralPublicKey,
|
||||
transportProperties, remoteTransportProperties, !alice);
|
||||
if (!crypto.verifyMac(mac, LABEL_AUTH_MAC, macKey, inputs)) {
|
||||
throw new GeneralSecurityException();
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getMacInputs(AuthorId introducerId,
|
||||
AuthorId localAuthorId, AuthorId remoteAuthorId,
|
||||
long acceptTimestamp, long remoteAcceptTimestamp,
|
||||
byte[] ephemeralPublicKey, byte[] remoteEphemeralPublicKey,
|
||||
Map<TransportId, TransportProperties> transportProperties,
|
||||
Map<TransportId, TransportProperties> remoteTransportProperties,
|
||||
boolean alice) {
|
||||
BdfList localInfo = BdfList.of(
|
||||
localAuthorId,
|
||||
acceptTimestamp,
|
||||
@@ -142,43 +193,10 @@ class IntroductionCryptoImpl implements IntroductionCrypto {
|
||||
alice ? localInfo : remoteInfo,
|
||||
alice ? remoteInfo : localInfo
|
||||
);
|
||||
return crypto.mac(
|
||||
LABEL_AUTH_MAC,
|
||||
macKey,
|
||||
clientHelper.toByteArray(macList)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void verifyMac(byte[] mac, IntroduceeSession s,
|
||||
AuthorId localAuthorId)
|
||||
throws GeneralSecurityException, FormatException {
|
||||
boolean alice = isAlice(localAuthorId, s.getRemoteAuthor().getId());
|
||||
verifyMac(mac, new SecretKey(s.getMasterKey()),
|
||||
s.getIntroducer().getId(), localAuthorId,
|
||||
s.getRemoteAuthor().getId(), s.getAcceptTimestamp(),
|
||||
s.getRemoteAcceptTimestamp(), s.getEphemeralPublicKey(),
|
||||
s.getRemotePublicKey(), s.getTransportProperties(),
|
||||
s.getRemoteTransportProperties(), !alice);
|
||||
}
|
||||
|
||||
void verifyMac(byte[] mac, SecretKey masterKey,
|
||||
AuthorId introducerId, AuthorId localAuthorId,
|
||||
AuthorId remoteAuthorId, long acceptTimestamp,
|
||||
long remoteAcceptTimestamp, byte[] ephemeralPublicKey,
|
||||
byte[] remoteEphemeralPublicKey,
|
||||
Map<TransportId, TransportProperties> transportProperties,
|
||||
Map<TransportId, TransportProperties> remoteTransportProperties,
|
||||
boolean alice) throws GeneralSecurityException, FormatException {
|
||||
SecretKey macKey = deriveMacKey(masterKey, alice);
|
||||
byte[] calculatedMac =
|
||||
mac(macKey, introducerId, localAuthorId, remoteAuthorId,
|
||||
acceptTimestamp, remoteAcceptTimestamp,
|
||||
ephemeralPublicKey, remoteEphemeralPublicKey,
|
||||
transportProperties, remoteTransportProperties, !alice);
|
||||
if (!Arrays.equals(mac, calculatedMac)) {
|
||||
throw new GeneralSecurityException();
|
||||
try {
|
||||
return clientHelper.toByteArray(macList);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +222,8 @@ class IntroductionCryptoImpl implements IntroductionCrypto {
|
||||
void verifySignature(SecretKey macKey, byte[] publicKey,
|
||||
byte[] signature) throws GeneralSecurityException {
|
||||
byte[] nonce = getNonce(macKey);
|
||||
if (!crypto.verify(LABEL_AUTH_SIGN, nonce, publicKey, signature)) {
|
||||
if (!crypto.verifySignature(signature, LABEL_AUTH_SIGN, nonce,
|
||||
publicKey)) {
|
||||
throw new GeneralSecurityException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.contact.ContactManager.ContactHook;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
@@ -37,6 +38,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
@@ -59,6 +61,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
implements IntroductionManager, Client, ContactHook {
|
||||
|
||||
private final ContactGroupFactory contactGroupFactory;
|
||||
private final ContactManager contactManager;
|
||||
private final MessageParser messageParser;
|
||||
private final SessionEncoder sessionEncoder;
|
||||
private final SessionParser sessionParser;
|
||||
@@ -74,6 +77,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
MetadataParser metadataParser,
|
||||
MessageTracker messageTracker,
|
||||
ContactGroupFactory contactGroupFactory,
|
||||
ContactManager contactManager,
|
||||
MessageParser messageParser,
|
||||
SessionEncoder sessionEncoder,
|
||||
SessionParser sessionParser,
|
||||
@@ -83,6 +87,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
IdentityManager identityManager) {
|
||||
super(db, clientHelper, metadataParser, messageTracker);
|
||||
this.contactGroupFactory = contactGroupFactory;
|
||||
this.contactManager = contactManager;
|
||||
this.messageParser = messageParser;
|
||||
this.sessionEncoder = sessionEncoder;
|
||||
this.sessionParser = sessionParser;
|
||||
@@ -107,8 +112,6 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
public void addingContact(Transaction txn, Contact c) throws DbException {
|
||||
// Create a group to share with the contact
|
||||
Group g = getContactGroup(c);
|
||||
// Return if we've already set things up for this contact
|
||||
if (db.containsGroup(txn, g.getId())) return;
|
||||
// Store the group and share it with the contact
|
||||
db.addGroup(txn, g);
|
||||
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
|
||||
@@ -124,12 +127,9 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
|
||||
@Override
|
||||
public void removingContact(Transaction txn, Contact c) throws DbException {
|
||||
try {
|
||||
removeSessionWithIntroducer(txn, c);
|
||||
abortOrRemoveSessionWithIntroducee(txn, c);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
removeSessionWithIntroducer(txn, c);
|
||||
abortOrRemoveSessionWithIntroducee(txn, c);
|
||||
|
||||
// Remove the contact group (all messages will be removed with it)
|
||||
db.removeGroup(txn, getContactGroup(c));
|
||||
}
|
||||
@@ -185,12 +185,12 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
Message m, BdfList body) throws DbException, FormatException {
|
||||
ContactId introducerId = getContactId(txn, m.getGroupId());
|
||||
Author introducer = db.getContact(txn, introducerId).getAuthor();
|
||||
Author alice = identityManager.getLocalAuthor(txn);
|
||||
Author bob = messageParser.parseRequestMessage(m, body).getAuthor();
|
||||
if (alice.equals(bob)) throw new FormatException();
|
||||
SessionId sessionId = crypto.getSessionId(introducer, alice, bob);
|
||||
Author local = identityManager.getLocalAuthor(txn);
|
||||
Author remote = messageParser.parseRequestMessage(m, body).getAuthor();
|
||||
if (local.equals(remote)) throw new FormatException();
|
||||
SessionId sessionId = crypto.getSessionId(introducer, local, remote);
|
||||
return IntroduceeSession
|
||||
.getInitial(m.getGroupId(), sessionId, introducer, bob);
|
||||
.getInitial(m.getGroupId(), sessionId, introducer, remote);
|
||||
}
|
||||
|
||||
private <S extends Session> S handleMessage(Transaction txn, Message m,
|
||||
@@ -249,7 +249,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
}
|
||||
|
||||
private void storeSession(Transaction txn, MessageId storageId,
|
||||
Session session) throws DbException, FormatException {
|
||||
Session session) throws DbException {
|
||||
BdfDictionary d;
|
||||
if (session.getRole() == INTRODUCER) {
|
||||
d = sessionEncoder
|
||||
@@ -260,7 +260,11 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
clientHelper.mergeMessageMetadata(txn, storageId, d);
|
||||
try {
|
||||
clientHelper.mergeMessageMetadata(txn, storageId, d);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -356,7 +360,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
Map<MessageId, BdfDictionary> results = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, contactGroupId, query);
|
||||
messages = new ArrayList<>(results.size());
|
||||
for (Map.Entry<MessageId, BdfDictionary> e : results.entrySet()) {
|
||||
for (Entry<MessageId, BdfDictionary> e : results.entrySet()) {
|
||||
MessageId m = e.getKey();
|
||||
MessageMetadata meta =
|
||||
messageParser.parseMetadata(e.getValue());
|
||||
@@ -394,11 +398,11 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
Role role = sessionParser.getRole(bdfSession);
|
||||
SessionId sessionId;
|
||||
Author author;
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||
if (role == INTRODUCER) {
|
||||
IntroducerSession session =
|
||||
sessionParser.parseIntroducerSession(bdfSession);
|
||||
sessionId = session.getSessionId();
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||
if (localAuthor.equals(session.getIntroducee1().author)) {
|
||||
author = session.getIntroducee2().author;
|
||||
} else {
|
||||
@@ -410,8 +414,14 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
sessionId = session.getSessionId();
|
||||
author = session.getRemoteAuthor();
|
||||
} else throw new AssertionError();
|
||||
String message = ""; // TODO
|
||||
boolean contactExists = false; // TODO
|
||||
Message msg = clientHelper.getMessage(txn, m);
|
||||
BdfList body = clientHelper.getMessageAsList(txn, m);
|
||||
if (msg == null || body == null) throw new AssertionError();
|
||||
RequestMessage rm = messageParser.parseRequestMessage(msg, body);
|
||||
String message = rm.getMessage();
|
||||
boolean contactExists = contactManager
|
||||
.contactExists(txn, rm.getAuthor().getId(),
|
||||
localAuthor.getId());
|
||||
|
||||
return new IntroductionRequest(sessionId, m, contactGroupId,
|
||||
role, meta.getTimestamp(), meta.isLocal(),
|
||||
@@ -449,12 +459,16 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
}
|
||||
|
||||
private void removeSessionWithIntroducer(Transaction txn,
|
||||
Contact introducer) throws DbException, FormatException {
|
||||
Contact introducer) throws DbException {
|
||||
BdfDictionary query = sessionEncoder
|
||||
.getIntroduceeSessionsByIntroducerQuery(introducer.getAuthor());
|
||||
Map<MessageId, BdfDictionary> sessions = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, getLocalGroup().getId(),
|
||||
query);
|
||||
Map<MessageId, BdfDictionary> sessions;
|
||||
try {
|
||||
sessions = clientHelper.getMessageMetadataAsDictionary(txn,
|
||||
getLocalGroup().getId(), query);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
for (MessageId id : sessions.keySet()) {
|
||||
db.deleteMessageMetadata(txn, id); // TODO needed?
|
||||
db.removeMessage(txn, id);
|
||||
@@ -462,16 +476,23 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
}
|
||||
|
||||
private void abortOrRemoveSessionWithIntroducee(Transaction txn,
|
||||
Contact c) throws DbException, FormatException {
|
||||
Contact c) throws DbException {
|
||||
BdfDictionary query = sessionEncoder.getIntroducerSessionsQuery();
|
||||
Map<MessageId, BdfDictionary> sessions = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, getLocalGroup().getId(),
|
||||
query);
|
||||
Map<MessageId, BdfDictionary> sessions;
|
||||
try {
|
||||
sessions = clientHelper.getMessageMetadataAsDictionary(txn,
|
||||
getLocalGroup().getId(), query);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||
for (Map.Entry<MessageId, BdfDictionary> session : sessions
|
||||
.entrySet()) {
|
||||
IntroducerSession s =
|
||||
sessionParser.parseIntroducerSession(session.getValue());
|
||||
for (Entry<MessageId, BdfDictionary> session : sessions.entrySet()) {
|
||||
IntroducerSession s;
|
||||
try {
|
||||
s = sessionParser.parseIntroducerSession(session.getValue());
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
if (s.getIntroducee1().author.equals(c.getAuthor())) {
|
||||
abortOrRemoveSessionWithIntroducee(txn, s, session.getKey(),
|
||||
s.getIntroducee2(), localAuthor);
|
||||
@@ -484,7 +505,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
|
||||
private void abortOrRemoveSessionWithIntroducee(Transaction txn,
|
||||
IntroducerSession s, MessageId storageId, Introducee i,
|
||||
LocalAuthor localAuthor) throws DbException, FormatException {
|
||||
LocalAuthor localAuthor) throws DbException {
|
||||
if (db.containsContact(txn, i.author.getId(), localAuthor.getId())) {
|
||||
IntroducerSession session = introducerEngine.onAbortAction(txn, s);
|
||||
storeSession(txn, storageId, session);
|
||||
|
||||
@@ -78,8 +78,7 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
checkLength(msg, 1, MAX_REQUEST_MESSAGE_LENGTH);
|
||||
|
||||
BdfDictionary meta = messageEncoder
|
||||
.encodeRequestMetadata(m.getTimestamp(), false, false,
|
||||
false, false);
|
||||
.encodeRequestMetadata(m.getTimestamp(), false, false, false);
|
||||
if (previousMessageId == null) {
|
||||
return new BdfMessageContext(meta);
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@ import javax.annotation.Nullable;
|
||||
interface MessageEncoder {
|
||||
|
||||
BdfDictionary encodeRequestMetadata(long timestamp, boolean local,
|
||||
boolean read, boolean available, boolean accepted);
|
||||
boolean read, boolean available);
|
||||
|
||||
BdfDictionary encodeMetadata(MessageType type,
|
||||
@Nullable SessionId sessionId, long timestamp, boolean local,
|
||||
@@ -30,8 +30,6 @@ interface MessageEncoder {
|
||||
|
||||
void setAvailableToAnswer(BdfDictionary meta, boolean available);
|
||||
|
||||
void setInvitationAccepted(BdfDictionary meta, boolean accepted);
|
||||
|
||||
Message encodeRequestMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, Author author,
|
||||
@Nullable String message);
|
||||
|
||||
@@ -21,7 +21,6 @@ import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_INVITATION_ACCEPTED;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_MESSAGE_TYPE;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_SESSION_ID;
|
||||
@@ -49,12 +48,10 @@ class MessageEncoderImpl implements MessageEncoder {
|
||||
|
||||
@Override
|
||||
public BdfDictionary encodeRequestMetadata(long timestamp,
|
||||
boolean local, boolean read, boolean available,
|
||||
boolean accepted) {
|
||||
boolean local, boolean read, boolean available) {
|
||||
BdfDictionary meta =
|
||||
encodeMetadata(REQUEST, null, timestamp, local, read, false);
|
||||
meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available);
|
||||
meta.put(MSG_KEY_INVITATION_ACCEPTED, accepted);
|
||||
return meta;
|
||||
}
|
||||
|
||||
@@ -90,11 +87,6 @@ class MessageEncoderImpl implements MessageEncoder {
|
||||
meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, available);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInvitationAccepted(BdfDictionary meta, boolean accepted) {
|
||||
meta.put(MSG_KEY_INVITATION_ACCEPTED, accepted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message encodeRequestMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, Author author,
|
||||
|
||||
@@ -14,11 +14,11 @@ class MessageMetadata {
|
||||
@Nullable
|
||||
private final SessionId sessionId;
|
||||
private final long timestamp;
|
||||
private final boolean local, read, visible, available, accepted;
|
||||
private final boolean local, read, visible, available;
|
||||
|
||||
MessageMetadata(MessageType type, @Nullable SessionId sessionId,
|
||||
long timestamp, boolean local, boolean read, boolean visible,
|
||||
boolean available, boolean accepted) {
|
||||
boolean available) {
|
||||
this.type = type;
|
||||
this.sessionId = sessionId;
|
||||
this.timestamp = timestamp;
|
||||
@@ -26,7 +26,6 @@ class MessageMetadata {
|
||||
this.read = read;
|
||||
this.visible = visible;
|
||||
this.available = available;
|
||||
this.accepted = accepted;
|
||||
}
|
||||
|
||||
MessageType getMessageType() {
|
||||
@@ -58,8 +57,4 @@ class MessageMetadata {
|
||||
return available;
|
||||
}
|
||||
|
||||
public boolean wasAccepted() {
|
||||
return accepted;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ interface MessageParser {
|
||||
|
||||
BdfDictionary getMessagesVisibleInUiQuery();
|
||||
|
||||
BdfDictionary getInvitesAvailableToAnswerQuery(SessionId sessionId);
|
||||
BdfDictionary getRequestsAvailableToAnswerQuery(SessionId sessionId);
|
||||
|
||||
MessageMetadata parseMetadata(BdfDictionary meta) throws FormatException;
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_INVITATION_ACCEPTED;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_MESSAGE_TYPE;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_SESSION_ID;
|
||||
@@ -43,7 +42,7 @@ class MessageParserImpl implements MessageParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdfDictionary getInvitesAvailableToAnswerQuery(SessionId sessionId) {
|
||||
public BdfDictionary getRequestsAvailableToAnswerQuery(SessionId sessionId) {
|
||||
return BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_AVAILABLE_TO_ANSWER, true),
|
||||
new BdfEntry(MSG_KEY_MESSAGE_TYPE, REQUEST.getValue()),
|
||||
@@ -64,9 +63,8 @@ class MessageParserImpl implements MessageParser {
|
||||
boolean read = d.getBoolean(MSG_KEY_READ);
|
||||
boolean visible = d.getBoolean(MSG_KEY_VISIBLE_IN_UI);
|
||||
boolean available = d.getBoolean(MSG_KEY_AVAILABLE_TO_ANSWER, false);
|
||||
boolean accepted = d.getBoolean(MSG_KEY_INVITATION_ACCEPTED, false);
|
||||
return new MessageMetadata(type, sessionId, timestamp, local, read,
|
||||
visible, available, accepted);
|
||||
visible, available);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -397,7 +397,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageEncoder)
|
||||
.encodeRequestMetadata(message.getTimestamp(), false, false,
|
||||
false, false);
|
||||
false);
|
||||
will(returnValue(meta));
|
||||
}});
|
||||
}
|
||||
|
||||
@@ -74,8 +74,7 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
@Test
|
||||
public void testRequestMessageMetadata() throws FormatException {
|
||||
BdfDictionary d = messageEncoder
|
||||
.encodeRequestMetadata(timestamp, true, false, false,
|
||||
true);
|
||||
.encodeRequestMetadata(timestamp, true, false, false);
|
||||
MessageMetadata meta = messageParser.parseMetadata(d);
|
||||
|
||||
assertEquals(REQUEST, meta.getMessageType());
|
||||
@@ -85,7 +84,6 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
assertFalse(meta.isRead());
|
||||
assertFalse(meta.isVisibleInConversation());
|
||||
assertFalse(meta.isAvailableToAnswer());
|
||||
assertTrue(meta.wasAccepted());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -102,7 +100,6 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
assertTrue(meta.isRead());
|
||||
assertFalse(meta.isVisibleInConversation());
|
||||
assertFalse(meta.isAvailableToAnswer());
|
||||
assertFalse(meta.wasAccepted());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user