mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 12:49:55 +01:00
Implement MessageEncoder and MessageParser
This commit is contained in:
@@ -18,16 +18,19 @@ class AcceptMessage extends IntroductionMessage {
|
|||||||
|
|
||||||
private final SessionId sessionId;
|
private final SessionId sessionId;
|
||||||
private final byte[] ephemeralPublicKey;
|
private final byte[] ephemeralPublicKey;
|
||||||
|
private final long acceptTimestamp;
|
||||||
private final Map<TransportId, TransportProperties> transportProperties;
|
private final Map<TransportId, TransportProperties> transportProperties;
|
||||||
|
|
||||||
protected AcceptMessage(MessageId messageId, GroupId groupId,
|
protected AcceptMessage(MessageId messageId, GroupId groupId,
|
||||||
long timestamp, @Nullable MessageId previousMessageId,
|
long timestamp, @Nullable MessageId previousMessageId,
|
||||||
SessionId sessionId,
|
SessionId sessionId,
|
||||||
byte[] ephemeralPublicKey,
|
byte[] ephemeralPublicKey,
|
||||||
|
long acceptTimestamp,
|
||||||
Map<TransportId, TransportProperties> transportProperties) {
|
Map<TransportId, TransportProperties> transportProperties) {
|
||||||
super(messageId, groupId, timestamp, previousMessageId);
|
super(messageId, groupId, timestamp, previousMessageId);
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.ephemeralPublicKey = ephemeralPublicKey;
|
this.ephemeralPublicKey = ephemeralPublicKey;
|
||||||
|
this.acceptTimestamp = acceptTimestamp;
|
||||||
this.transportProperties = transportProperties;
|
this.transportProperties = transportProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +42,10 @@ class AcceptMessage extends IntroductionMessage {
|
|||||||
return ephemeralPublicKey;
|
return ephemeralPublicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getAcceptTimestamp() {
|
||||||
|
return acceptTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
public Map<TransportId, TransportProperties> getTransportProperties() {
|
public Map<TransportId, TransportProperties> getTransportProperties() {
|
||||||
return transportProperties;
|
return transportProperties;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.briarproject.briar.introduction2;
|
||||||
|
|
||||||
|
interface IntroductionConstants {
|
||||||
|
|
||||||
|
// Message metadata keys
|
||||||
|
String MSG_KEY_MESSAGE_TYPE = "messageType";
|
||||||
|
String MSG_KEY_SESSION_ID = "sessionId";
|
||||||
|
String MSG_KEY_TIMESTAMP = "timestamp";
|
||||||
|
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";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -28,7 +28,6 @@ import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
|||||||
import static org.briarproject.briar.api.introduction2.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH;
|
import static org.briarproject.briar.api.introduction2.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH;
|
||||||
import static org.briarproject.briar.introduction2.MessageType.ACCEPT;
|
import static org.briarproject.briar.introduction2.MessageType.ACCEPT;
|
||||||
import static org.briarproject.briar.introduction2.MessageType.AUTH;
|
import static org.briarproject.briar.introduction2.MessageType.AUTH;
|
||||||
import static org.briarproject.briar.introduction2.MessageType.REQUEST;
|
|
||||||
|
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@@ -79,8 +78,8 @@ class IntroductionValidator extends BdfMessageValidator {
|
|||||||
checkLength(msg, 1, MAX_REQUEST_MESSAGE_LENGTH);
|
checkLength(msg, 1, MAX_REQUEST_MESSAGE_LENGTH);
|
||||||
|
|
||||||
BdfDictionary meta = messageEncoder
|
BdfDictionary meta = messageEncoder
|
||||||
.encodeRequestMetadata(REQUEST, m.getTimestamp(), false,
|
.encodeRequestMetadata(m.getTimestamp(), false, false,
|
||||||
false, false, false, false);
|
false, false);
|
||||||
if (previousMessageId == null) {
|
if (previousMessageId == null) {
|
||||||
return new BdfMessageContext(meta);
|
return new BdfMessageContext(meta);
|
||||||
} else {
|
} else {
|
||||||
@@ -92,7 +91,7 @@ class IntroductionValidator extends BdfMessageValidator {
|
|||||||
|
|
||||||
private BdfMessageContext validateAcceptMessage(Message m, BdfList body)
|
private BdfMessageContext validateAcceptMessage(Message m, BdfList body)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
checkSize(body, 5);
|
checkSize(body, 6);
|
||||||
|
|
||||||
byte[] sessionIdBytes = body.getRaw(1);
|
byte[] sessionIdBytes = body.getRaw(1);
|
||||||
checkLength(sessionIdBytes, UniqueId.LENGTH);
|
checkLength(sessionIdBytes, UniqueId.LENGTH);
|
||||||
@@ -103,7 +102,9 @@ class IntroductionValidator extends BdfMessageValidator {
|
|||||||
byte[] ephemeralPublicKey = body.getRaw(3);
|
byte[] ephemeralPublicKey = body.getRaw(3);
|
||||||
checkLength(ephemeralPublicKey, 0, MAX_PUBLIC_KEY_LENGTH);
|
checkLength(ephemeralPublicKey, 0, MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
|
||||||
BdfDictionary transportProperties = body.getDictionary(4);
|
body.getLong(4);
|
||||||
|
|
||||||
|
BdfDictionary transportProperties = body.getDictionary(5);
|
||||||
if (transportProperties.size() < 1) throw new FormatException();
|
if (transportProperties.size() < 1) throw new FormatException();
|
||||||
for (String tId : transportProperties.keySet()) {
|
for (String tId : transportProperties.keySet()) {
|
||||||
checkLength(tId, 1, MAX_TRANSPORT_ID_LENGTH);
|
checkLength(tId, 1, MAX_TRANSPORT_ID_LENGTH);
|
||||||
|
|||||||
@@ -1,15 +1,57 @@
|
|||||||
package org.briarproject.briar.introduction2;
|
package org.briarproject.briar.introduction2;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
|
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.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.briar.api.client.SessionId;
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
interface MessageEncoder {
|
interface MessageEncoder {
|
||||||
|
|
||||||
BdfDictionary encodeRequestMetadata(MessageType type,
|
BdfDictionary encodeRequestMetadata(long timestamp, boolean local,
|
||||||
long timestamp, boolean local, boolean read, boolean visible,
|
boolean read, boolean available, boolean accepted);
|
||||||
boolean available, boolean accepted);
|
|
||||||
|
|
||||||
BdfDictionary encodeMetadata(MessageType type, SessionId sessionId,
|
BdfDictionary encodeMetadata(MessageType type,
|
||||||
long timestamp, boolean local, boolean read, boolean visible);
|
@Nullable SessionId sessionId, long timestamp, boolean local,
|
||||||
|
boolean read, boolean visible);
|
||||||
|
|
||||||
|
void addSessionId(BdfDictionary meta, SessionId sessionId);
|
||||||
|
|
||||||
|
void setVisibleInUi(BdfDictionary meta, boolean visible);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Message encodeAcceptMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||||
|
byte[] ephemeralPublicKey, long acceptTimestamp,
|
||||||
|
Map<TransportId, TransportProperties> transportProperties);
|
||||||
|
|
||||||
|
Message encodeDeclineMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId);
|
||||||
|
|
||||||
|
Message encodeAuthMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||||
|
byte[] mac, byte[] signature);
|
||||||
|
|
||||||
|
Message encodeActivateMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId);
|
||||||
|
|
||||||
|
Message encodeAbortMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,205 @@
|
|||||||
|
package org.briarproject.briar.introduction2;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.client.ClientHelper;
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
|
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.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_INVITATION_ACCEPTED;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_LOCAL;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_MESSAGE_TYPE;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_SESSION_ID;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_TIMESTAMP;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_VISIBLE_IN_UI;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.ABORT;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.ACCEPT;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.ACTIVATE;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.AUTH;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.DECLINE;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.REQUEST;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
class MessageEncoderImpl implements MessageEncoder {
|
||||||
|
|
||||||
|
private final ClientHelper clientHelper;
|
||||||
|
private final MessageFactory messageFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
MessageEncoderImpl(ClientHelper clientHelper,
|
||||||
|
MessageFactory messageFactory) {
|
||||||
|
this.clientHelper = clientHelper;
|
||||||
|
this.messageFactory = messageFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BdfDictionary encodeRequestMetadata(long timestamp,
|
||||||
|
boolean local, boolean read, boolean available,
|
||||||
|
boolean accepted) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BdfDictionary encodeMetadata(MessageType type,
|
||||||
|
@Nullable SessionId sessionId, long timestamp, boolean local,
|
||||||
|
boolean read, boolean visible) {
|
||||||
|
BdfDictionary meta = new BdfDictionary();
|
||||||
|
meta.put(MSG_KEY_MESSAGE_TYPE, type.getValue());
|
||||||
|
if (sessionId != null)
|
||||||
|
meta.put(MSG_KEY_SESSION_ID, sessionId);
|
||||||
|
else if (type != REQUEST)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
meta.put(MSG_KEY_TIMESTAMP, timestamp);
|
||||||
|
meta.put(MSG_KEY_LOCAL, local);
|
||||||
|
meta.put(MSG_KEY_READ, read);
|
||||||
|
meta.put(MSG_KEY_VISIBLE_IN_UI, visible);
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addSessionId(BdfDictionary meta, SessionId sessionId) {
|
||||||
|
meta.put(MSG_KEY_SESSION_ID, sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisibleInUi(BdfDictionary meta, boolean visible) {
|
||||||
|
meta.put(MSG_KEY_VISIBLE_IN_UI, visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAvailableToAnswer(BdfDictionary meta, boolean available) {
|
||||||
|
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,
|
||||||
|
@Nullable String message) {
|
||||||
|
if (message != null && message.equals("")) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
BdfList body = BdfList.of(
|
||||||
|
REQUEST.getValue(),
|
||||||
|
previousMessageId,
|
||||||
|
clientHelper.toList(author),
|
||||||
|
message
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
return messageFactory.createMessage(contactGroupId, timestamp,
|
||||||
|
clientHelper.toByteArray(body));
|
||||||
|
} catch (FormatException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message encodeAcceptMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||||
|
byte[] ephemeralPublicKey, long acceptTimestamp,
|
||||||
|
Map<TransportId, TransportProperties> transportProperties) {
|
||||||
|
BdfList body = BdfList.of(
|
||||||
|
ACCEPT.getValue(),
|
||||||
|
sessionId,
|
||||||
|
previousMessageId,
|
||||||
|
ephemeralPublicKey,
|
||||||
|
acceptTimestamp,
|
||||||
|
encodeTransportProperties(transportProperties)
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
return messageFactory.createMessage(contactGroupId, timestamp,
|
||||||
|
clientHelper.toByteArray(body));
|
||||||
|
} catch (FormatException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message encodeDeclineMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId) {
|
||||||
|
return encodeMessage(DECLINE, contactGroupId, sessionId, timestamp,
|
||||||
|
previousMessageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message encodeAuthMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||||
|
byte[] mac, byte[] signature) {
|
||||||
|
BdfList body = BdfList.of(
|
||||||
|
AUTH.getValue(),
|
||||||
|
sessionId,
|
||||||
|
previousMessageId,
|
||||||
|
mac,
|
||||||
|
signature
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
return messageFactory.createMessage(contactGroupId, timestamp,
|
||||||
|
clientHelper.toByteArray(body));
|
||||||
|
} catch (FormatException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message encodeActivateMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId) {
|
||||||
|
return encodeMessage(ACTIVATE, contactGroupId, sessionId, timestamp,
|
||||||
|
previousMessageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message encodeAbortMessage(GroupId contactGroupId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId, SessionId sessionId) {
|
||||||
|
return encodeMessage(ABORT, contactGroupId, sessionId, timestamp,
|
||||||
|
previousMessageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Message encodeMessage(MessageType type, GroupId contactGroupId,
|
||||||
|
SessionId sessionId, long timestamp,
|
||||||
|
@Nullable MessageId previousMessageId) {
|
||||||
|
BdfList body = BdfList.of(
|
||||||
|
type.getValue(),
|
||||||
|
sessionId,
|
||||||
|
previousMessageId
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
return messageFactory.createMessage(contactGroupId, timestamp,
|
||||||
|
clientHelper.toByteArray(body));
|
||||||
|
} catch (FormatException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BdfDictionary encodeTransportProperties(
|
||||||
|
Map<TransportId, TransportProperties> map) {
|
||||||
|
BdfDictionary d = new BdfDictionary();
|
||||||
|
for (Map.Entry<TransportId, TransportProperties> e : map.entrySet()) {
|
||||||
|
d.put(e.getKey().getString(), e.getValue());
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package org.briarproject.briar.introduction2;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
@NotNullByDefault
|
||||||
|
class MessageMetadata {
|
||||||
|
|
||||||
|
private final MessageType type;
|
||||||
|
@Nullable
|
||||||
|
private final SessionId sessionId;
|
||||||
|
private final long timestamp;
|
||||||
|
private final boolean local, read, visible, available, accepted;
|
||||||
|
|
||||||
|
MessageMetadata(MessageType type, @Nullable SessionId sessionId,
|
||||||
|
long timestamp, boolean local, boolean read, boolean visible,
|
||||||
|
boolean available, boolean accepted) {
|
||||||
|
this.type = type;
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.local = local;
|
||||||
|
this.read = read;
|
||||||
|
this.visible = visible;
|
||||||
|
this.available = available;
|
||||||
|
this.accepted = accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageType getMessageType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public SessionId getSessionId() {
|
||||||
|
return sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isLocal() {
|
||||||
|
return local;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isRead() {
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isVisibleInConversation() {
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isAvailableToAnswer() {
|
||||||
|
return available;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wasAccepted() {
|
||||||
|
return accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package org.briarproject.briar.introduction2;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
interface MessageParser {
|
||||||
|
|
||||||
|
BdfDictionary getMessagesVisibleInUiQuery();
|
||||||
|
|
||||||
|
BdfDictionary getInvitesAvailableToAnswerQuery(SessionId sessionId);
|
||||||
|
|
||||||
|
MessageMetadata parseMetadata(BdfDictionary meta) throws FormatException;
|
||||||
|
|
||||||
|
RequestMessage parseRequestMessage(Message m, BdfList body)
|
||||||
|
throws FormatException;
|
||||||
|
|
||||||
|
AcceptMessage parseAcceptMessage(Message m, BdfList body)
|
||||||
|
throws FormatException;
|
||||||
|
|
||||||
|
DeclineMessage parseDeclineMessage(Message m, BdfList body)
|
||||||
|
throws FormatException;
|
||||||
|
|
||||||
|
AuthMessage parseAuthMessage(Message m, BdfList body)
|
||||||
|
throws FormatException;
|
||||||
|
|
||||||
|
ActivateMessage parseActivateMessage(Message m, BdfList body)
|
||||||
|
throws FormatException;
|
||||||
|
|
||||||
|
AbortMessage parseAbortMessage(Message m, BdfList body)
|
||||||
|
throws FormatException;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package org.briarproject.briar.introduction2;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.client.ClientHelper;
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.bramble.api.data.BdfEntry;
|
||||||
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
|
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.Message;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_INVITATION_ACCEPTED;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_LOCAL;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_MESSAGE_TYPE;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_SESSION_ID;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_TIMESTAMP;
|
||||||
|
import static org.briarproject.briar.introduction2.IntroductionConstants.MSG_KEY_VISIBLE_IN_UI;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.REQUEST;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
class MessageParserImpl implements MessageParser {
|
||||||
|
|
||||||
|
private final ClientHelper clientHelper;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
MessageParserImpl(ClientHelper clientHelper) {
|
||||||
|
this.clientHelper = clientHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BdfDictionary getMessagesVisibleInUiQuery() {
|
||||||
|
return BdfDictionary.of(new BdfEntry(MSG_KEY_VISIBLE_IN_UI, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BdfDictionary getInvitesAvailableToAnswerQuery(SessionId sessionId) {
|
||||||
|
return BdfDictionary.of(
|
||||||
|
new BdfEntry(MSG_KEY_AVAILABLE_TO_ANSWER, true),
|
||||||
|
new BdfEntry(MSG_KEY_MESSAGE_TYPE, REQUEST.getValue()),
|
||||||
|
new BdfEntry(MSG_KEY_SESSION_ID, sessionId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageMetadata parseMetadata(BdfDictionary d)
|
||||||
|
throws FormatException {
|
||||||
|
MessageType type = MessageType
|
||||||
|
.fromValue(d.getLong(MSG_KEY_MESSAGE_TYPE).intValue());
|
||||||
|
byte[] sessionIdBytes = d.getOptionalRaw(MSG_KEY_SESSION_ID);
|
||||||
|
SessionId sessionId =
|
||||||
|
sessionIdBytes == null ? null : new SessionId(sessionIdBytes);
|
||||||
|
long timestamp = d.getLong(MSG_KEY_TIMESTAMP);
|
||||||
|
boolean local = d.getBoolean(MSG_KEY_LOCAL);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RequestMessage parseRequestMessage(Message m, BdfList body)
|
||||||
|
throws FormatException {
|
||||||
|
byte[] previousMsgBytes = body.getOptionalRaw(1);
|
||||||
|
MessageId previousMessageId = (previousMsgBytes == null ? null :
|
||||||
|
new MessageId(previousMsgBytes));
|
||||||
|
Author author = clientHelper.parseAndValidateAuthor(body.getList(2));
|
||||||
|
String message = body.getOptionalString(3);
|
||||||
|
return new RequestMessage(m.getId(), m.getGroupId(),
|
||||||
|
m.getTimestamp(), previousMessageId, author, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AcceptMessage parseAcceptMessage(Message m, BdfList body)
|
||||||
|
throws FormatException {
|
||||||
|
SessionId sessionId = new SessionId(body.getRaw(1));
|
||||||
|
byte[] previousMsgBytes = body.getOptionalRaw(2);
|
||||||
|
MessageId previousMessageId = (previousMsgBytes == null ? null :
|
||||||
|
new MessageId(previousMsgBytes));
|
||||||
|
byte[] ephemeralPublicKey = body.getRaw(3);
|
||||||
|
long acceptTimestamp = body.getLong(4);
|
||||||
|
Map<TransportId, TransportProperties> transportProperties = clientHelper
|
||||||
|
.parseAndValidateTransportPropertiesMap(body.getDictionary(5));
|
||||||
|
return new AcceptMessage(m.getId(), m.getGroupId(), m.getTimestamp(),
|
||||||
|
previousMessageId, sessionId, ephemeralPublicKey,
|
||||||
|
acceptTimestamp, transportProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeclineMessage parseDeclineMessage(Message m, BdfList body)
|
||||||
|
throws FormatException {
|
||||||
|
SessionId sessionId = new SessionId(body.getRaw(1));
|
||||||
|
byte[] previousMsgBytes = body.getOptionalRaw(2);
|
||||||
|
MessageId previousMessageId = (previousMsgBytes == null ? null :
|
||||||
|
new MessageId(previousMsgBytes));
|
||||||
|
return new DeclineMessage(m.getId(), m.getGroupId(), m.getTimestamp(),
|
||||||
|
previousMessageId, sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthMessage parseAuthMessage(Message m, BdfList body)
|
||||||
|
throws FormatException {
|
||||||
|
SessionId sessionId = new SessionId(body.getRaw(1));
|
||||||
|
byte[] previousMsgBytes = body.getRaw(2);
|
||||||
|
MessageId previousMessageId = new MessageId(previousMsgBytes);
|
||||||
|
byte[] mac = body.getRaw(3);
|
||||||
|
byte[] signature = body.getRaw(4);
|
||||||
|
return new AuthMessage(m.getId(), m.getGroupId(), m.getTimestamp(),
|
||||||
|
previousMessageId, sessionId, mac, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActivateMessage parseActivateMessage(Message m, BdfList body)
|
||||||
|
throws FormatException {
|
||||||
|
SessionId sessionId = new SessionId(body.getRaw(1));
|
||||||
|
byte[] previousMsgBytes = body.getRaw(2);
|
||||||
|
MessageId previousMessageId = new MessageId(previousMsgBytes);
|
||||||
|
return new ActivateMessage(m.getId(), m.getGroupId(), m.getTimestamp(),
|
||||||
|
previousMessageId, sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbortMessage parseAbortMessage(Message m, BdfList body)
|
||||||
|
throws FormatException {
|
||||||
|
SessionId sessionId = new SessionId(body.getRaw(1));
|
||||||
|
byte[] previousMsgBytes = body.getOptionalRaw(2);
|
||||||
|
MessageId previousMessageId = (previousMsgBytes == null ? null :
|
||||||
|
new MessageId(previousMsgBytes));
|
||||||
|
return new AbortMessage(m.getId(), m.getGroupId(), m.getTimestamp(),
|
||||||
|
previousMessageId, sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -41,6 +41,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
private final String text =
|
private final String text =
|
||||||
getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
|
getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
|
||||||
private final BdfDictionary meta = new BdfDictionary();
|
private final BdfDictionary meta = new BdfDictionary();
|
||||||
|
private final long acceptTimestamp = 42;
|
||||||
private final BdfDictionary transportProperties = BdfDictionary.of(
|
private final BdfDictionary transportProperties = BdfDictionary.of(
|
||||||
new BdfEntry("transportId", new BdfDictionary())
|
new BdfEntry("transportId", new BdfDictionary())
|
||||||
);
|
);
|
||||||
@@ -124,7 +125,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
public void testAcceptsAccept() throws Exception {
|
public void testAcceptsAccept() throws Exception {
|
||||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||||
previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
||||||
transportProperties);
|
acceptTimestamp, transportProperties);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||||
transportProperties.getDictionary("transportId"));
|
transportProperties.getDictionary("transportId"));
|
||||||
@@ -140,7 +141,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
public void testRejectsTooShortBodyForAccept() throws Exception {
|
public void testRejectsTooShortBodyForAccept() throws Exception {
|
||||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||||
previousMsgId.getBytes(),
|
previousMsgId.getBytes(),
|
||||||
getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
|
getRandomBytes(MAX_PUBLIC_KEY_LENGTH), acceptTimestamp);
|
||||||
validator.validateMessage(message, group, body);
|
validator.validateMessage(message, group, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +149,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
public void testRejectsTooLongBodyForAccept() throws Exception {
|
public void testRejectsTooLongBodyForAccept() throws Exception {
|
||||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||||
previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
previousMsgId.getBytes(), getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
||||||
transportProperties, null);
|
acceptTimestamp, transportProperties, null);
|
||||||
validator.validateMessage(message, group, body);
|
validator.validateMessage(message, group, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +157,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
public void testRejectsInvalidSessionIdForAccept() throws Exception {
|
public void testRejectsInvalidSessionIdForAccept() throws Exception {
|
||||||
BdfList body =
|
BdfList body =
|
||||||
BdfList.of(ACCEPT.getValue(), null, previousMsgId.getBytes(),
|
BdfList.of(ACCEPT.getValue(), null, previousMsgId.getBytes(),
|
||||||
getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
getRandomBytes(MAX_PUBLIC_KEY_LENGTH), acceptTimestamp,
|
||||||
transportProperties);
|
transportProperties);
|
||||||
validator.validateMessage(message, group, body);
|
validator.validateMessage(message, group, body);
|
||||||
}
|
}
|
||||||
@@ -164,7 +165,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testRejectsInvalidPreviousMsgIdForAccept() throws Exception {
|
public void testRejectsInvalidPreviousMsgIdForAccept() throws Exception {
|
||||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||||
null, getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
null, getRandomBytes(MAX_PUBLIC_KEY_LENGTH), acceptTimestamp,
|
||||||
transportProperties);
|
transportProperties);
|
||||||
validator.validateMessage(message, group, body);
|
validator.validateMessage(message, group, body);
|
||||||
}
|
}
|
||||||
@@ -173,7 +174,8 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
public void testRejectsTooLongPublicKeyForAccept() throws Exception {
|
public void testRejectsTooLongPublicKeyForAccept() throws Exception {
|
||||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||||
previousMsgId.getBytes(),
|
previousMsgId.getBytes(),
|
||||||
getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1), transportProperties);
|
getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1), acceptTimestamp,
|
||||||
|
transportProperties);
|
||||||
validator.validateMessage(message, group, body);
|
validator.validateMessage(message, group, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +184,8 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||||
previousMsgId.getBytes(),
|
previousMsgId.getBytes(),
|
||||||
getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1), new BdfDictionary());
|
getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1), acceptTimestamp,
|
||||||
|
new BdfDictionary());
|
||||||
validator.validateMessage(message, group, body);
|
validator.validateMessage(message, group, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,9 +400,8 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
|||||||
private void expectEncodeRequestMetadata() {
|
private void expectEncodeRequestMetadata() {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(messageEncoder)
|
oneOf(messageEncoder)
|
||||||
.encodeRequestMetadata(REQUEST, message.getTimestamp(),
|
.encodeRequestMetadata(message.getTimestamp(), false, false,
|
||||||
false, false,
|
false, false);
|
||||||
false, false, false);
|
|
||||||
will(returnValue(meta));
|
will(returnValue(meta));
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
package org.briarproject.briar.introduction2;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.client.ClientHelper;
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
|
import org.briarproject.bramble.api.identity.AuthorFactory;
|
||||||
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
|
import org.briarproject.briar.test.BriarIntegrationTestComponent;
|
||||||
|
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAC_BYTES;
|
||||||
|
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_SIGNATURE_BYTES;
|
||||||
|
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getTransportPropertiesMap;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.ABORT;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.REQUEST;
|
||||||
|
import static org.briarproject.briar.test.BriarTestUtils.getRealAuthor;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ClientHelper clientHelper;
|
||||||
|
@Inject
|
||||||
|
MessageFactory messageFactory;
|
||||||
|
@Inject
|
||||||
|
AuthorFactory authorFactory;
|
||||||
|
|
||||||
|
private final MessageEncoder messageEncoder;
|
||||||
|
private final MessageParser messageParser;
|
||||||
|
|
||||||
|
private final GroupId groupId = new GroupId(getRandomId());
|
||||||
|
private final long timestamp = 42L;
|
||||||
|
private final SessionId sessionId = new SessionId(getRandomId());
|
||||||
|
private final MessageId previousMsgId = new MessageId(getRandomId());
|
||||||
|
private final Author author;
|
||||||
|
private final String text =
|
||||||
|
getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
|
||||||
|
private final byte[] ephemeralPublicKey =
|
||||||
|
getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
private final byte[] mac = getRandomBytes(MAC_BYTES);
|
||||||
|
private final byte[] signature = getRandomBytes(MAX_SIGNATURE_BYTES);
|
||||||
|
|
||||||
|
public MessageEncoderParserIntegrationTest() {
|
||||||
|
BriarIntegrationTestComponent component =
|
||||||
|
DaggerBriarIntegrationTestComponent.builder().build();
|
||||||
|
component.inject(this);
|
||||||
|
|
||||||
|
messageEncoder = new MessageEncoderImpl(clientHelper, messageFactory);
|
||||||
|
messageParser = new MessageParserImpl(clientHelper);
|
||||||
|
author = getRealAuthor(authorFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestMessageMetadata() throws FormatException {
|
||||||
|
BdfDictionary d = messageEncoder
|
||||||
|
.encodeRequestMetadata(timestamp, true, false, false,
|
||||||
|
true);
|
||||||
|
MessageMetadata meta = messageParser.parseMetadata(d);
|
||||||
|
|
||||||
|
assertEquals(REQUEST, meta.getMessageType());
|
||||||
|
assertNull(meta.getSessionId());
|
||||||
|
assertEquals(timestamp, meta.getTimestamp());
|
||||||
|
assertTrue(meta.isLocal());
|
||||||
|
assertFalse(meta.isRead());
|
||||||
|
assertFalse(meta.isVisibleInConversation());
|
||||||
|
assertFalse(meta.isAvailableToAnswer());
|
||||||
|
assertTrue(meta.wasAccepted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMessageMetadata() throws FormatException {
|
||||||
|
BdfDictionary d = messageEncoder
|
||||||
|
.encodeMetadata(ABORT, sessionId, timestamp, false, true,
|
||||||
|
false);
|
||||||
|
MessageMetadata meta = messageParser.parseMetadata(d);
|
||||||
|
|
||||||
|
assertEquals(ABORT, meta.getMessageType());
|
||||||
|
assertEquals(sessionId, meta.getSessionId());
|
||||||
|
assertEquals(timestamp, meta.getTimestamp());
|
||||||
|
assertFalse(meta.isLocal());
|
||||||
|
assertTrue(meta.isRead());
|
||||||
|
assertFalse(meta.isVisibleInConversation());
|
||||||
|
assertFalse(meta.isAvailableToAnswer());
|
||||||
|
assertFalse(meta.wasAccepted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestMessage() throws FormatException {
|
||||||
|
Message m = messageEncoder
|
||||||
|
.encodeRequestMessage(groupId, timestamp, previousMsgId, author,
|
||||||
|
text);
|
||||||
|
RequestMessage rm =
|
||||||
|
messageParser.parseRequestMessage(m, clientHelper.toList(m));
|
||||||
|
|
||||||
|
assertEquals(m.getId(), rm.getMessageId());
|
||||||
|
assertEquals(m.getGroupId(), rm.getGroupId());
|
||||||
|
assertEquals(m.getTimestamp(), rm.getTimestamp());
|
||||||
|
assertEquals(previousMsgId, rm.getPreviousMessageId());
|
||||||
|
assertEquals(author, rm.getAuthor());
|
||||||
|
assertEquals(text, rm.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestMessageWithPreviousMsgNull() throws FormatException {
|
||||||
|
Message m = messageEncoder
|
||||||
|
.encodeRequestMessage(groupId, timestamp, null, author, text);
|
||||||
|
RequestMessage rm =
|
||||||
|
messageParser.parseRequestMessage(m, clientHelper.toList(m));
|
||||||
|
|
||||||
|
assertNull(rm.getPreviousMessageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestMessageWithMsgNull() throws FormatException {
|
||||||
|
Message m = messageEncoder
|
||||||
|
.encodeRequestMessage(groupId, timestamp, previousMsgId, author,
|
||||||
|
null);
|
||||||
|
RequestMessage rm =
|
||||||
|
messageParser.parseRequestMessage(m, clientHelper.toList(m));
|
||||||
|
|
||||||
|
assertNull(rm.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAcceptMessage() throws Exception {
|
||||||
|
Map<TransportId, TransportProperties> transportProperties =
|
||||||
|
getTransportPropertiesMap(2);
|
||||||
|
|
||||||
|
long acceptTimestamp = 1337L;
|
||||||
|
Message m = messageEncoder
|
||||||
|
.encodeAcceptMessage(groupId, timestamp, previousMsgId,
|
||||||
|
sessionId, ephemeralPublicKey, acceptTimestamp,
|
||||||
|
transportProperties);
|
||||||
|
AcceptMessage rm =
|
||||||
|
messageParser.parseAcceptMessage(m, clientHelper.toList(m));
|
||||||
|
|
||||||
|
assertEquals(m.getId(), rm.getMessageId());
|
||||||
|
assertEquals(m.getGroupId(), rm.getGroupId());
|
||||||
|
assertEquals(m.getTimestamp(), rm.getTimestamp());
|
||||||
|
assertEquals(previousMsgId, rm.getPreviousMessageId());
|
||||||
|
assertEquals(sessionId, rm.getSessionId());
|
||||||
|
assertArrayEquals(ephemeralPublicKey, rm.getEphemeralPublicKey());
|
||||||
|
assertEquals(acceptTimestamp, rm.getAcceptTimestamp());
|
||||||
|
assertEquals(transportProperties, rm.getTransportProperties());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeclineMessage() throws Exception {
|
||||||
|
Message m = messageEncoder
|
||||||
|
.encodeDeclineMessage(groupId, timestamp, previousMsgId,
|
||||||
|
sessionId);
|
||||||
|
DeclineMessage rm =
|
||||||
|
messageParser.parseDeclineMessage(m, clientHelper.toList(m));
|
||||||
|
|
||||||
|
assertEquals(m.getId(), rm.getMessageId());
|
||||||
|
assertEquals(m.getGroupId(), rm.getGroupId());
|
||||||
|
assertEquals(m.getTimestamp(), rm.getTimestamp());
|
||||||
|
assertEquals(previousMsgId, rm.getPreviousMessageId());
|
||||||
|
assertEquals(sessionId, rm.getSessionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAuthMessage() throws Exception {
|
||||||
|
Message m = messageEncoder
|
||||||
|
.encodeAuthMessage(groupId, timestamp, previousMsgId,
|
||||||
|
sessionId, mac, signature);
|
||||||
|
AuthMessage rm =
|
||||||
|
messageParser.parseAuthMessage(m, clientHelper.toList(m));
|
||||||
|
|
||||||
|
assertEquals(m.getId(), rm.getMessageId());
|
||||||
|
assertEquals(m.getGroupId(), rm.getGroupId());
|
||||||
|
assertEquals(m.getTimestamp(), rm.getTimestamp());
|
||||||
|
assertEquals(previousMsgId, rm.getPreviousMessageId());
|
||||||
|
assertEquals(sessionId, rm.getSessionId());
|
||||||
|
assertArrayEquals(mac, rm.getMac());
|
||||||
|
assertArrayEquals(signature, rm.getSignature());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testActivateMessage() throws Exception {
|
||||||
|
Message m = messageEncoder
|
||||||
|
.encodeActivateMessage(groupId, timestamp, previousMsgId,
|
||||||
|
sessionId);
|
||||||
|
ActivateMessage rm =
|
||||||
|
messageParser.parseActivateMessage(m, clientHelper.toList(m));
|
||||||
|
|
||||||
|
assertEquals(m.getId(), rm.getMessageId());
|
||||||
|
assertEquals(m.getGroupId(), rm.getGroupId());
|
||||||
|
assertEquals(m.getTimestamp(), rm.getTimestamp());
|
||||||
|
assertEquals(previousMsgId, rm.getPreviousMessageId());
|
||||||
|
assertEquals(sessionId, rm.getSessionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAbortMessage() throws Exception {
|
||||||
|
Message m = messageEncoder
|
||||||
|
.encodeAbortMessage(groupId, timestamp, previousMsgId,
|
||||||
|
sessionId);
|
||||||
|
AbortMessage rm =
|
||||||
|
messageParser.parseAbortMessage(m, clientHelper.toList(m));
|
||||||
|
|
||||||
|
assertEquals(m.getId(), rm.getMessageId());
|
||||||
|
assertEquals(m.getGroupId(), rm.getGroupId());
|
||||||
|
assertEquals(m.getTimestamp(), rm.getTimestamp());
|
||||||
|
assertEquals(previousMsgId, rm.getPreviousMessageId());
|
||||||
|
assertEquals(sessionId, rm.getSessionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package org.briarproject.briar.introduction2;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.client.ClientHelper;
|
||||||
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
|
import org.jmock.Expectations;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
|
||||||
|
import static org.briarproject.briar.introduction2.MessageType.REQUEST;
|
||||||
|
|
||||||
|
public class MessageEncoderTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
|
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
|
||||||
|
private final MessageFactory messageFactory =
|
||||||
|
context.mock(MessageFactory.class);
|
||||||
|
private final MessageEncoder messageEncoder =
|
||||||
|
new MessageEncoderImpl(clientHelper, messageFactory);
|
||||||
|
|
||||||
|
private final GroupId groupId = new GroupId(getRandomId());
|
||||||
|
private final long timestamp = 42L;
|
||||||
|
private final Message message =
|
||||||
|
new Message(new MessageId(getRandomId()), groupId, timestamp,
|
||||||
|
getRandomBytes(48));
|
||||||
|
private final byte[] body = getRandomBytes(42);
|
||||||
|
private final Author author = getAuthor();
|
||||||
|
private final BdfList authorList = new BdfList();
|
||||||
|
private final String text =
|
||||||
|
getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeRequestMessage() throws FormatException {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clientHelper).toList(author);
|
||||||
|
will(returnValue(authorList));
|
||||||
|
}});
|
||||||
|
expectCreateMessage(
|
||||||
|
BdfList.of(REQUEST.getValue(), null, authorList, text));
|
||||||
|
|
||||||
|
messageEncoder
|
||||||
|
.encodeRequestMessage(groupId, timestamp, null, author, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectCreateMessage(BdfList bodyList) throws FormatException {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clientHelper).toByteArray(bodyList);
|
||||||
|
will(returnValue(body));
|
||||||
|
oneOf(messageFactory).createMessage(groupId, timestamp, body);
|
||||||
|
will(returnValue(message));
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ import org.briarproject.briar.blog.BlogModule;
|
|||||||
import org.briarproject.briar.client.BriarClientModule;
|
import org.briarproject.briar.client.BriarClientModule;
|
||||||
import org.briarproject.briar.forum.ForumModule;
|
import org.briarproject.briar.forum.ForumModule;
|
||||||
import org.briarproject.briar.introduction.IntroductionModule;
|
import org.briarproject.briar.introduction.IntroductionModule;
|
||||||
|
import org.briarproject.briar.introduction2.MessageEncoderParserIntegrationTest;
|
||||||
import org.briarproject.briar.messaging.MessagingModule;
|
import org.briarproject.briar.messaging.MessagingModule;
|
||||||
import org.briarproject.briar.privategroup.PrivateGroupModule;
|
import org.briarproject.briar.privategroup.PrivateGroupModule;
|
||||||
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
|
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
|
||||||
@@ -76,6 +77,8 @@ public interface BriarIntegrationTestComponent {
|
|||||||
|
|
||||||
void inject(BriarIntegrationTest<BriarIntegrationTestComponent> init);
|
void inject(BriarIntegrationTest<BriarIntegrationTestComponent> init);
|
||||||
|
|
||||||
|
void inject(MessageEncoderParserIntegrationTest init);
|
||||||
|
|
||||||
void inject(BlogModule.EagerSingletons init);
|
void inject(BlogModule.EagerSingletons init);
|
||||||
|
|
||||||
void inject(ContactModule.EagerSingletons init);
|
void inject(ContactModule.EagerSingletons init);
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
package org.briarproject.briar.test;
|
package org.briarproject.briar.test;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
|
import org.briarproject.bramble.api.identity.AuthorFactory;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.briar.api.client.MessageTracker;
|
import org.briarproject.briar.api.client.MessageTracker;
|
||||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
public class BriarTestUtils {
|
public class BriarTestUtils {
|
||||||
@@ -25,4 +30,9 @@ public class BriarTestUtils {
|
|||||||
assertEquals(unreadCount, c1.getUnreadCount());
|
assertEquals(unreadCount, c1.getUnreadCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Author getRealAuthor(AuthorFactory authorFactory) {
|
||||||
|
return authorFactory.createAuthor(getRandomString(5),
|
||||||
|
getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user